• <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>

            輕重緩急

            成功來(lái)源于有效的自我管理。
            隨筆 - 14, 文章 - 3, 評(píng)論 - 3, 引用 - 0
            數(shù)據(jù)加載中……

            signal 轉(zhuǎn)貼的,不知來(lái)源,見(jiàn)諒

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

            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   //本次程序提到信號(hào)
            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、信號(hào)的產(chǎn)生

            (1)kill函數(shù)

            函數(shù)調(diào)用形式為int kill(pid_t pid,int sig),表示向進(jìn)程pid發(fā)送信號(hào)sig。這個(gè)函數(shù)之前用過(guò),不再介紹。

            函數(shù)執(zhí)行成功返回0,失敗返回-1.

            (2)raise函數(shù)

            該函數(shù)用于給調(diào)用進(jìn)程自身發(fā)送信號(hào),調(diào)用形式為int raise(int sig);等同與調(diào)用kill(getpid(),sig).

            函數(shù)執(zhí)行成功返回0,失敗返回非零數(shù)值。

            (3)alarm函數(shù)

            該函數(shù)用于給進(jìn)程設(shè)置告警時(shí)鐘,時(shí)鐘(單位為秒)到達(dá)后,給進(jìn)程發(fā)送SIGALARM信號(hào)。默認(rèn)處理方式為進(jìn)程直接終止運(yùn)行,也可以修改捕捉信號(hào)后的默認(rèn)處理函數(shù)。

            【程序?qū)嵗?/p>

            //連續(xù)創(chuàng)建5個(gè)子進(jìn)程,分別給5個(gè)子進(jìn)程設(shè)置告警時(shí)鐘1-5秒,時(shí)鐘到達(dá)時(shí),捕捉到SIGALARM信號(hào),采用默認(rèn)處理方式,直接終止執(zhí)行;捕捉到信號(hào)之前用pause掛起進(jìn)程,使其處于等待狀態(tài);由于捕捉信號(hào)以后的默認(rèn)處理就是終止,因此不需要顯式的調(diào)用_exit等函數(shù)。

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

            #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;

            }

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

            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對(duì)應(yīng)信號(hào)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、信號(hào)的處理

            進(jìn)程捕捉到信號(hào)以后可以有三種處理方式:

            ---不做任何處理(采用系統(tǒng)默認(rèn)的處理方式);

            ---忽略信號(hào)(需要修改默認(rèn)處理到ignore);

            ---捕獲信號(hào)(需要修改默認(rèn)處理到自定義的處理方式);

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

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

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

            下面signal函數(shù)和sigaction函數(shù)是Linux提供的2個(gè)系統(tǒng)調(diào)用。

             

            (1)signal函數(shù)

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

            typedef void (*sighandler_t)(int);

            signum:要捕獲的信號(hào)值;

            handler:指向要調(diào)用的函數(shù)指針(可以為SIG_IGN忽略信號(hào)或者為SIG_DFL采用默認(rèn)方式);

            【程序?qū)嵗?/p>

            代碼中修改了對(duì)SIGINT的處理方式,默認(rèn)為直接終止,修改成為忽略信號(hào);對(duì)于SIGUSR1,調(diào)用函數(shù)sigusr1 進(jìn)行處理后結(jié)束。

            #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;
            }

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

            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函數(shù)

            該函數(shù)用于檢查或者指定信號(hào)的處理動(dòng)作。

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

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

            ---act:如果act非空,則按照act指向的結(jié)構(gòu)體信息重新設(shè)置信號(hào)處理函數(shù);

            ---oldact:如果oldact非空,將原有的信號(hào)處理函數(shù)保存在oldact指向的結(jié)構(gòu)體。

            sigaction結(jié)構(gòu)體定義和參數(shù)取值略。。。

            【程序?qū)嵗?/p>

            下面的程序打印信號(hào)1-11的處理方式,由于只有信號(hào)10(SIGUSR1)的默認(rèn)處理方式被函數(shù)sigaction修改過(guò),其他的打印都為默認(rèn)處理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:捕獲信號(hào)完成處理后,將信號(hào)處理恢復(fù)為默認(rèn)處理;SA_NODEFER:完成信號(hào)處理之前如果再次收到信號(hào),不做處理

             sigaction(SIGUSR1,&act,&oldact);  //對(duì)信號(hào)SIGUSR1更改默認(rèn)處理方式,處理調(diào)用函數(shù)usr1_handler

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

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

            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:~$
            *************************************************************************************

            信號(hào)值小于SIGRTMIN的信號(hào)都是不可靠信號(hào)。對(duì)于UNIX系統(tǒng)而言,不可靠信號(hào)的含義有2個(gè):

            (1)可能對(duì)信號(hào)采用錯(cuò)誤的處理

            捕捉到不可靠信號(hào)并處理以后,可能將信號(hào)的處理方法恢復(fù)到系統(tǒng)默認(rèn)的處理方法。因此每次處理以后,都要重新設(shè)置信號(hào)處理函數(shù)。

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

            比如sleep()或者pause()時(shí)可能捕捉不到信號(hào)。

            在Linux系統(tǒng)下,不可靠信號(hào)僅指信號(hào)的丟失,因?yàn)橄到y(tǒng)對(duì)不可靠信號(hào)機(jī)制做了改進(jìn),不需要重新設(shè)置信號(hào)處理函數(shù)。

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

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


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            一级A毛片免费观看久久精品| 国产精品一区二区久久精品涩爱 | 精品久久久久久中文字幕| 欧洲成人午夜精品无码区久久| 2021久久国自产拍精品| 国内精品久久久久久麻豆| 久久强奷乱码老熟女网站| 国产精品久久久久久影院| 亚洲国产成人精品91久久久| 欧洲人妻丰满av无码久久不卡| 国产福利电影一区二区三区久久久久成人精品综合 | 精品久久久久久亚洲精品| 久久一区二区免费播放| 久久精品人人做人人爽97 | 国产精品热久久毛片| 一本久道久久综合狠狠爱| 精品人妻伦一二三区久久| 久久久精品人妻一区二区三区四| 国产一区二区三精品久久久无广告 | 色综合合久久天天综合绕视看| 国内精品久久国产| 狠狠人妻久久久久久综合| 久久99精品国产自在现线小黄鸭| 亚洲国产精品无码久久青草| 国产精品天天影视久久综合网| 国产精品乱码久久久久久软件| 久久精品国产一区二区| 久久久久久久尹人综合网亚洲 | 亚洲欧美久久久久9999| 中文精品久久久久国产网址| 久久精品人人做人人爽97| 亚洲国产美女精品久久久久∴| 99精品国产免费久久久久久下载| 久久午夜综合久久| 久久精品女人天堂AV麻| Xx性欧美肥妇精品久久久久久| 国产精品久久久久久久| 久久不见久久见免费视频7| 新狼窝色AV性久久久久久| 性欧美大战久久久久久久久| 久久精品国产亚洲AV蜜臀色欲|