本文主机频道详细介绍了“linux信号的作用是什么”,内容详实,步骤清晰,细节得当。希望这篇文章《linux信号的作用是什么》能帮你解决疑惑。让我们按照主机频道的思路,一起学习新知识。
Linux信号用于通知进程一个特定的事件或者让进程执行一个特定的处理功能;信号就是信号,是Unix家族中一种古老的通信机制。信号可以来自终端的键盘字符输入,如control-C触发的SIGINIT,也可以来自硬件或软件相关的异常,如应用程序访问无效地址触发的SIGSEGV,定时器超时触发的SIGALARM等。
linux信号是用来做什么的?
Linux中的信号处理机制
信号是Unix家族中一种古老的通信机制,主要用于通知进程某个特定的事件,或者使进程执行某个特定的处理功能。之所以老,是因为它存在于第一代Unix系统中。
信号的发送信号可以来自终端的键盘字符输入,比如control-C触发的SIGINIT;它也可能来自硬件或软件相关的异常,如应用程序访问无效地址触发的SIGSEGV(分段故障)、定时器到期触发的SIGALARM等。这些信号由内核发送给进程。
一个进程收到的信号也可能来自其他进程。但并非所有进程都可以向任何其他进程发送信号。只有具有root权限的超级用户才能这样做。对于普通用户进程,只有属于同一个用户的进程才能发送信号。
进程能向内核发送信号吗?可以,但是内核线程不会响应,而且是灰色的,除非……你修改了内核代码。
信号通常被认为是一种异步机制,但是在Linux代码中,下列由异常引起的信号也被称为“同步”信号的:
# define synchronous _ mask \(sigsegv)| SIG mask(sigbus)| SIG mask(sigill)| \ SIG mask(sigtrap)| SIG mask(sigfpe)| SIG mask(sigsys))在这里,我们把接收信号的进程称为“目标进程”。传统的信令函数是kill(),看起来很吓人,感觉目标进程就要被“杀死”了。其实虽然所有的信号都是kill()发出的,但是真的要“kill & quot只有一小部分流程丢失。当然还有一个更强大更友好的名字sigqueue()。
让我们来看看两者的功能原型:
int kill(pid_t pid,int SIG);int sigqueue(pid_t pid,int sig,const union sigval值);Pid表示目标进程的PID。Linux中进程的pid是正的,那么如果参数PID的值为0或负,是否非法?不,事实上,0和负数在这里都有其他用途。Linux中有一个进程组的概念,代表进程的集合。在kill()中,参数pid是“0 & quot解释信号发送给当前进程所属的进程组中的所有进程,并且小于“-1 & quot;它向编号为-pid的进程组发送信号。
__kill_pgrp_info(sig,info,pid?find_vpid(-pid) : task_pgrp(当前));Pid是“-1 & quot;指示它被发送到除Init进程及其自身之外的所有进程,或者除其自身之外pid大于1的所有进程。
for _ each _ process(p){ if(task _ PID _ vnr(p)>1 & amp& amp!相同线程组(p,当前))...如果这里的pid是进程自己的PID,那么进程会向自己发送一个信号。为此,Linux还提供了一个更简洁的接口:raise()函数。
kill(getpid(),SIG)-& gt;Raise(sig)需要注意的是,在sigqueue()中,不能通过将参数pid的值设置为负数来向整个进程组发送信号。
Sig代表要发送的信号的编号。Linux中的信号号从1开始。参数sig的值为0怎么办?这里的0也很有用,sig是“0 & quot时间并不真正向目标进程(或进程组)发送信号,而是用来检测目标进程(或进程组)是否存在。
至于sigqueue添加的第三个参数,其定义如下:
union sigval { int sival _ intvoid _ _ user * sival _ ptr};传统信号没有传递消息的功能,sigval稍微扩展了信号的通信能力。例如,通信各方可以事先约定某些事件是特定的int值,即“sival _ int & quot它可以用来存储特定的int值,目标进程可以区分不同的事件,并相应地做出不同的响应。当然,这种方式传递的信息内容有限,不易扩展,不适合常规通信手段。
即使信号在进程间发送,也必须经过内核,可以理解为被内核“拦截”。
由于内核态和用户态的切换操作在不同的硬件架构下是不同的,而且有些信号,比如SIGCHLD和SIGSTOP也是架构相关的,所以Linux中信号机制的很多代码都放在架构相关的目录下,比如“/arch/arm/kernel/signal . c & quot;。
信号的相关信息由内核中的siginfo_t结构表示:
siginfo _ t { int si _ signoint si _ sicodeunion _ _ sifields _ sifields}si_signo是信号的编号,1到64的值都是合法的。
Si_sicode记录信号的来源。比如SI_USER表示信号由进程调用kill()发送,SI_QUEUE由进程调用sigqueue()发送,SI_KERNEL表示信号由内核生成。
_sifields对于不同的信号有不同的含义,通常包括信号发送进程的si_pid和发送进程所属用户的si_uid。对于sigqueue()发送的信号,还包括“sigval & quot参数携带的附加信息。
内核在截获一个进程发出的信号后,首先会做一系列的检查,比如信号的值是否合法,进程是否有权发出信号。如果检查通过,则调用copy_from_user()将信号的相关信息复制到siginfo_t结构中。
评论前必须登录!
注册