APUE学习--信号(2)

来源:互联网 发布:淘宝上怎么预约快递 编辑:程序博客网 时间:2024/05/20 05:28

这篇文章详细说明信号产生的方法。


终端按键、kill命令、硬件条件,这些是系统为我们定义好的,并且与编程无管,所以不多说了。

1、kill和raise函数

kill()函数,功能是向指定的进程或进程组发送指定的信号。

raise函数则是允许进程向自身发送信号。

[cpp] view plaincopy
  1. int kill(pid_t pid, int signo);  
  2. int raise(int signo)

pid就是指定发送的进程id,signo是发送的信号的编号。其中pid的取值意义和watpid()的pid参数的取值意义类似:

当pid>0时向进程号为pid的进程发送;

当pid==0,向当前进程组中的所有进程发送;

当pid==-1时,向所有有权限发送的进程发送;

当pid<0时,向指定pgid=-pid(进程组ID等于pid的绝对值)的进程组中的所有进程发送,而且发送进程具有向 其发送信号的权限;

这里要说下什么是发送权限,如果是root用户当然可以向任何的进程发送了,如果是普通用户,只能向进程uid也是该用户的进程发送。

和kill()类似的函数,还有raise()和abort()。

调用

raise(signo);

等价于调用

kill(getpid(),signo);

raise()函数是向当前进程发送信号,而abort()是向当前进程发送SIGABRT信号,这个信号是一个异常终止信号,该信号的处理动作必须是系统默认或者自定义处理函数且要求处理函数中必须退出进程或longjmp()跳转。

2、alarm和pause函数

我们再来看下一个比较有意思的信号,SIGALRM,这是一个闹钟信号。很多编程语言都提供了定时器的功能,在UNIX中就是通过这个信号完成的定时器功能,当闹钟到时时会自动向当前进程发送这个信号,将这个信号的处理动作设置为定时处理的事件,这样就可以实现定时器的功能。那如何实现启动闹钟呢?定时器一般分为两种,一种是单次启动,即当时钟到时候不会自动重启,我们使用的函数是alarm();另一种是循环启东的,即当时钟到时候会自动重启。

[cpp] view plaincopy

  1. #include<unistd.h>
    unsigned 
    int alarm(unsigned int seconds);  
  2. int pause(void);

pause函数使调用进程挂起直至捕捉到一个信号。

alarm函数非常的简单,seconds是设置的闹钟时间,单位是秒,返回值是设置前闹钟剩余的时间(也就是说闹钟未到时再次调用会删除原来的闹钟,即进程只有一个SIGALRM的闹钟),调用alarm(0)可以直接关闭闹钟,当seconds到时后会向当前进程发送SIGALRM信号。应用:定时做默写事情,输入超时等。需要提到的一点是,sleep()函数使用了SIGALRM信号,所以要避免alarm()和sleep()一起使用,sleep()的替换函数有usleep() nanosleep() select() poll()等。

[cpp] view plaincopy
  1. int getitimer(int which, struct itimerval *value);  
  2. int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);  
  3. struct itimerval {  
  4.       struct timeval it_interval; /* next value */  
  5.       struct timeval it_value;    /* current value */  
  6. };  
  7. struct timeval {  
  8.       long tv_sec;                /* seconds */  
  9.       long tv_usec;               /* microseconds */  
  10. };  
这个函数可以实现自动重启的功能,并且时间不再只精确到秒,而是微妙。getitimer()可以获取设置的时间,setitimer()用来设置闹钟时间,第一个参数是which,which的值可以是:ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF,分别表示进程的实际时间、用户态运行的时间、内核态运行的时间,对应发送的信号分别是SIGALRM、SIGVTALRM、SIGPROF。第二个参数和三个参数都是一个时间结构体,分别是要设置的闹钟时间,和设置前的闹钟时间(不像alarm()那样通过返回值)。时间结构体struct itimerval中有两个struct timeval的时间结构,分别表示本次闹钟的时间,和重启后的闹钟时间;而struct timeval时间结构中的两个成员分别是秒和微妙。
0 0