Linux环境编程之信号处理(二、kill()函数)

        前一篇有关信号的blog  Linux中信号处理(一)中已经大概的分析了信号基本处理方法,已经signal的解析和绑定处理函数;这一篇blog来复习下信号中常用到的几个函数;


        kill函数将信号发射给指定进程或者进程组,raise函数则把信号发送给自己;raise函数比较好理解,raise(int signo);kill(pid_t pid, int signo)函数就有点复杂了。其实这个函数很类似前面进程中涉及到的 waitpid()函数 Linux中进程控制函数:wait()和waitpid() ;下面着重来看下kill函数;

        int kill(pid_t pid, int signo);

        a、pid > 0   , 信号发送给pid进程;

        b、pid == 0, 把信号发送给本进程(自己)所在的进程组中所有进程,不包括系统进程;

        c、pid < 0   , 把信号发送给组id  为 -pid 的进程组中所有进程;

        d、pid == -1,把信号发送给所有进程,除系统进程外(9和19号进程有些信号不接受)


        前面复习了进程,所以这里特意挑出SIGCHLD信号来把信号和进程链接起来复习;当子进程退出时会发出一个SIGCHLD信号,这时候父进程可以调用wait函数来回收子进程的资源,避免子进程变成僵死进程;


        下面的代码是打印下wait函数得到的退出码;

#include"common.h"
 
 void print_status(int exitCode)
 {
     if (WIFEXITED(exitCode)) 
         printf("normal termination, exitCode:%d\n", WEXITSTATUS(exitCode));
     else if (WIFSIGNALED(exitCode)) 
         printf("abnormal termination, signal number:%d\n", WEXITSTATUS(exitCode));
     else if (WIFSTOPPED(exitCode))
         printf("child stopped, signal number = %d\n", WSTOPSIG(exitCode));
 }

        下面的代码是核心

#include"common.h"
 
 void  waitChild(int signo)// 把SIGCHLD信号和该函数绑定,当父进程接受到SIGCHLD信号后调用该函数,主要是回收子进程资源
 {
     if (signo == SIGCHLD){
         wait(&status);
     }   
     print_status(status);// 调用上面代码,打印退出码
 }
 
 void testInt(int signo)// 和ctrl + c,  SIGINT信号绑定的函数
 {
     printf("ctrl+c  pid:%d\n", getpid());
 }
 
 void testTstp(int signo)// 和ctrl + c,SIGTSTP信号绑定的函数
 {
     printf("ctrl+z  pid:%d\n", getpid());
 }
 
 int main(void)
 {
     pid_t pid;
     
     if (0 > (pid = fork())){// 创建子进程
         fprintf(stderr, "fork error!\n");
         exit(1);
     }else if(0 == pid){// 子进程操作区域
         sleep(2);// 睡眠2秒,让父进程为SIGCHLD信号绑定好函数
         printf("I am is child! pid is %d\n", getpid());
         if (SIG_ERR == signal(SIGTSTP, testTstp)){ // 子进程中也让SIGTSTP信号绑定testTstp函数,主要是测试kill发信号给进程组
             fprintf(stderr, "signal sigtstp error!\n");
             exit(-1);
         }   
 
         printf("send sigint to process group!\n");// 利用kill函数 发信号给父进程(打印语句中不应该有group)
         if (-1 == kill(getppid(), SIGINT))fprintf(stderr, "kill sigint error!\n");
 
         printf("send sigtstp to process group!\n");// 利用kill函数发送信号给自己所在的进程组
         //if (-1 == kill(0, SIGTSTP))fprintf(stderr, "kill sigint error!\n");
         if (-1 == kill(-(getgid()), SIGTSTP))fprintf(stderr, "kill sigint error!\n");
 
         exit(123);// 退出,退出码为 123
     }else{// 父进程操作区域
         printf("I am is parent! pid is %d\n", getpid());
         if (SIG_ERR == signal(SIGCHLD, waitChild)){ // 让SIGCHLD信号绑定waitChild函数
             fprintf(stderr, "signal error!\n");
             exit(-1);
         }
         if (SIG_ERR == signal(SIGINT, testInt)){ // 让SIGINT 信号绑定testInt
             fprintf(stderr, "signal sigint error!\n");
             exit(-1);
         }
         if (SIG_ERR == signal(SIGTSTP, testTstp)){ // 让SIGTSTP 信号绑定testTstp
             fprintf(stderr, "signal sigtstp error!\n");
             exit(-1);
         }
         while(1) // 死循环,等待信号
         pause();
 
     }
 
     return 0;
 }

        运行结果:

        Linux环境编程之信号处理(二、kill()函数)_第1张图片

        从上面结果可以看出:

        1、子进程把SIGINT信号发送给父进程,父进程调用了绑定的testInt()函数,打印了 pid为1364;

        2、子进程把SIGTSTP信号发送给子进程所在的进程组(新fork的子进程默认和父进程在同一个进程组),可以看出父进程和子进程都调用了testTstp()函数,打印的pid分别为:1364和1365;

        3、子进程退出时,发送了一个SIGCHLD信号给父进程(这是系统默认会发送的),父进程调用了绑定的waitChild()函数打印了退出码为:123;


        转载请注明作者和原文出处,原文地址: http://blog.csdn.net/yuzhihui_no1/article/details/44831865
        若有不正确之处,望大家指正,共同学习!谢谢!!!


你可能感兴趣的:(unix环境高级编程)