linux信号signal处理机制(三)

前面两节已经介绍了有关信号的大部分知 识。这一节我们来了解一下这些系统调用。其中,系统调用signal是进程用来设定某个信号的处理方法,系统调用kill是用来发送信号给指定进程的。这 两个调用可以形成信号的基本操作。后两个调用pause和alarm是通过信号实现的进程暂停和定时器,调用alarm是通过信号通知进程定时器到时。所 以在这里,我们还要介绍这两个调用。

        1、signal 系统调用

        系统调用signal用来设定某个信号的处理方法。该调用声明的格式如下:
        void (*signal(int signum, void (*handler)(int)))(int);
        在使用该调用的进程中加入以下头文件:
        #include <signal.h>

        上述声明格式比较复杂,如果不清楚如何使用,也可以通过下面这种类型定义的格式来使用(POSIX的定义):
        typedef void (*sighandler_t)(int);
        sighandler_t signal(int signum, sighandler_t handler);
        但这种格式在不同的系统中有不同的类型定义,所以要使用这种格式,最好还是参考一下联机手册。

        在调用中,参数signum指出要设置处理方法的信号。第二个参数handler是一个处理函数,或者是
        SIG_IGN:忽略参数signum所指的信号。
        SIG_DFL:恢复参数signum所指信号的处理方法为默认值。

        传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。系统调用signal返回值是指定信号signum前一次的处理例程或者错误时返回错误代码SIG_ERR。下面来看一个简单的例子:

C代码
  1. #include <signal.h>  
  2. #include <unistd.h>  
  3. #include <stdio.h>  
  4. void sigroutine(int dunno) { /* 信号处理例程,其中dunno将会得到信号的值 */  
  5. switch (dunno) {  
  6. case 1:  
  7. printf("Get a signal -- SIGHUP ");  
  8. break;  
  9. case 2:  
  10. printf("Get a signal -- SIGINT ");  
  11. break;  
  12. case 3:  
  13. printf("Get a signal -- SIGQUIT ");  
  14. break;  
  15. }  
  16. return;  
  17. }  
  18.   
  19. int main() {  
  20. printf("process id is %d ",getpid());  
  21. signal(SIGHUP, sigroutine); //* 下面设置三个信号的处理方法  
  22. signal(SIGINT, sigroutine);  
  23. signal(SIGQUIT, sigroutine);  
  24. for (;;) ;  
  25. }  
  1. #include <signal.h>  
  2. #include <unistd.h>  
  3. #include <stdio.h>  
  4. void sigroutine(int dunno) { /* 信号处理例程,其中dunno将会得到信号的值 */  
  5. switch (dunno) {  
  6. case 1:  
  7. printf("Get a signal -- SIGHUP ");  
  8. break;  
  9. case 2:  
  10. printf("Get a signal -- SIGINT ");  
  11. break;  
  12. case 3:  
  13. printf("Get a signal -- SIGQUIT ");  
  14. break;  
  15. }  
  16. return;  
  17. }  
  18.   
  19. int main() {  
  20. printf("process id is %d ",getpid());  
  21. signal(SIGHUP, sigroutine); //* 下面设置三个信号的处理方法  
  22. signal(SIGINT, sigroutine);  
  23. signal(SIGQUIT, sigroutine);  
  24. for (;;) ;  
  25. }  


        其中信号SIGINT由按下Ctrl-C发出,信号SIGQUIT由按下Ctrl-发出。该程序执行的结果如下:

        localhost:~$ ./sig_test
        process id is 463
        Get a signal -SIGINT //按下Ctrl-C得到的结果
        Get a signal -SIGQUIT //按下Ctrl-得到的结果
        //按下Ctrl-z将进程置于后台
        [1]+ Stopped ./sig_test
        localhost:~$ bg
        [1]+ ./sig_test &
        localhost:~$ kill -HUP 463 //向进程发送SIGHUP信号
        localhost:~$ Get a signal – SIGHUP
        kill -9 463 //向进程发送SIGKILL信号,终止进程
        localhost:~$

        2、kill 系统调用

        系统调用kill用来向进程发送一个信号。该调用声明的格式如下:
        int kill(pid_t pid, int sig);
        在使用该调用的进程中加入以下头文件:
        #include <sys/types.h>
        #include <signal.h>

        该 系统调用可以用来向任何进程或进程组发送任何信号。如果参数pid是正数,那么该调用将信号sig发送到进程号为pid的进程。如果pid等于0,那么信 号sig将发送给当前进程所属进程组里的所有进程。如果参数pid等于-1,信号sig将发送给除了进程1和自身以外的所有进程。如果参数pid小于- 1,信号sig将发送给属于进程组-pid的所有进程。如果参数sig为0,将不发送信号。该调用执行成功时,返回值为0;错误时,返回-1,并设置相应 的错误代码errno。下面是一些可能返回的错误代码:
        EINVAL:指定的信号sig无效。
        ESRCH:参数pid指定的进程或进程组不存在。注意,在进程表项中存在的进程,可能是一个还没有被wait收回,但已经终止执行的僵死进程。
        EPERM: 进程没有权力将这个信号发送到指定接收信号的进程。因为,一个进程被允许将信号发送到进程pid时,必须拥有root权力,或者是发出调用的进程的UID 或EUID与指定接收的进程的UID或保存用户ID(savedset-user-ID)相同。如果参数pid小于-1,即该信号发送给一个组,则该错误 表示组中有成员进程不能接收该信号。

        3、pause系统调用

        系统调用pause的作用是等待一个信号。该调用的声明格式如下:
        int pause(void);
        在使用该调用的进程中加入以下头文件:
        #include <unistd.h>

        该调用使得发出调用的进程进入睡眠,直到接收到一个信号为止。该调用总是返回-1,并设置错误代码为EINTR(接收到一个信号)。下面是一个简单的范例:

C代码
  1.  #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <signal.h>  
  4. void sigroutine(int unused) {  
  5. printf("Catch a signal SIGINT ");  
  6. }  
  7.   
  8. int main() {  
  9. signal(SIGINT, sigroutine);  
  10. pause();  
  11. printf("receive a signal ");  
  12. }  
  1.  #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <signal.h>  
  4. void sigroutine(int unused) {  
  5. printf("Catch a signal SIGINT ");  
  6. }  
  7.   
  8. int main() {  
  9. signal(SIGINT, sigroutine);  
  10. pause();  
  11. printf("receive a signal ");  
  12. }  


        在这个例子中,程序开始执行,就象进入了死循环一样,这是因为进程正在等待信号,当我们按下Ctrl-C时,信号被捕捉,并且使得pause退出等待状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值