7.2.3 系统调用

   除了signal()系统调用,Linux还提供关于信号的系统调用如下:

 

       调用原型                                       功能

  int sigaction(sig,&handler,&oldhandler)      定义对信号的处理操作

  int sigreturn(&context)                             从信号返回

  int sigprocmask(int how, sigset_t *mask,   检查或修改信号屏蔽

               sigset_t *old)             

  int sigpending(sigset_t mask)               替换信号掩码并使进程挂起

  int kill(pid_t pid, int sig)                      发送信号到进程

  long alarm(long secs)                  设置事件闹钟

  int pause(void)                        将调用进程挂起直到下一个进程

 

    其中sigset_t定义为:

 

typedef unsigned long sigset_t;       /* 至少32*/

下面介绍几个典型的系统调用。

1. kill系统调用

从前面所叙述的可以看到,一个进程接收到的信号,或者是由异常的错误产生(如浮点异常),或者是用户在键盘上用中断和退出信号干涉而产生,那么,一个进程能否给另一个进程发送信号?回答是肯定的,但发送者进程必需有适当的权限。Kill()系统调用可以完成此任务:

 

int kill(pid_t pig, int sig)

 

参数sig规定发送哪一个信号,参数pid(进程标识号)规定把信号发送到何处,pig各种不同值具有下列意义:

 

pid>0    把信号sig发送给进程标识号为pid的进程。

pid=0    假设调用kill()的进程其组标识号为p, 则把信号sig发送给与

          p相等的其它所有进程。

pid=-1   Linux规定把信号sig发送给系统中除去init进程和调用者

         进程以外的所有进程。

pid<-1   把信号发送给进程组-pid中的所有进程。

 

    为了用kill()发送信号,调用进程的有效用户ID必须是root,或者必须和接收进程的实际或有效用户ID相同。

 

2.  pause()alarm()系统调用

当一个进程需要等待另一个进程完成某项操作时,它将执行pause()调用,当这项操作已完成时,另一个进程可以发送一个预约的信号给这一暂停的进程,它将强迫pause()返回,并且允许收到信号的进程恢复执行,知道它正在等待的事件现在已经出现。

对于许多实际应用,需要在一段指定时间后,中断进程的原有操作,以进行某种其它的处理,例如在不可靠的通信线路上重传一个丢失的包,为了处理此类情况,系统提供了alarm()系统调用。每个进程都有一个闹钟计时器与之相联,在经过预先设置的时间后,进程可以用它来给自己发送SIGALARM信号。Alarm()调用只取一个参数secs,它是在闹钟关闭之前所经过的秒数。如果传递一个0值给alarm(),这将关闭任何当前正在运行的闹钟计时器。

Alarm()返回值是以前的闹钟计时器值,如果当前没有设置任何闹钟计时器,这将是零,或者是当作出该调用时,闹钟的剩余时间。

某些情况下,进程在信号到达之前不要做任何操作,例如一个测验阅读和理解速度的CAI系统,它先在屏幕上显示一些课文,然后调用alarm()设定在30s后向自己发送一个信号,以激活程序进行一些处理。当学生阅读课文时,程序无需执行任何操作,它可以采用的一种方法是执行空操作循环以等待时间到,但假如此时系统中还有其它进程运行,这将浪费CPU的时间,好的方法是使用pause()系统调用,它将挂起调用进程直到信号到来,这段时间里别的进程可以使用CPU