zoukankan      html  css  js  c++  java
  • Linux 进程学习(三)

    捕捉信号:
      
     
    使用 signal 函数
     signal 函数是 Linux 系统上传统的信号处理接口:
     #include <signal.h>
     sighandler_t signal(int signum, sighandler_t handler);

     其中 sighandler_t 类型是一个函数指针类型,定义如下:
     typedef void (*sighandler_t)(int);

     这个类型表示一个信号处理函数。signal 函数的作用就是讲 handler 参数所指向的函数注册成为参数

    signum 所代表的信号的处理函数,它的返回值是这个信号原来的处理函数,如果返回 SIG_ERR,则说明有错误发生,
    注册失败。
     注册成功后,所注册的函数就会在信号被处理时调用,代替了默认的行为,或者成为信号被捕捉。 
     
     使用 signal 函数时应注意以下两点:
     ◆ handler 参数的值可以是 SIG_IGN 或者 SIG_DFL,SIG_IGN 表示忽略这个信号,SIG_DFL 表示对信号的处

    理重设为系统的默认方式。
     ◆ 有些信号是不可以忽略或捕获的,如 SIGKILL 和 SIGSTOP。

     下面给出一个例程来说明信号的产生、忽略与捕获的编程,例程代码如下:

      1 /* 文件名:sigtest.c */
      2 /* 说明:信号处理例程 */
      3 
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <signal.h>
      7 #include <unistd.h>
      8 #include <sys/wait.h>
      9 
     10 static pid_t pid;
     11 
     12 /* 子进程 1 SIGALRM 信号处理函数 */
     13 static void wakeup(int dummy)
     14 {
     15     printf("I (pid = %d) am up now\n",pid);
     16 }
     17 
     18 /* 子进程 1 SIGINT 信号处理函数 */
     19 static void handler(int dummy)
     20 {
     21     printf("I (pid = %d) got an interrupt, will exit\n",pid);
     22     exit(0);
     23 }
     24 
     25 /* 子进程 2 信号处理函数 */
     26 static void trapper(int i)
     27 {
     28     if(i == SIGUSR1)
     29     {
     30         printf("I (pid = %d) got SIGUSR1,will exit\n", pid);
     31         exit(0);
     32     }
     33     else
     34     {
     35         printf("I (pid = %d) got signal %d, will continue\n", pid, i);
     36     }
     37 }
     38 
     39 
     40 /* 父进程信号处理函数 */
     41 void parent(int sig)
     42 {
     43     printf("Signal (%d) received by parent (%d)\n", sig, pid);
     44 }
     45 
     46 int main(int argc, char *argv[])
     47 {
     48     int i, cpid1, cpid2;
     49     
     50     printf("Number of signal is %d\n", NSIG);   //输出系统中信号的个数
     51     
     52     if(!(cpid1 = fork()))  //创建第一个子进程
     53     {
     54         pid = cpid1 = getpid();  //获得子进程的进程号
     55         printf("CPID1 = %d\n", cpid1);
     56         
     57         for(i=1; i<NSIG; i++)
     58         {
     59             signal(i, SIG_IGN);  //忽略所以的信号
     60         }
     61         
     62         signal(SIGINT, handler); //捕获信号 SIGINT
     63         signal(SIGALRM, wakeup); //捕获超时信号
     64         alarm(2);                //启动定时器,设置 2 秒后超时
     65         
     66         for(; ;)
     67         {
     68             pause();  //等待信号
     69         }
     70         
     71         printf(" -- CPID1 (%d) terminates\n", cpid1);
     72         
     73         exit(0);
     74     }
     75     else if(!(cpid2 = fork()))  //创建第二个子进程
     76     {
     77         pid = cpid2 = getpid();
     78         printf("CPID2 = %d\n", cpid2);
     79         
     80         for(i=1; i<NSIG; i++)
     81         {
     82             signal(i, trapper);  //捕获所有的信号
     83         }
     84         
     85         for(; ;)
     86         {
     87             pause();  //等待信号
     88         }
     89         
     90         printf(" -- CPID2 (%d) terminates\n", cpid2);
     91         
     92         exit(0);
     93     }
     94     
     95     /* 下面是父进程执行的代码 */
     96     pid = getpid();  //取得 PID
     97     sleep(3);        //睡眠,让子进程先运行
     98     printf("This is parent process (pid = %d)\n", pid);
     99     
    100     for(i=1; i<NSIG; i++)
    101     {
    102         signal(i, parent);  //捕获所以信号
    103     }
    104     
    105     printf("Send SIGUSR1(%d) to CPID1 (%d)\n", SIGUSR1, cpid1);
    106     kill(cpid1, SIGUSR1);
    107     printf("Send SIGINT(%d) to CPID1 (%d)\n", SIGINT, cpid1);
    108     kill(cpid1, SIGINT);
    109     printf("Send SIGINT(%d) to CPID2 (%d)\n", SIGBUS, cpid2);
    110     kill(cpid2, SIGINT);
    111     printf("Send SIGUSR1(%d) to CPID2 (%d)\n", SIGUSR1, cpid2);
    112     kill(cpid2, SIGUSR1);
    113     
    114     for(; wait((int *)0) > 0; );  //等待子进程结束
    115     
    116     return 0;
    117 }

    在这个例程中,父进程又创建了两个子进程,这三个进程分别注册或忽略了相关的信号,然后通过 alarm 函数设置超

    时信号或通过 kill 函数发送信号。还用到了 pause 和 sleep 函数,如下:
     #include <unistd.h>
     int pause(void);
     unsigned int sleep(unsigned int seconds);

     pause 函数将使当前进程进入睡眠态,直到有信号发送。它的返回值永远是 -1,同时变量 errno 的值被设为

    EINTR 以表示有信号发生。
     sleep 函数将使当前进程进入睡眠态,并在 seconds 参数指定的秒数后被唤醒继续执行。注意当有未忽略的

    信号发生时 sleep 函数会提前返回,返回值是剩余的秒数。如果返回 0 则说明是正常被唤醒的,而不是因信号的发生

    提前返回的。

  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/wblyuyang/p/2767167.html
Copyright © 2011-2022 走看看