• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            輕重緩急

            成功來源于有效的自我管理。
            隨筆 - 14, 文章 - 3, 評論 - 3, 引用 - 0
            數據加載中……

            signal 轉貼的,不知來源,見諒

            信號是進程之間通信的另外一種方式。之前用過kill -l看了Linux系統支持的所有信號,這些信號在sys/signal.h中定義,系統支持64種信號。除了系統內核和root之外,只有具備相同uid、gid的進程才可以使用信號進行通信。

            gaolu@gaolu-desktop:~$ kill -l
             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 16) SIGSTKFLT   //本次程序提到信號
            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 34) SIGRTMIN
            35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
            39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
            43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
            47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
            51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
            55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
            59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
            63) SIGRTMAX-1 64) SIGRTMAX 
            gaolu@gaolu-desktop:~$

            1、信號的產生

            (1)kill函數

            函數調用形式為int kill(pid_t pid,int sig),表示向進程pid發送信號sig。這個函數之前用過,不再介紹。

            函數執行成功返回0,失敗返回-1.

            (2)raise函數

            該函數用于給調用進程自身發送信號,調用形式為int raise(int sig);等同與調用kill(getpid(),sig).

            函數執行成功返回0,失敗返回非零數值。

            (3)alarm函數

            該函數用于給進程設置告警時鐘,時鐘(單位為秒)到達后,給進程發送SIGALARM信號。默認處理方式為進程直接終止運行,也可以修改捕捉信號后的默認處理函數。

            【程序實例】

            //連續創建5個子進程,分別給5個子進程設置告警時鐘1-5秒,時鐘到達時,捕捉到SIGALARM信號,采用默認處理方式,直接終止執行;捕捉到信號之前用pause掛起進程,使其處于等待狀態;由于捕捉信號以后的默認處理就是終止,因此不需要顯式的調用_exit等函數。

            父進程等待所有的子進程結束,根據wait到的status,調用宏判斷是屬于正常退出(打印退出碼),還是接受到信號退出(打印接收到的信號值)。

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

            int main(void)
            {
             int status,i;
             pid_t pid,wait_pid;

             for(i=1;i<=5;i++)
             {
              pid = fork();
              if(pid<0)
              {
               perror("Creat child process failed.\n");
               return 1;
              }
              if(pid == 0)
              {
               printf("Child process %ld will terminal after %d seconds.\n",(long)getpid(),i);
               alarm(i);
               pause();
              }
             }
             
             while((pid = wait(&status))&&pid!=-1)
             {
              if(WIFSIGNALED(status))
              {
               printf("Process %d exit because of receiving signal %d.\n",pid,WTERMSIG(status));
              }
              if(WIFEXITED(status))
              {
               printf("Process %d exit code %d.\n",pid,WEXITSTATUS(status));
              }
             }
             return 0;

            }

            執行結果:

            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$ gcc -o sig systemcall2.c
            gaolu@gaolu-desktop:~$ ./sig
            Child process 5757 will terminal after 1 seconds.
            Child process 5758 will terminal after 2 seconds.
            Child process 5759 will terminal after 3 seconds.
            Child process 5760 will terminal after 4 seconds.
            Child process 5761 will terminal after 5 seconds.
            Process 5757 exit because of receiving signal 14.   //14對應信號SIGALRM 
            Process 5758 exit because of receiving signal 14.
            Process 5759 exit because of receiving signal 14.
            Process 5760 exit because of receiving signal 14.
            Process 5761 exit because of receiving signal 14.
            gaolu@gaolu-desktop:~$

             

            2、信號的處理

            進程捕捉到信號以后可以有三種處理方式:

            ---不做任何處理(采用系統默認的處理方式);

            ---忽略信號(需要修改默認處理到ignore);

            ---捕獲信號(需要修改默認處理到自定義的處理方式);

            *******************************************

            SIGKILL和SIGSTOP是不能夠被捕獲的。

            *******************************************

            下面signal函數和sigaction函數是Linux提供的2個系統調用。

             

            (1)signal函數

            調用形式sighandler_t signal(int signum,sighandler_t handler);

            typedef void (*sighandler_t)(int);

            signum:要捕獲的信號值;

            handler:指向要調用的函數指針(可以為SIG_IGN忽略信號或者為SIG_DFL采用默認方式);

            【程序實例】

            代碼中修改了對SIGINT的處理方式,默認為直接終止,修改成為忽略信號;對于SIGUSR1,調用函數sigusr1 進行處理后結束。

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

            void sigusr1 (int sig)
            {
             printf("Get the SIGUSER signal,now process...\n");


             exit(0);
            }

            int main (void)
            {
             if(signal(SIGINT,SIG_IGN)==SIG_ERR)
             {
              printf("Fail to reset signal handler of SIGINT.\n");
              return 1;
             }
             if(signal(SIGUSR1,sigusr1)==SIG_ERR)
             {
              printf("Fail to reset signal handler of SIGUSR1.\n");
              return 1;
             }
             pause();
             return 0;
            }

            執行結果:

            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$ gcc -o sig systemcall2.c
            gaolu@gaolu-desktop:~$ ./sig &
            [1] 6011
            gaolu@gaolu-desktop:~$ kill -SIGINT 6011
            gaolu@gaolu-desktop:~$ jobs
            [1]+  Running                 ./sig &      //SIGINT被忽略了
            gaolu@gaolu-desktop:~$ kill -SIGUSR1 6011
            Get the SIGUSER signal,now process...
            [1]+  Done                    ./sig
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$ jobs
            gaolu@gaolu-desktop:~$

             

            (2)sigaction函數

            該函數用于檢查或者指定信號的處理動作。

            調用形式int sigaction(int signum,const struct sigaction *act,const struct sigaction *oldact);

            ---signum:要捕捉的信號值(不包括SIGKILL和SIGSTOP);

            ---act:如果act非空,則按照act指向的結構體信息重新設置信號處理函數;

            ---oldact:如果oldact非空,將原有的信號處理函數保存在oldact指向的結構體。

            sigaction結構體定義和參數取值略。。。

            【程序實例】

            下面的程序打印信號1-11的處理方式,由于只有信號10(SIGUSR1)的默認處理方式被函數sigaction修改過,其他的打印都為默認處理SIG_DFL.

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

            void signal_process_info(struct sigaction *act)
            {
             switch(act->sa_flags)
             {
              case (int)SIG_DFL:
              {
               printf("using default handler.\n");
               break;
              }
              case (int)SIG_IGN:
              {
               printf("ignore the signal.\n");
               break;
              }
              default:
              {
               printf("use handler: %0x.\n",act->sa_flags);
               break;
              }
             }
             return;
            }

            void usr1_handler(void)
            {
             
            }

            int main(void)
            {
             int i;
             struct sigaction act,oldact;

             act.sa_handler =  usr1_handler;
             act.sa_flags = SA_NODEFER|SA_RESETHAND;  //SA_RESETHAND:捕獲信號完成處理后,將信號處理恢復為默認處理;SA_NODEFER:完成信號處理之前如果再次收到信號,不做處理

             sigaction(SIGUSR1,&act,&oldact);  //對信號SIGUSR1更改默認處理方式,處理調用函數usr1_handler

             for(i=1;i<12;i++)
             {
              printf("signal %d handler is:",i);
              sigaction(i,NULL,&oldact); //act=NULL,檢查而已
              signal_process_info(&oldact); //打印信號處理方式
             }
             return 0;
            }

            執行結果:

            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$ gcc -o sig2 systemcall2.c
            systemcall2.c: In function main
            systemcall2.c:37: warning: assignment from incompatible pointer type
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$
            gaolu@gaolu-desktop:~$ ./sig2
            signal 1 handler is:using default handler.
            signal 2 handler is:using default handler.
            signal 3 handler is:using default handler.
            signal 4 handler is:using default handler.
            signal 5 handler is:using default handler.
            signal 6 handler is:using default handler.
            signal 7 handler is:using default handler.
            signal 8 handler is:using default handler.
            signal 9 handler is:using default handler.
            signal 10 handler is:use handler: c0000000.
            signal 11 handler is:using default handler.
            gaolu@gaolu-desktop:~$
            *************************************************************************************

            信號值小于SIGRTMIN的信號都是不可靠信號。對于UNIX系統而言,不可靠信號的含義有2個:

            (1)可能對信號采用錯誤的處理

            捕捉到不可靠信號并處理以后,可能將信號的處理方法恢復到系統默認的處理方法。因此每次處理以后,都要重新設置信號處理函數。

            (2)存在信號丟失的可能

            比如sleep()或者pause()時可能捕捉不到信號。

            在Linux系統下,不可靠信號僅指信號的丟失,因為系統對不可靠信號機制做了改進,不需要重新設置信號處理函數。

            考慮到代碼的可移植性,使用較多的是sigaction()函數。

            posted on 2010-04-16 17:34 隨遇而安 閱讀(268) 評論(0)  編輯 收藏 引用

            国产精品99久久久精品无码| 色欲综合久久中文字幕网| 久久se精品一区二区| 亚洲国产精品久久久久网站| 久久精品成人免费观看97| 伊人久久国产免费观看视频| 亚洲午夜久久久影院| 丁香狠狠色婷婷久久综合| 免费一级欧美大片久久网| 麻豆精品久久精品色综合| 久久乐国产综合亚洲精品| 91久久精品91久久性色| 久久黄色视频| 久久国产精品一国产精品金尊| 亚洲七七久久精品中文国产 | 九九久久精品国产| 狠狠88综合久久久久综合网| 欧美精品乱码99久久蜜桃| 日韩精品无码久久一区二区三| 久久99国产精品久久99| 无码人妻久久一区二区三区蜜桃| 久久精品亚洲中文字幕无码麻豆| 久久国产精品二国产精品| 精品久久久久久中文字幕大豆网| 久久天天躁狠狠躁夜夜不卡| 一级做a爰片久久毛片16| 人妻无码αv中文字幕久久| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 97超级碰碰碰久久久久| 亚洲欧美日韩久久精品| 国产AⅤ精品一区二区三区久久| 国产精品久久国产精麻豆99网站| 伊人久久大香线蕉AV一区二区| 久久综合中文字幕| 久久精品9988| 伊人色综合久久天天| 久久精品中文字幕久久| 狠狠干狠狠久久| 色综合久久精品中文字幕首页| 久久综合久久综合久久| 久久久久久久尹人综合网亚洲|