<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # 信號捕捉 ## 信號處理方式 一個進程收到一個信號的時候,可以用如下方法進行處理: 1)執行系統默認動作 對大多數信號來說,系統默認動作是用來終止該進程。 2)忽略此信號(丟棄) 接收到此信號后沒有任何動作。 3)執行自定義信號處理函數(捕獲) 用用戶定義的信號處理函數處理該信號。 【注意】:SIGKILL 和 SIGSTOP 不能更改信號的處理方式,因為它們向用戶提供了一種使進程終止的可靠方法。 內核實現信號捕捉過程: ![](https://img.kancloud.cn/ee/40/ee40dac755d0256897cb1b82920b510a_665x489.png) ## signal函數 ~~~ #include <signal.h> ? typedef void(*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); 功能: 注冊信號處理函數(不可用于 SIGKILL、SIGSTOP 信號),即確定收到信號后處理函數的入口地址。此函數不會阻塞。 ? 參數: signum:信號的編號,這里可以填數字編號,也可以填信號的宏定義,可以通過命令 kill - l("l" 為字母)進行相應查看。 handler : 取值有 3 種情況: SIG_IGN:忽略該信號 SIG_DFL:執行系統默認動作 信號處理函數名:自定義信號處理函數,如:func 回調函數的定義如下: void func(int signo) { // signo 為觸發的信號,為 signal() 第一個參數的值 } ? 返回值: 成功:第一次返回 NULL,下一次返回此信號上一次注冊的信號處理函數的地址。如果需要使用此返回值,必須在前面先聲明此函數指針的類型。 失敗:返回 SIG_ERR ~~~ 該函數由ANSI定義,由于歷史原因在不同版本的Unix和不同版本的Linux中可能有不同的行為。因此應該盡量避免使用它,取而代之使用sigaction函數。 ~~~ // 信號處理函數 void signal_handler(int signo) { if (signo == SIGINT) { printf("recv SIGINT\n"); } else if (signo == SIGQUIT) { printf("recv SIGQUIT\n"); } } ? int main() { printf("wait for SIGINT OR SIGQUIT\n"); ? /* SIGINT: Ctrl+c ; SIGQUIT: Ctrl+\ */ // 信號注冊函數 signal(SIGINT, signal_handler); signal(SIGQUIT, signal_handler); ? while (1); //不讓程序結束 ? return 0; } ~~~ ## sigaction函數 ~~~ #include <signal.h> ? int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 功能: 檢查或修改指定信號的設置(或同時執行這兩種操作)。 ? 參數: signum:要操作的信號。 act: 要設置的對信號的新處理方式(傳入參數)。 oldact:原來對信號的處理方式(傳出參數)。 ? 如果 act 指針非空,則要改變指定信號的處理方式(設置),如果 oldact 指針非空,則系統將此前指定信號的處理方式存入 oldact。 ? 返回值: 成功:0 失敗:-1 ~~~ **struct sigaction結構體:** ~~~ struct sigaction { void(*sa_handler)(int); //舊的信號處理函數指針 void(*sa_sigaction)(int, siginfo_t *, void *); //新的信號處理函數指針 sigset_t sa_mask; //信號阻塞集 int sa_flags; //信號處理的方式 void(*sa_restorer)(void); //已棄用 }; ~~~ 1) sa\_handler、sa\_sigaction:信號處理函數指針,和 signal() 里的函數指針用法一樣,應根據情況給sa\_sigaction、sa\_handler 兩者之一賦值,其取值如下: a) SIG\_IGN:忽略該信號 b) SIG\_DFL:執行系統默認動作 c) 處理函數名:自定義信號處理函數 2) sa\_mask:信號阻塞集,在信號處理函數執行過程中,臨時屏蔽指定的信號。 3) sa\_flags:用于指定信號處理的行為,通常設置為0,表使用默認屬性。它可以是一下值的“按位或”組合: ? SA\_RESTART:使被信號打斷的系統調用自動重新發起(已經廢棄) ? SA\_NOCLDSTOP:使父進程在它的子進程暫停或繼續運行時不會收到 SIGCHLD 信號。 ? SA\_NOCLDWAIT:使父進程在它的子進程退出時不會收到 SIGCHLD 信號,這時子進程如果退出也不會成為僵尸進程。 ? SA\_NODEFER:使對信號的屏蔽無效,即在信號處理函數執行期間仍能發出這個信號。 ? SA\_RESETHAND:信號處理之后重新設置為默認的處理方式。 ? SA\_SIGINFO:使用 sa\_sigaction 成員而不是 sa\_handler 作為信號處理函數。 **信號處理函數:** ~~~ void(*sa_sigaction)(int signum, siginfo_t *info, void *context); 參數說明: signum:信號的編號。 info:記錄信號發送進程信息的結構體。 context:可以賦給指向 ucontext_t 類型的一個對象的指針,以引用在傳遞信號時被中斷的接收進程或線程的上下文。 ~~~ ~~~ void myfunc(int sig) { printf("hello signal: %d\n", sig); sleep(5); printf("wake up .....\n"); } ? int main() { // 注冊信號捕捉函數 struct sigaction act; act.sa_flags = 0; act.sa_handler = myfunc; // 設置臨時屏蔽的信號 sigemptyset(&act.sa_mask); // 清空 // ctrl + 反斜杠 sigaddset(&act.sa_mask, SIGQUIT); ? sigaction(SIGINT, &act, NULL); //注冊信號 ? while (1); ? return 0; } ~~~ ## sigqueue函數 ~~~ #include <signal.h> ? int sigqueue(pid_t pid, int sig, const union sigval value); 功能: 給指定進程發送信號。 參數: pid : 進程號。 sig : 信號的編號。 value : 通過信號傳遞的參數。 union sigval 類型如下: union sigval { int sival_int; void *sival_ptr; }; 返回值: 成功:0 失敗:-1 ~~~ 向指定進程發送指定信號的同時,攜帶數據。但如傳地址,需注意,不同進程之間虛擬地址空間各自獨立,將當前進程地址傳遞給另一進程沒有實際意義。 下面我們做這么一個例子,一個進程在發送信號,一個進程在接收信號的發送。 發送信號示例代碼如下: ~~~ /******************************************************* *功能: 發 SIGINT 信號及信號攜帶的值給指定的進程 *參數: argv[1]:進程號 argv[2]:待發送的值(默認為100) *返回值: 0 ********************************************************/ int main() { if (argc >= 2) { pid_t pid, pid_self; union sigval tmp; ? pid = atoi(argv[1]); // 進程號 if (argc >= 3) { tmp.sival_int = atoi(argv[2]); } else { tmp.sival_int = 100; } ? // 給進程 pid,發送 SIGINT 信號,并把 tmp 傳遞過去 sigqueue(pid, SIGINT, tmp); ? pid_self = getpid(); // 進程號 printf("pid = %d, pid_self = %d\n", pid, pid_self); } ? return 0; } ~~~ 接收信號示例代碼如下: ~~~ // 信號處理回調函數 void signal_handler(int signum, siginfo_t *info, void *ptr) { printf("signum = %d\n", signum); // 信號編號 printf("info->si_pid = %d\n", info->si_pid); // 對方的進程號 printf("info->si_sigval = %d\n", info->si_value.sival_int); // 對方傳遞過來的信息 } ? int main() { struct sigaction act, oact; ? act.sa_sigaction = signal_handler; //指定信號處理回調函數 sigemptyset(&act.sa_mask); // 阻塞集為空 act.sa_flags = SA_SIGINFO; // 指定調用 signal_handler ? // 注冊信號 SIGINT sigaction(SIGINT, &act, &oact); ? while (1) { printf("pid is %d\n", getpid()); // 進程號 ? pause(); // 捕獲信號,此函數會阻塞 } ? return 0; } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看