色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 信號通信編程實(shí)踐

          信號通信編程實(shí)踐

          ——
          作者: 時間:2007-03-05 來源: 收藏

          簡單的說,信號就是在軟件層次上對中斷機(jī)制的一種模擬,是一種異步通信方式。它可以實(shí)現(xiàn)內(nèi)核進(jìn)程和用戶進(jìn)程之間的交互。實(shí)現(xiàn)方式是,在任何時候發(fā)給某一進(jìn)程,如果該進(jìn)程沒有處于執(zhí)行態(tài),則該信號由內(nèi)核保存,直到該進(jìn)程恢復(fù)執(zhí)行再傳遞給它為止。如果一個信號進(jìn)程設(shè)置為阻塞,則該信號的傳遞被延遲,直到其阻塞被取消時才被傳遞給進(jìn)程。

            使用kill -l選項列出系統(tǒng)所支持的所有信號列表。我的Redhat 9.0上如下:
            
          1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
           5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
           9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
          13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
          18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
          22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
          26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
          30) SIGPWR 31) SIGSYS 33) SIGRTMIN 34) SIGRTMIN+1
          35) SIGRTMIN+2 36) SIGRTMIN+3 37) SIGRTMIN+4 38) SIGRTMIN+5
          39) SIGRTMIN+6 40) SIGRTMIN+7 41) SIGRTMIN+8 42) SIGRTMIN+9
          43) SIGRTMIN+10 44) SIGRTMIN+11 45) SIGRTMIN+12 46) SIGRTMIN+13
          47) SIGRTMIN+14 48) SIGRTMIN+15 49) SIGRTMAX-14 50) SIGRTMAX-13
          51) SIGRTMAX-12 52) SIGRTMAX-11 53) SIGRTMAX-10 54) SIGRTMAX-9
          55) SIGRTMAX-8 56) SIGRTMAX-7 57) SIGRTMAX-6 58) SIGRTMAX-5
          59) SIGRTMAX-4 60) SIGRTMAX-3 61) SIGRTMAX-2 62) SIGRTMAX-1
          63) SIGRTMAX
           

            可見信號值在31號前的有不同的名稱,這些是不可靠信號(非實(shí)時信號);后面的都是以SIGRTMIN或者SIGRTMAX開頭的信號,這些是為了解決前面“不可靠信號”的問題而進(jìn)行了更改和擴(kuò)充的信號,也稱為實(shí)時信號。其中RT就是Real Time的簡寫形式。

          1、信號的生命周期
           
          一個完整的信號生命周期可以分為3個重要階段,這三個重要階段由4個重要事件來刻畫:信號產(chǎn)生、信號在進(jìn)程中注冊、信號在進(jìn)程中注銷、執(zhí)行信號處理函數(shù)。相鄰兩個事件的時間間隔構(gòu)成信號生命周期的一個階段。
           
          2、信號處理過程
           
          一個不可靠信號的處理過程如下:若發(fā)現(xiàn)該信號已經(jīng)在進(jìn)程中注冊,就忽略該信號,所以,若前一個信號還未注銷又產(chǎn)生了相同的信號就會造成信號丟失。
           
          一個可靠信號的處理過程如下:可靠信號發(fā)送給進(jìn)程,不管該信號是否已經(jīng)在進(jìn)程中注冊,都會被再注冊一次,因此信號不會丟失。
           
          所有可靠信號都支持排隊,而不可靠信號不支持排隊。
           
          3、用戶進(jìn)程對信號的響應(yīng)形式
           
          (1)忽略信號,除SIGKILL、SIGSTOP。
          (2)捕捉信號,定義信號處理函數(shù),當(dāng)信號發(fā)生則執(zhí)行相應(yīng)的處理函數(shù)。
          (3)缺省操作。
           
          4、信號發(fā)送函數(shù)
           
          kill() raise() alarm() pause()
           
          實(shí)例一:保證子進(jìn)程不在父進(jìn)程調(diào)用kill之前退出
           
           
          /*
           * kill.c
           */

          #include <stdio.h>
          #include <stdlib.h>
          #include <sys/types.h>
          #include <unistd.h>
          #include <signal.h>
          #include <sys/wait.h>

          int main()
          {
              pid_t pid;

              if ((pid = fork()) < 0) {
                  perror("fork");
                  exit(1);
              }
              /*child*/
              else if (pid == 0) {
                  raise(SIGSTOP);
                  exit(0);
              }
              /*father*/
              else {
                  printf("pid = %dn", pid);
                  if (waitpid(pid, NULL, WNOHANG) == 0) {
                      if (kill(pid, SIGKILL) == 0) {
                          printf("kill %dn", pid);
                      }
                      else {
                          perror("kill");
                          exit(1);
                      }
                  }/*if*/
              }/*else*/

              return 0;
          }
           

          執(zhí)行結(jié)果:

          [armlinux@lqm kill]$ ./mykill
          pid = 2032
          kill 2032
           

          實(shí)例二:利用alarm完成sleep功能

          /*
           * alarm.c
           */

          #include <stdio.h>
          #include <stdlib.h>
          #include <unistd.h>
          #include <signal.h>

          void my_alarm_handle(int sign_no)
          {
              if (sign_no == SIGALRM) {
                  printf("I have been waken up.n");
              }
          }

          int main()
          {
              printf("sleep for 5s ... ...n");
              signal(SIGALRM, my_alarm_handle);

              alarm(5);
              pause();

              return 0;
          }
           

          執(zhí)行結(jié)果:

          [armlinux@lqm alarm]$ ./myalarm
          sleep for 5s ... ...

          等待5秒鐘后執(zhí)行處理函數(shù),打印輸出下面內(nèi)容:
          I have been waken up.
           

          5、信號處理集函數(shù)組

          sigemptyset:初始化信號集合為空

          sigfillset:初始化信號集合為所有信號的集合

          sigaddset:將指定信號加入到信號集合中去

          sigdelset:將指定信號從信號集中刪去

          sigismember:查詢指定信號是否在信號集合之中

          sigprocmask:判斷檢測或更改信號屏蔽字

          sigaction:用于改變進(jìn)程接收到特定信號之后的行為

          實(shí)踐三:練習(xí)信號處理集函數(shù)

          /*
           * 信號集函數(shù)組練習(xí)
           * 數(shù)據(jù)結(jié)構(gòu)sigaction
           * struct sigaction {
           * void (*sa_handler)(int signo);
           * sigset_t sa_mask;
           * int sa_flags;
           * void (*sa_restore)(void);
           * }
           */

          #include <stdio.h>
          #include <stdlib.h>
          #include <signal.h>
          #include <unistd.h>

          /*自定義SIGINT的處理函數(shù),如果你按ctrl+c,則會打印提示,而不是默認(rèn)的退出*/
          void my_func(int sigo_num)
          {
              printf("If you want to quit, please try 'ctrl+\' .n");
          }

          int main()
          {
              sigset_t set;
              struct sigaction action1, action2;

              /*初始化信號集為空*/
              if (sigemptyset(&set) < 0) {
                  perror("sigemptyset");
                  exit(1);
              }

              /*將相應(yīng)的信號加入信號集*/
              if (sigaddset(&set, SIGQUIT) < 0) {
                  perror("sigaddset SIGQUIT");
                  exit(1);
              }
              if (sigaddset(&set, SIGINT) < 0) {
                  perror("sigaddset SIGINT");
                  exit(1);
              }

              /*設(shè)置信號屏蔽字*/
              if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
                  perror("sigprocmask SIG_BLOCK");
                  exit(1);
              }
              else {
                  printf("blocked,and sleep for 5s ...n");
                  sleep(5);
              }
              if (sigprocmask(SIG_UNBLOCK, &set, NULL) < 0) {
                  perror("sigprocmask SIG_UNBLOCK");
                  exit(1);
              }
              else {
                  printf("unblockn");
                  /*此處可以添加函數(shù)功能模塊process()*/
                  sleep(2);
                  printf("If you want to quit this program, please try ...n");
              }

              /*對相應(yīng)的信號進(jìn)行循環(huán)處理*/
              while (1) {
                  if (sigismember(&set, SIGINT)) {
                      sigemptyset(&action1.sa_mask);
                      action1.sa_handler = my_func;
                      sigaction(SIGINT, &action1, NULL);
                  }
                  else if (sigismember(&set, SIGQUIT)) {
                      sigemptyset(&action2.sa_mask);
                      /*SIG_DFL采用缺省的方式處理*/
                      action2.sa_handler = SIG_DFL;
                      sigaction(SIGTERM, &action2, NULL);
                  }
              }

              return 0;
          }
           

          執(zhí)行處理:

          [armlinux@lqm sigaction]$ ./sigaction
          blocked,and sleep for 5s ...
          unblock
          If you want to quit this program, please try ...
          If you want to quit, please try 'ctrl+' .
          退出



          關(guān)鍵詞: 信號通信

          評論


          技術(shù)專區(qū)

          關(guān)閉