深入理解Linux内核--信号

2023-05-16

信号用于在用户态进程间通信。内核也用信号通知进程系统所发生的事情。

1、信号的作用

信号(signal)是很短的消息,可以被发送到一个进程或一组进程。发送给进程的唯一信息通常是一个数,以此来标识信号。

使用信号的两个主要目的:

让进程知道已经发生了一个特定的事件。

强迫进程执行它自己 代码 中的信号处理 程序

当然,这两个目的不是互斥的,因为进程经常通过执行一个特定的例程来对某一事件作出反应。

常规信号:前31个

实时信号:32-64

实时信号与常规信号有很大的不同,因为它们必须排队以便发送的多个信号能被接收到。另一方面,同种类型的常规信号并不排队;如果一个常规信号被连续发送多次,那么,只有其中的一个发送到接收进程。尽管Linux内核并不使用实时信号,它还是通过几个特定的系统调用完全实现了POSIX标准。

许多系统调用允许程序员发送信号,并决定他们的进程如何响应所接收的信号。

信号的一个重要特点是它们可以随时被发送给状态经常不可预知的进程。发送给非运行进程的信号必须由内核保存,直到进程恢复执行。

阻塞一个信号要求信号的传递拖延,直到随后解除阻塞,这使得信号产生一段时间之后才能对其传递这一问题变得更加严重。

内核区分信号传递的两个不同阶段:

信号产生:

内核更新目标进程的数据结构以表示一个新信号已被发送。

信号传递:

内核强迫目标进程通过以下方式对信号做出反应:或改变目标进程的执行状态,或开始执行一个特定的信号处理程序,或两者都是。

每个所产生的信号至多被传递一次。信号是可消费资源:一旦它们已传递出去,进程描述符中有关这个信号的所有信息都被取消。

已经产生但还没有传递的信号称为挂起信号(pendingsignal)。任何时候,一个进程仅存在给定类型的一个挂起信号,同一进程同种类型的其他信号不被排队,只被简单地丢弃。但是,实时信号是不同的:同种类型的挂起信号可以有好几个。

信号可以保留不可预知的挂起时间,必须考虑的因素:

信号通常只被当前正运行的进程传递

给定类型的信号可以由进程选择性地阻塞

当进程执行一个信号处理程序的函数时,通常“屏蔽”相应的信号,即自动阻塞这个信号到处理程序结束。因此,所处理的信号的另一次出现不能中断信号处理程序,所以,信号处理函数不必是可重入的。

内核实现:

记住每个进程阻塞哪些信号

当从内核态切换到用户态时,对任何一个进程都要检查是否有一个信号已到达。这几乎在每个定时中断时都发生

确定是否可以忽略信号。这个发生在下列所有的条件都满足时:

目标进程没有被另一个进程跟踪

信号没有被目标进程阻塞

信号被目标进程忽略

处理这样的信号,即信号可能在进程运行期间的任一时刻请求把进程切换到一个信号处理函数,并在这个函数返回以后恢复原来执行的上下文。 

[1]传递信号之前所执行的操作

进程以三种方式对一个信号做出应答:

(1)显示地忽略信号

(2)执行与信号相关的缺省操作。由内核预定义的缺省操作取决于信号的类型,下列类型:

Terminate:进程被终止(杀死)

Dump:进程被终止(杀死)

Ignore:信号被忽略

Stop:进程被停止,即把进程置为TASK_STOPPED状态

Continue:如果进程被停止,就把它置为TASK_RUNNING状态

(3)通过调用相应的信号处理函数捕获信号

注意,被对一个信号的阻塞和忽略是不同的:只要信号被阻塞,它就不被传递;只有在信号解除阻塞后才传递它。而一个被忽略的信号总是被传递,只是没有进一步的操作。

SIGKILL和SIGSTOP信号不可以被显示地忽略、捕获或阻塞,因此,通常必须执行它们的缺省操作。因此,SIGKILL和SIGSTOP允许具有适当特权的用户分别终止并停止任何进程,不管进程执行时采取怎样的防御措施。

如果信号的传递会引起内核杀死一个进程,难么这个信号对该进程就是致命的。SIGKILL信号总是致命的;而且,缺省操作为Terminate的每个信号,以及不被进程捕获的信号对该进程也是致命的。注意,如果一个被进程所捕获的信号,其对应的信号处理函数终止了这个进程,那么这个信号就不是致命的,因为进程自己选择了终止,而不是被内核杀死。

[2]POSIX信号和多线程应用


POSIX1003.1标准对多线程应用的信号处理有一些严格的要求:

信号处理程序必须在多线程应用的所有线程之间共享;不过,每个线程必须有自己的挂起信号掩码和阻塞信号掩码。

POSIX库函数kill()和sigqueue()必须向所有的多线程应用而不是某个特殊的线程发送信号。所有由内核产生的信号同样如此。

每个发送给多线程应用的信号仅传送给一个线程,这个线程是由内核在从不会阻塞该信号的线程中随意选择出来的

如果向多线程应用发送了一个致命的信号,那么内核将杀死该应用的所有线程,而不仅仅是杀死接收信号的那个线程。

Linux内核2.6把多线程应用实现为一组属于同一个线程组的轻量级进程。

如果一个挂起信号被发送给了某个特定进程,那么这个信号是私有的;如果被发送给了整个线程组,它就是共享的

[3]与信号相关的数据结构

对系统中的每个进程来说,内核必须跟踪什么信号当前正在挂起或被屏蔽,以及每个线程组是如何处理所有信号的。为了完成这些操作,内核使用几个处理器描述符可存取的数据结构:参考图11-1***

深入理解Linux内核--信号(阅读笔记)(原创)

(1)信号描述符和信号处理程序描述符

进程描述符signal字段指向信号描述符(signaldescriptor)--一个signal_struct类型的结构,用来跟踪共享挂起信号。

除了信号描述符以外,每个进程还引用一个信号处理程序描述符(signal handler deseriplor),它是一个sighand_struct类型的结构,用来描述每个信号必须怎样被线程组处理

(2)sigaction数据结构

一些体系结构把特性赋给仅对内核可见的信号。因此,信号的特性存放在k_sigaction结构中,k_sigaciton结构既包含对用户态进程所隐藏的特性,也包含大家熟悉的sigaction结构,该结构保存了用户态进程能看见的所有特性。实际上,在80x86平台上,信号的所有特性对用户态的进程都是可见的。因此,k_sigaction结构只不过简化为类型为sigaction的单个sa结构。字段:

sa_handler:指定要执行操作的类型。它的值可以是指向信号处理程序的一个指针,SIG_DFL(即值0,指定执行缺省操作),或者SIG_IGN(即值1,指定忽略信号)

sa_flags:是一个标志集,指定必须怎样处理信号。

sa_mask:类型为sigset_t的变量,指定当运行信号处理程序时要屏蔽的信号

(3)挂起信号队列

有几个系统调用能产生发送给整个线程组的信号,如kill()和rt_sigqueueinfo(),而其他的一些则产生发送给特定进程的信号,如tkill()和tgkill()

为了跟踪当前的挂起信号是什么,内核把两个挂起信号队列与每个进程相关联:

共享挂起信号队列,它位于信号描述符的shared_pending字段,存放整个线程组的挂起信号

私有挂起信号队列,它位于进程描述符的pending字段,存放特定进程的挂起信号

[4]在信号数据结构上的操作:参考p429-430的函数列表




2、产生信号

很多内核函数都会产生信号:它们完成信号处理第一步的工作,即根据需要更新一个或多个进程的描述符。它们不直接执行第二步的信号传递操作,而是可能根据信号的类型和目标进程的状态唤醒一些进程,并促使这些进程接收信号。

当发送给进程一个信号时,这个信号可能来自内核,也可能来自另一个进程。内核通过对如表11-9所示的某个函数进行调用而产生信号

当一个信号被发往整个线程组时,这个信号可能来自内核,也可能来自另一个进程。内核通过对如表11-10所示的某个函数进行调用而产生信号

[1]specific_send_sig_info()函数:向指定进程发送信号,步骤:参考p433

[2]send_signal()函数:在挂起信号队列中插入一个新元素,步骤:参考p434

[3]group_send_sig_info()函数:向整个线程组发送信号,步骤:参考p435-437



3、传递信号

为确保进程的挂起信号得到处理内核所执行的操作。

内核在允许进程恢复用户态下的执行之前,检查进程TIF_SIGPENDING标志的值。每当内核处理完一个中断或异常时,就检查是否存在挂起信号

为了处理非阻塞的挂起信号,内核调用do_signal()函数

通常只是在CPU要返回到用户态时才调用do_signal()函数

do_signal()函数的核心由重复调用dequeue_signal()函数的循环组成,直到在私有挂起信号队列和共享挂起信号队列中都没有非阻塞的挂起信号时,循环才结束。

dequeue_singal()函数首先考虑私有挂起信号队列中的所有信号,并从最低编号的挂起信号开始。然后考虑共享队列中的信号。它更新数据结构以表示信号不再是挂起的,并返回它的编号。

do_signal()函数如何处理每一个挂起的信号,其编号由dequeue_signal()返回。首先,它检查current接收进程是否正受到其他一些进程的监控;在肯定的情况下,do_signal()调用do_notify_parent_cldstop()和schedule()让监控进程知道进程的信号处理。

然后,do_signal()把要处理信号的k_sigaction数据结构的地址赋给局部变量ka;根据ka的内容可以执行三种操作:忽略信号、执行缺省操作或执行信号处理程序。如果显式忽略被传递的信号,那么do_signal()函数仅仅继续执行循环,并由此考虑另一个挂起信号

[1]执行信号的缺省操作

如果ka->sa.sa_handler等于SIG_DFL,do_signal()就必须执行信号的缺省操作。唯一的例外是当接收进程是init时,这个信号被丢弃。

SIGSTOP与其他信号的差异比较微妙:SIGSTOP总是停止线程组,而其他信号只停止不在“孤儿进程组”中的线程组。POSIX标准规定,只要进程组中一个进程有父进程,尽管进程处于不同的进程组中但在同一个会话中,那么这个进程组就不是孤儿。因此,如果父进程死亡,但启动该进程的用户并登录在线,那么该进程组就不是一个孤儿。

缺省操作为Dump的信号可以在进程的工作目录中创建一个“转储”文件,这个文件列出进程地址空间和CPU寄存器的全部内容

[2]捕获信号


如果信号有一个专门的处理程序,do_signal()就函数必须强迫该处理程序执行。这是通过调用handle_signal()进行的

注意do_signal()的处理了一个单独的信号后怎样返回。直到下一次调用do_signal()时才考虑其他挂起的信号。这种方式确保了实时信号将以适当的顺序得到处理

执行一个信号处理程序是件相当复杂的任务,因此在用户态和内核态之间切换时需要谨慎地处理栈中的内容。我们将正确地解释这里所承担的任务

信号处理程序是用户态进程所定义的函数,并包含在用户态的代码段中。handle_signal()函数运行在内核态,而信号处理程序运行在用户态,这就意味着在当前进程恢复“正常”执行之前,它必须首先执行用户态的信号处理程序。此外,当内核打算恢复进程的正常执行时,内核态堆栈不再包含被中断程序的硬件上下文,因此每当从内核态向用户态转换时,内核态堆栈都被清空。而另外一个复杂性是因为信号处理程序可以调用系统调用,在这种情况下,执行了系统调用的服务例程以后,控制权必须返回到信号处理程序而不是到被中断程序的正常代码流。

linux所采用的解决方法是把保存在内核态堆栈中的硬件上下文拷贝到当前进程的用户态堆栈中。用户态堆栈也以这样的方式被修改,即当信号处理程序终止时,自动调用sigreturn()系统调用把这个硬件上下文拷贝回到内核态堆栈中,并恢复用户态堆栈中原来的内容。

图11-2说明了有关捕捉一个信号的函数的执行流:

一个非阻塞的信号发送给一个进程。当中断或异常发生时,进程切换到内核态。

正要返回到用户态前,内核执行do_signal()函数,

这个函数又依次处理信号(通过调用handle_signal())和建立用户态堆栈(通过调用setup_frame()或setup_rt_frame())

当进程又切换到用户态时,因为信号处理程序的起始地址被强制放进程序计数器中,因此开始执行信号处理程序。

当处理程序终止时,setup_frame()或setup_rt_frame()函数放在用户态堆栈中的返回代码就被执行。这个代码调用sigreturn()或rt_sigrenturn()系统调用,相应的服务例程把正常程序的用户态堆栈硬件上下文拷贝到内核堆栈,并把用户态堆栈恢复到它原来的状态(通过调用restore_sigcongtext()).当这个系统调用结束时,普通进程就因此能恢复自己的执行

图:11-2***

深入理解Linux内核--信号(阅读笔记)(原创)



(1)建立帧

为了适当地建立进程的用户态堆栈,handle_signal()函数或者调用setup_frame()或者调用setup_rt_frame()

setup_frame()函数把一个叫做帧(frame)的数据结构推进用户态堆栈中,这个帧含有处理信号所需要的信息,并确保正确返回到handle_signal()函数

setup_frame()函数把保存在内核态堆栈的段寄存器内容重新设置成它们的缺省值以后才结束。现在,信号处理程序所有需的信息就在用户态堆栈的顶部。

(2)检查信号标志

建立了用户态堆栈以后,handle_signal()函数检查与信号相关的标志值。如果信号没有设置SA_NODEFER标志,在sigaction表中sa_make字段对应的信号就必须在信号处理程序执行期间被阻塞,然后,handle_signal()返回到do_signal(),do_signal()也立即返回

(3)开始执行信号处理程序

do_signal()返回时,当前进程恢复它在用户态的执行。由于如前所述setup_frame()的准备,eip寄存器指向信号处理程序的第一条指令,而esp指向已推进用户态堆栈顶的帧的第一个内存单元。因此,信号处理程序被执行。

(4)终止信号处理程序

信号处理程序结束时,返回栈顶地址,该地址指向帧的pretcode字段所引用的vsyscall页中的代码。因此,信号编号(即帧的sig字段)被从栈中丢弃,然后调用sigreturn()系统调用

sys_rt_sigreturn()服务例程把来自扩展帧的进程硬件上下文拷贝到内核态堆栈,并通过从用户态堆栈删除扩展帧以恢复用户态堆栈原来的内容。

(5)系统调用的重新执行

内核并不总是能立即满足系统调用发出的请求,在这种情况发生时,把发出系统调用的进程置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE状态

如果进程处于TASK_INTERRUPTIBLE状态,并且某个进程向它发送了一个信号,那么,内核不完成系统调用就把进程置成TASK_RUNNING状态。当切换回用户态时信号被传递给进程。当这种情况发生时,系统调用服务例程没有完成它的工作,但返回EINTR,ERESTARTNOHAND,ERESTART_RESTARTBLOCK,ERESTARTSYS或ERESTARTNOINTR错误码。实际上,这种情况下用户态进程获得的唯一错误码是EINTR,这个错误码表示系统调用还没有执行完。内核内部使用剩余的错误码来指定信号处理程序结束后是否自动重新执行系统调用。

与未完成的系统调用相关的出错码及这些出错码对信号三种可能的操作产生的影响。

Terminate:不会自动重新执行系统调用

Reexecut:内核强迫用户态进程把系统调用号重新装入eax寄存器,并重新执行int$0x80指令或sysenter指令。进程意识不到这种重新执行,因此出错码也不传递给进程。

Depends:只有被传递信号的SA_RESTART标志被设置,才重新执行系统调用;否则系统调用-EINTER出错码结束

当传递信号时,内核在试图重新执行一个系统调用前必须确定进程确实发出过这个系统调用。这就是regs硬件上下文的orig_eaz字段起重要作用之处 

a、重新执行被未捕获信号中断的系统调用

如果信号被显式地忽略,或者如果它的缺省操作已被强制执行,do_signal()就分析系统调用的出错码,并如表11-11中所说明的那样决定是否重新自动执行未完成的系统调用。如果必须重新开始执行系统调用,那么do_signal()就修改regs硬件上下文,以便在进程返回到用户态时,eip指向int$0x80指令或sysenter指令,且eax包含系统调用号

b、为所捕获的信号重新执行系统调用

如果信号被捕获,那么handle_signal()分析出错码,也可能分析sigaction表的SA_RESTART标志来决定是否必须重新执行未完成的系统调用

如果系统调用必须被重新开始执行,handle_signal()就与do_signal()完全一样地继续执行;否则,它向用户态进程返回一个出错码-ENTR

4、与信号处理相关的系统调用

在用户态运行的进程可以发送和接收信号。这意味着必须定义一组系统调用用来完成这些操作。遗憾的是,由于历史的原因,已经存在几个具有相同功能的系统调用,因此,其中一些系统调用从未被调用。例如:系统调用sys_sigaction()和sys_rt_sigaciton()几乎是相同的,因此C库中封装函数sigaction()调用sys_rt_sigaction()而不是sys_sigaction()。

[1]kill()系统调用

一般用kill(pid,sig)系统调用向普通进程或多线程应用发送信号,其相应的服务例程是sys_kill()函数

kill()系统调用能发送任何信号,即使编号在32-64之间的实时信号。kill()系统调用不能确保把一个新的元素加入到目标进程的挂起信号队列,因此,挂起信号的多个实例可能被丢失。实时信号应该当通过rt_siggueueinfo()系统调用进行发送

[2]tkill和gkill()系统调用


tkill()和tgkill()系统调用向线程组中的指定进程发送信号

[3]改变信号的操作

sigaction(sig,act,oact)系统调用允许用户为信号指定一个操作。当然,如果没有自定义的信号操作,那么内核执行与传递的信号相关的缺省操作

[4]检查挂起的阻塞信号

sigpending()系统调用允许进程检查挂起的阻塞信号的集合,也就是说,检查信号被阻塞时已产生的那些信号

[5]修改阻塞信号的集合

sigprocmask()系统调用允许进程修改阻塞信号的集合。这个系统调用只应用于常规信号

[6]挂起进程

sigsuspend()系统调用把进程置为TASK_INTERRUPTIBLE状态,当然这是把mask参数指向的位掩码数组所指定的标准信号阻塞以后设置的。只有当一个非忽略、非阻塞的信号发送到进程以后,进程才被唤醒

[7]实时信号的系统调用

系统调用只应用到标准信号,因此,必须引入另外的系统调用来允许用户态进程处理实时信号

实时信号的几个系统调用:rt_sigaction()rt_sigpending()rt_sigprocmask()rt_sigsuspend()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解Linux内核--信号 的相关文章

  • 用另一个文件的标签为图表(ggplot2)中的标题添加下标

    在我的程序中 我有两个主要文件 第一个包含数据 第二个包含标签 或图形标题 文件总数1 数据 3 10000 3 32039232 1 0 0017290351 2 0 0002781092 3 10001 3 32101193 1 0 0
  • Linux shell 根据第二列对文件进行排序?

    我有一个这样的文件 FirstName FamilyName Address PhoneNumber 如何按 FamilyName 排序 如果这是 UNIX sort k 2 file txt 您可以使用多个 k用于对多列进行排序的标志 例
  • linux新手关于嵌入式linux设备驱动的问题

    最近在研究linux驱动 正如我读过的那些文章所说 设备驱动程序模块很可能会根据内核的需要自动加载 因此我想知道内核如何确定为特定设备 声卡 I2C spi 设备 等 我也无法彻底想象内核如何在启动时检测每个硬件设备 与嵌入式linux相关
  • Pthreads - 高内存使用率

    我正在用 C 编写一些东西 在 256Mb 系统上的 Linux 中创建大量 Pthread 我通常有 200Mb 的免费空间 当我使用少量线程运行该程序时 它可以工作 但是一旦我让它创建大约 100 个线程 它就会出现错误 因为系统内存不
  • 如何在 Vim 中突出显示 Bash 脚本?

    我的 Vim 编辑器自动突出显示 PHP 文件 vim file php HTML 文件 vim file html 等等 但是当我输入 vim file在里面写一个Bash脚本 它不会突出显示它 我如何告诉 Vim 将其突出显示为 Bas
  • 选择fasta文件中氨基酸超过300个且“C”出现至少4次的序列

    我有一个包含蛋白质序列的 fasta 文件 我想选择超过 300 个氨基酸且半胱氨酸 C 氨基酸出现超过 4 次的序列 我使用此命令来选择具有超过 300 个 aa 的序列 cat 72hDOWN fasta fasta bioawk c
  • 如何在Linux上用C/C++编写Web服务器[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在考虑在 Linux 平台上开发一个小型 阅读 初级 Web 服务器 但我不知道从哪里开始 我希望它能够做的是 监听特定端口 接受
  • 任何退出 bash 脚本但不退出终端的方法

    当我使用exitshell 脚本中的命令 该脚本将终止终端 提示符 有什么方法可以终止脚本然后停留在终端中吗 我的剧本run sh预计通过直接获取或从另一个脚本获取来执行 编辑 更具体地说 有两个脚本run2 sh as run sh ec
  • 如何在C(Linux utf8终端)中打印“盒子抽屉”Unicode字符?

    我正在尝试显示 方框图范围 2500 257F 中的 Unicode 字符 它应该是标准 utf8 Unicode 标准 版本 6 2 我根本做不到 我首先尝试使用旧的 ASCII 字符 但 Linux 终端以 utf8 显示 并且没有显示
  • Vagrant 遇到问题 - “404 - 未找到”

    我正在尝试使用 Vagrant 制作一个 LAMP 盒子 有人告诉我它使用起来非常简单 我对网络和虚拟机完全陌生 对 Linux Ubuntu 的经验也很少 我目前已尝试按照官方文档页面上的教程进行操作 http docs vagrantu
  • 为什么此 NASM 代码会打印我的环境变量?

    本学期我刚刚完成计算机体系结构课程 除其他外 我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它 今天 出于好奇 我开始在我的 Ubuntu 机器上摆弄 NASM 基本上只是将教程中的内容拼凑起来 并感受一下 NASM 与 MIP
  • Crontab 每 5 分钟一次 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我如何告诉 crontab 每 5 分钟运行一次 但从每小时的第二分钟开始 换句话说 我想在以下时间执行我的脚本minute 5 2 例如 我的脚本应
  • 使用 libusb 输出不正确

    我用libusb编写了一个程序 我怀疑输出是否正确 因为所有条目都显示相同的供应商和产品 ID 以下是代码 include
  • 如何并行执行4个shell脚本,我不能使用GNU并行?

    我有4个shell脚本dog sh bird sh cow sh和fox sh 每个文件使用 xargs 并行执行 4 个 wget 来派生一个单独的进程 现在我希望这些脚本本身能够并行执行 由于某些我不知道的可移植性原因 我无法使用 GN
  • 嵌入清单文件以要求具有 mingw32 的管理员执行级别

    我正在 ubuntu 下使用 i586 mingw32msvc 交叉编译应用程序 我很难理解如何嵌入清单文件以要求 mingw32 具有管理员执行级别 对于我的例子 我使用了这个hello c int main return 0 这个资源文
  • 为 Linux 编译 Objective-C 应用程序(API 覆盖范围)

    我可能在这里问一些奇怪的问题 但我不确定从哪里开始 问题是我正在考虑使用 Obj C 和 Foundation 类在 Mac 上编写一个命令行工具 但存在一个非常大的风险 那就是我希望能够为不同的 Linux 发行版编译它 以便将来作为服务
  • ssh 连接超时

    我无法在 git 中 ssh 到 github bitbucket 或 gitlab 我通常会收到以下错误消息 如何避免它 输出 ssh T email protected cdn cgi l email protection i ssh
  • 为什么 Linux 原始套接字的 RX 环大小限制为 4GB?

    背景 我试图mmap 我的原始套接字的 RX 环形缓冲区64 bitLinux 应用程序 我的环由 4096 个块组成 每个块大小为 1MB 总共 4GB 请注意 每个 1MB 块中可以有许多帧 如果您好奇 请参阅此文档了解背景信息 htt
  • 执行命令而不将其保留在历史记录中[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 在进行软件开发时 经常需要在命令行命令中包含机密信息 典型示例是将项目部署到服务器的凭据设置为环境变量 当我不想将某些命令存储在命令历史记
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu

随机推荐

  • k8s基础

    目录 一 基本介绍 二 组件介绍 1 master组件 2 node组件 三 核心概念 1 Pod 2 controller 3 service 四 单master搭建集群 1 系统初始化 2 安装k8s核心组件 3 容器化安装其他插件 4
  • 论文解读:Tips and Tricks for Visual Question Answering: Learnings from the 2017 Challenge

    这是关于VQA问题的第十二篇系列文章 这篇论文具有很强的指导意义 xff0c 本篇文章将介绍论文 xff1a 主要思想 xff1b 模型方法 xff1b 试验细节 有兴趣可以查看原文 xff1a Tips and Tricks for Vi
  • 总结2014——迷茫以及迷茫过后的坚持

    首先 xff0c 借用一句话和大家共勉 xff1a 少一些功利主义的追求 xff0c 多一些不为什么的坚持 xff01 xff01 不知不觉15年也快过了1个月了 xff0c 还是想着要为14年做一下总结 xff1a 记录一下自己的历程 今
  • 在faster rcnn中使用soft nms,faster rcnn的改进(一)

    1 背景介绍 我的项目是利用faster rcnn检测kiiti数据集 xff0c 用原始nms xff0c iters 61 10000的情况下 xff0c 得到的mAP 61 0 586 在改用soft nms后 xff0c 其他参数均
  • 建立DATAGUARD最大保护模式-测试手记

    建立DATAGUARD 最大保护模式 xff08 自写 xff09 xff08 备注 xff1a 本文档符合最大保护模式 xff0c 所有参数均为最大保护模式下适用 xff0c 其他模式不适用 xff09 1 主库 xff0c 启动归档 x
  • docker中安装ping | vim | nginx镜像

    docker安装nginx镜像并常见nginx容器 docker pull nginx latest docker run detach publish 9999 80 name nginxSer restart unless stoppe
  • 从操作系统内核解释电脑死机原理

    关于电脑死机的原因或者说原理 xff0c 即电脑为什么会死机 xff0c 电脑死机时计算机底层都发生了什么 一直不太明白 xff0c 在网上也查过相关的资料 xff0c 但是都没有找到自己想要的 网上谈的都是外部导致电脑死机的原因 xff0
  • 自己动手写操作系统第二章 pmtest1.asm分析

    34 pm inc 34 描述符 Usage Descrptor Base Limit Attr Base dd Limit dd Low 20 bits available Attr dw lower 4 bits of higher b
  • Linux 0.11 内核在内核空间创建进程时不使用写时复制技术

    在Linux0 12内核完全剖析中 xff0c 有这样一段话 34 由于创建新进程的过程是通过完全复制父进程代码段和数据段的方式实现 xff0c 因此在首次使用fork 创建新进程init 时 xff0c 为了确保新进程用户态栈中没有进程0
  • putty 登陆VMware虚拟机下的linux系统

    物理机的操作系统是Windows XP 虚拟机是在VMware上安装的CentOS xff0c 版本是5 6 因为每次登陆虚拟机鼠标会被限定在虚拟机的登陆界面 xff0c 所以想通过远程登陆工具来登陆虚拟机 虚拟机使用的网络是桥接模式 注意
  • Minx内核中scanf函数实现代码

    include lt stdio h gt include lt stdarg h gt include 34 loc incl h 34 int scanf const char format va list ap int retval
  • 双系统Linux下突然挂载Windows分区失败

    问题描述 xff0c 装了双系统之后 xff0c 一开始在Linux下还能访问Windows的分区 xff0c 可是突然之间就不能访问了 xff0c 错误信息如下 xff1a Error mounting dev sda1 at media
  • 对Linux0.11 "内核空间不使用写时复制机制" 本质理解

    一个页面被多个进程共享 xff0c 每当一个进程产生一次写保护 错误 xff0c 内核将给进程分配一个新的物理页面 xff0c 将共享页面的内容复制过来 xff0c 新的页面将设置为可读写 xff0c 而共享页面仍然是只读的 xff0c 只
  • Session && Cookie

  • windowsxp远程桌面端口号改变的位置

    HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Terminal Server Wds rdpwd Tds tcp 下的PortNamber HKEY LOCAL MACHINE SY
  • linux0.11 进程切换

    move to user mode是在堆栈中创建一个任务切换的假象 xff0c 用iret跳转到外层3 xff0c 这样cpu就会自动根据tr加载tss xff0c 并初始化各个寄存器运行任务0 所以 xff0c 任务0其实就是内核空间中的
  • Linux0.11 进程0

    Linux中1号进程是由0号进程来创建的 xff0c 因此必须要知道的是如何创建0号进程 xff0c 由于在创建进程时 xff0c 程序一直运行在内核态 xff0c 而进程运行在用户态 xff0c 因此创建0号进程涉及到特权级的变化 xff
  • Linux0.11 由进程睡眠函数sleep_on()中的堆栈变量tmp引发的思考 关于进程内核堆栈

    sleep on cpp view plaincopy 功能 xff1a 当前进程进入不可中断睡眠态 xff0c 挂起在等待队列上 参数 xff1a p 等待队列头 返回 xff1a xff08 无 xff09
  • 关于Windows系统环境变量的引用问题

    做Leap Motion开发时 xff0c 新建了LEAP SDK的系统环境变量 xff0c 按照官方SDK文档中说明的 xff0c 在工程中引入 LEAP SDK include 之前半年的时间里都是这样做的 xff0c 没有任何问题 x
  • 深入理解Linux内核--信号

    信号用于在用户态进程间通信 内核也用信号通知进程系统所发生的事情 1 信号的作用 信号 signal 是很短的消息 xff0c 可以被发送到一个进程或一组进程 发送给进程的唯一信息通常是一个数 xff0c 以此来标识信号 使用信号的两个主要