一、信号的介绍


我们一般都是用第一个,也就是通过typedef改写过的。








注意:signal函数我一般觉得其是向内核注冊当前进程收到信号的处理的方式。


signal(SIGINT,handler);






參数说明:




signum  :  指定信号


handler  :  SIG_IGN忽略该信号,SIG_DFL採用系统默认方式处理信号,自己定义的信号处理函数指针。




案例探究:




通过异步方式,给子进程收尸




注意:子进程在终止时会给父进程发SIGCHLD,该信号的默认处理动作是忽略。父进程能够自己定义SIGCHLD信号的处理函数,这样父进程仅仅须要专心处理自己的工作。不必关心子进程了。子进程终止时会通知父进程。父进程在信号处理函数中调用wait清理子进程就可以。









点击(此处)折叠或打开




  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>

  5. void child_exit_handler(int signum)
  6. {
  7.     if(signum == SIGCHLD)
  8.     {
  9.         printf("Child exit.\n");
  10.         wait(NULL);
  11.     }
  12. }

  13. int main()
  14. {
  15.     int pid;
  16.     int i = 0;

  17.     //想内核注冊,处理 SIGCHLD信号的方式
  18.     signal(SIGCHLD,child_exit_handler);

  19.     if((pid = fork()) < 0)
  20.     {
  21.         perror("Fail to fork");
  22.         exit(EXIT_FAILURE);

  23.     }else if(pid == 0){
  24.         
  25.         for(i = 0;i < 5;i ++)
  26.         {
  27.             printf("child loop.\n");
  28.             sleep(1);
  29.         }
  30.     
  31.     }else{
  32.         
  33.         for(i = 0;i < 5;i ++)
  34.         {
  35.             printf("Father loop.\n");
  36.             sleep(2);
  37.         }

  38.     }

  39.     exit(EXIT_SUCCESS);
  40. }





    C.闹钟函数alarm



    larm()也称为闹钟函数,它能够在进程中设置一个定时器。当定时器指定的时间到时。内核就向进程发送SIGALARM信号。




    seconds:指定的秒数,假设參数seconds为0。则之前设置的闹钟会被取消。并将剩下的时间返回。




    成功:假设调用此alarm()前,进程中已经设置了闹钟时间,则放回上一个闹钟时间的剩余时间,否则返回0。




    alarm(100);


    ........




    ......




    alarm(5);




    出错:-1




    案例探究:





    点击(此处)折叠或打开




    1. #include <stdio.h>
    2. #include <signal.h>
    3. #include <stdlib.h>

    4. void handler(int signum)
    5. {
    6.     if(signum == SIGALRM)
    7.     {
    8.         printf("Recv SIGALARM.\n");
    9.     }

    10.     exit(EXIT_SUCCESS);
    11. }

    12. int main()
    13. {
    14.     int count = 0;
    15.     int n = 0;

    16.     signal(SIGALRM,handler);

    17.     n = alarm(10);

    18.     printf("n = %d.\n",n);
    19.     
    20.     sleep(2);

    21.     n = alarm(5);

    22.     printf("n = %d.\n",n);
    23.     
    24.     while(1)
    25.     {
    26.         printf("count = %d.\n", ++count);
    27.         sleep(1);
    28.     }

    29.     return 0;
    30. }




      运行结果例如以下:


      案例二、综合案例




      使用FIFO实现clientA与clientB之间聊天


      A.输入quit后,两个进程退出


      B.假设在20秒内。没有等到还有一端发来的消息,则觉得对方已不在。此时终止。




      clientA:





      点击(此处)折叠或打开




      1. #include <stdio.h>
      2. #include <stdlib.h>
      3. #include <signal.h>
      4. #include <sys/types.h>
      5. #include <sys/stat.h>
      6. #include <errno.h>
      7. #include <string.h>
      8. #include <fcntl.h>

      9. #define MAX 100

      10. void signal_handler(int signum)
      11. {
      12.     static int flag = 0;

      13.     switch(signum)
      14.     {
      15.         case SIGALRM:
      16.             if(flag == 0)
      17.             {
      18.                 printf("The people is leaving,the system is closed in 10 seconds \
      19.                         and you can input 'ctrl + c' cancel.\n");
      20.                 alarm(10);
      21.             }else{
      22.                 
      23.                 kill(getppid(),SIGKILL);
      24.                 usleep(500);
      25.                 exit(EXIT_SUCCESS);
      26.             }

      27.             flag = 1;            
      28.             break;

      29.         case SIGINT:
      30.             printf("The alarm is cancel.\n");
      31.             alarm(0);
      32.             break;
      33.     }

      34. }

      35. int child_recv_fifo(char *fifo_name)
      36. {
      37.     int n,fd;
      38.     char buf[MAX];

      39.     if((fd = open(fifo_name,O_RDONLY)) < 0)
      40.     {
      41.         fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno));
      42.         return -1;
      43.     }

      44.     signal(SIGALRM,signal_handler);
      45.     signal(SIGINT,signal_handler);
      46.     alarm(15);//璁剧疆瀹氭椂鍣?    
      47.     while(1)
      48.     {
      49.         n = read(fd,buf,sizeof(buf));
      50.         buf[n] = '\0';

      51.         printf("Read %d bytes : %s.\n",n,buf);

      52.         if(strncmp(buf,"quit",4) == 0 || n == 0)
      53.         {
      54.             kill(getppid(),SIGKILL);
      55.             usleep(500);
      56.             exit(EXIT_SUCCESS);
      57.         }

      58.         alarm(15);
      59.     }

      60.     return 0;
      61. }

      62. int father_send_fifo(char *fifo_name,int pid)
      63. {
      64.     int n,fd;
      65.     char buf[MAX];

      66.     if((fd = open(fifo_name,O_WRONLY)) < 0)
      67.     {
      68.         fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno));
      69.         return -1;
      70.     }

      71.     signal(SIGINT,SIG_IGN);

      72.     while(1)
      73.     {
      74.         getchar();
      75.         printf(">");

      76.         fgets(buf,sizeof(buf),stdin);
      77.         buf[strlen(buf)-1] = '\0';

      78.         write(fd,buf,strlen(buf));

      79.         if(strncmp(buf,"quit",4) == 0)
      80.         {
      81.             kill(pid,SIGKILL);
      82.             usleep(500);
      83.             exit(EXIT_SUCCESS);
      84.         }
      85.     }

      86.     return 0;
      87. }

      88. int main(int argc,char *argv[])
      89. {
      90.     int pid;

      91.     if(argc < 3)
      92.     {
      93.         fprintf(stderr,"usage %s argv[1].\n",argv[0]);
      94.         exit(EXIT_FAILURE);
      95.     }

      96.     if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
      97.     {
      98.         perror("Fail to mkfifo");
      99.         exit(EXIT_FAILURE);
      100.     }

      101.     if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
      102.     {
      103.         perror("Fail to mkfifo");
      104.         exit(EXIT_FAILURE);
      105.     }
      106.     
      107.     if((pid = fork()) < 0)
      108.     {
      109.     
      110.         perror("Fail to fork");
      111.         exit(EXIT_FAILURE);
      112.     
      113.     }else if(pid == 0){
      114.         
      115.         child_recv_fifo(argv[2]);
      116.     
      117.     }else{

      118.         father_send_fifo(argv[1],pid);
      119.     }

      120.     exit(EXIT_SUCCESS);
      121. }





        client B





        点击(此处)折叠或打开




        1. #include <stdio.h>
        2. #include <stdlib.h>
        3. #include <signal.h>
        4. #include <sys/types.h>
        5. #include <sys/stat.h>
        6. #include <errno.h>
        7. #include <string.h>
        8. #include <fcntl.h>

        9. #define MAX 100

        10. void signal_handler(int signum)
        11. {
        12.     static int flag = 0;

        13.     switch(signum)
        14.     {
        15.         case SIGALRM:
        16.             if(flag == 0)
        17.             {
        18.                 printf("The people is leaving,the system is closed in 10 seconds \
        19.                         and you can input 'ctrl + c' cancel.\n");
        20.                 alarm(10);
        21.             }else{
        22.                 
        23.                 kill(getppid(),SIGKILL);
        24.                 usleep(500);
        25.                 exit(EXIT_SUCCESS);
        26.             }

        27.             flag = 1;            
        28.             break;

        29.         case SIGINT:
        30.             printf("The alarm is cancel.\n");
        31.             alarm(0);
        32.             break;
        33.     }

        34. }

        35. int child_recv_fifo(char *fifo_name)
        36. {
        37.     int n,fd;
        38.     char buf[MAX];

        39.     if((fd = open(fifo_name,O_RDONLY)) < 0)
        40.     {
        41.         fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno));
        42.         return -1;
        43.     }

        44.     signal(SIGALRM,signal_handler);
        45.     signal(SIGINT,signal_handler);
        46.     alarm(15);//璁剧疆瀹氭椂鍣?

            

        1.     while(1)
        2.     {
        3.         n = read(fd,buf,sizeof(buf));
        4.         buf[n] = '\0';

        5.         printf("Read %d bytes : %s.\n",n,buf);

        6.         if(strncmp(buf,"quit",4) == 0 || n == 0)
        7.         {
        8.             kill(getppid(),SIGKILL);
        9.             usleep(500);
        10.             exit(EXIT_SUCCESS);
        11.         }

        12.         alarm(15);
        13.     }

        14.     return 0;
        15. }

        16. int father_send_fifo(char *fifo_name,int pid)
        17. {
        18.     int n,fd;
        19.     char buf[MAX];

        20.     if((fd = open(fifo_name,O_WRONLY)) < 0)
        21.     {
        22.         fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno));
        23.         return -1;
        24.     }

        25.     signal(SIGINT,SIG_IGN);

        26.     while(1)
        27.     {
        28.         getchar();
        29.         printf(">");

        30.         fgets(buf,sizeof(buf),stdin);
        31.         buf[strlen(buf)-1] = '\0';

        32.         write(fd,buf,strlen(buf));

        33.         if(strncmp(buf,"quit",4) == 0)
        34.         {
        35.             kill(pid,SIGKILL);
        36.             usleep(500);
        37.             exit(EXIT_SUCCESS);
        38.         }
        39.     }

        40.     return 0;
        41. }

        42. int main(int argc,char *argv[])
        43. {
        44.     int pid;

        45.     if(argc < 3)
        46.     {
        47.         fprintf(stderr,"usage %s argv[1].\n",argv[0]);
        48.         exit(EXIT_FAILURE);
        49.     }

        50.     if(mkfifo(argv[1],0666) < 0 && errno != EEXIST)
        51.     {
        52.         perror("Fail to mkfifo");
        53.         exit(EXIT_FAILURE);
        54.     }

        55.     if(mkfifo(argv[2],0666) < 0 && errno != EEXIST)
        56.     {
        57.         perror("Fail to mkfifo");
        58.         exit(EXIT_FAILURE);
        59.     }
        60.     
        61.     if((pid = fork()) < 0)
        62.     {
        63.     
        64.         perror("Fail to fork");
        65.         exit(EXIT_FAILURE);
        66.     
        67.     }else if(pid == 0){
        68.         
        69.         child_recv_fifo(argv[1]);
        70.     
        71.     }else{

        72.         father_send_fifo(argv[2],pid);
        73.     }

        74.     exit(EXIT_SUCCESS);
        75. }