新聞中心

        EEPW首頁 > 信號通信編程實踐

        信號通信編程實踐

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

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

          使用kill -l選項列出系統所支持的所有信號列表。我的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號前的有不同的名稱,這些是不可靠信號(非實時信號);后面的都是以SIGRTMIN或者SIGRTMAX開頭的信號,這些是為了解決前面“不可靠信號”的問題而進行了更改和擴充的信號,也稱為實時信號。其中RT就是Real Time的簡寫形式。

        1、信號的生命周期
         
        一個完整的信號生命周期可以分為3個重要階段,這三個重要階段由4個重要事件來刻畫:信號產生、信號在進程中注冊、信號在進程中注銷、執行信號處理函數。相鄰兩個事件的時間間隔構成信號生命周期的一個階段。
         
        2、信號處理過程
         
        一個不可靠信號的處理過程如下:若發現該信號已經在進程中注冊,就忽略該信號,所以,若前一個信號還未注銷又產生了相同的信號就會造成信號丟失。
         
        一個可靠信號的處理過程如下:可靠信號發送給進程,不管該信號是否已經在進程中注冊,都會被再注冊一次,因此信號不會丟失。
         
        所有可靠信號都支持排隊,而不可靠信號不支持排隊。
         
        3、用戶進程對信號的響應形式
         
        (1)忽略信號,除SIGKILL、SIGSTOP。
        (2)捕捉信號,定義信號處理函數,當信號發生則執行相應的處理函數。
        (3)缺省操作。
         
        4、信號發送函數
         
        kill() raise() alarm() pause()
         
        實例一:保證子進程不在父進程調用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;
        }
         

        執行結果:

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

        實例二:利用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;
        }
         

        執行結果:

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

        等待5秒鐘后執行處理函數,打印輸出下面內容:
        I have been waken up.
         

        5、信號處理集函數組

        sigemptyset:初始化信號集合為空

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

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

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

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

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

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

        實踐三:練習信號處理集函數

        /*
         * 信號集函數組練習
         * 數據結構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的處理函數,如果你按ctrl+c,則會打印提示,而不是默認的退出*/
        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);
            }

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

            /*設置信號屏蔽字*/
            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");
                /*此處可以添加函數功能模塊process()*/
                sleep(2);
                printf("If you want to quit this program, please try ...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;
        }
         

        執行處理:

        [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+' .
        退出



        關鍵詞: 信號通信

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 阿克| 金昌市| 临湘市| 宁河县| 石城县| 永丰县| 阿克苏市| 平邑县| 遵化市| 盱眙县| 泰安市| 平安县| 平凉市| 盘山县| 林甸县| 惠安县| 扶绥县| 凤冈县| 恩平市| 信宜市| 新蔡县| 蛟河市| 霍州市| 冕宁县| 江陵县| 东城区| 乌苏市| 南充市| 定陶县| 乌兰县| 绿春县| 奉化市| 敦煌市| 白朗县| 逊克县| 井研县| 延长县| 竹北市| 乐东| 衡水市| 霍邱县|