(莱昂氏unix源代码分析导读-24)signal(上)

                                                                          by cszhao1980

signal更确切的称呼应该是soft interruption,顾名思义,就是一种能够通过软件手段达到

类似interruption目的的方法。

 

Unix最多支持NSIG20)种软中断,进程的u中有u.signal[NSIG]数组,记录每种软中

断的处理方法。

u_signaln〕的值

当#n中断发生时

此进程将终止自身

奇数,非0

忽略此软件中断

偶数,非0

该值为用户空间中一过程的起始地址,应立即执行该过程

 

第#4 8系统调用ssig(),其主要功能就是设置数组“u_signal”,这个sys call有两个参数:

1asignal type0 ~ NSIG

2u_signal(a)应该被设置的值

 

3614: ssig()

3615: {

3616:    register a;

3617:

3618:    a = u.u_arg[0];

3619:    if(a<=0 || a>=NSIG || a ==SIGKIL) {

3620:       u.u_error = EINVAL;

3621:       return;

3622:    }

3623:    u.u_ar0[R0] = u.u_signal[a];    /返回old

3624:    u.u_signal[a] = u.u_arg[1];

3625:    if(u.u_procp->p_sig == a)      /clear以前的signal

3626:       u.u_procp->p_sig = 0;

3627: }

从代码可知,SIGKIL的处理是不可更改的——而其被初始化为0,即一旦收到此

信号,进程就会终止。

 

而进程的proc结构中的“psig”项,记录进程目前收到的signal,将其值设置为某一

中断类型编号(亦即在1NSIG1之间的一个值),就是对该进程造成一个软中断。

psignal(p, sig)就是用来向进程发送signal的函数,它有两个参数:

 

参数1p——执行进程的进程表项

参数2sig——向该进程发送何种signal

 

3963: psignal(p, sig)

3964: int *p;

3965: {

3966:    register *rp;

3967:

3968:    if(sig >= NSIG)

3969:       return;

3970:    rp = p;

3971:    if(rp->p_sig != SIGKIL)

3972:       rp->p_sig = sig;

3973:    if(rp->p_stat > PUSER)   /莱昂指出,这里的“p_stat”应为“p_prio

3974:       rp->p_stat = PUSER;    /  …

3975:    if(rp->p_stat == SWAIT)

3976:       setrun(rp);

3977: }

 

从程序可知:

(1)         一般情况下,连续向进程发送多个signal时,后者会覆盖前者;

(2)         SIGKIL例外,一旦发送KILL信号,就不能被覆盖;

(3)         处于SWAIT状态的进程,会被信号叫醒。

要想理解莱昂对3975行的注释,需要翻回到sleep2066)——当以正的priority

调用sleep时,会将进程状态设置为“SWAIT”,意思为可被信号唤醒(也可理解

为等待信号,即非内核事件)。

 

相关的程序还有

13949: signal(tp, sig)

为每个p_ttyp == tp(即终端==tp)的进程发送sig信号;

 

2sys call kill

     有两个参数:

(1)         r0传进来,为process id

(2)         跟在trap指令后(会存放在u_arg[0]中),为signaltype

    其作用是向指定进程发送指定信号。

 

     需要注意的是:

(1)    不能向当前进程(本进程)发信号;

(2)    当输入的process id0时,表示要向具有同一控制终端(p_ttyp)的

              所有进程(不包括#0#1进程)发信号;

(3)    会进行权限检查——当前进程要末为超级用户(u_uid==0),要末与被

             发信号的进程的u_uid相同。之所以仅有此函数进行权限检查,是因为此

            函数为unix开放给用户的系统调用,而其他几个函数都是内核态“内部”

            函数,故无需进行权限的检查。

 

博客地址:http://blog.csdn.net/cszhao1980

 博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html


你可能感兴趣的:((莱昂氏unix源代码分析导读-24)signal(上))