linux SA_RESTART的問題

來源:互聯網
上載者:User

訊號是非同步,它會在程式的任何地方發生。由此程式正常的執行路徑被打破,去執行訊號處理函數。

一般情況下

,進程正在執行某個系統調用,那麼在該系統調用返回前訊號是不會被遞送的。但慢速系統調用除外,如讀寫終端、網路、磁碟,以及wait和pause。這些系
統調用都會返回-1,errno置為EINTR當系統調用被中斷時,我們可以選擇使用迴圈再次調用,或者設定重新啟動該系統調用
(SA_RESTART)。

現在說說對上面話的理解:

我認為函數或進程的運行最終都迴歸結尾系統調用,(呵呵,非官方,自己理解)

那麼

“進程正在執行某個系統調用,那麼在該系統調用返回前訊號是不會被遞送的”,就是說大多數進程在運行期間是阻塞訊號的,系統調用完再處理,

但是(以下引用APUE):如果在進程執行一個低速系統而阻塞期間捕捉到一個訊號,該系統調用被終端不再繼續執行

When a system call is slow and a signal arrives while it was blocked,
waiting for something, the call is aborted and returns -EINTR

,
so that the library function will return -1 and set errno

to EINTR

. Just before the system call returns, the user program's
signal handler is called.

(So, what is "slow"? Mostly those calls that can block forever waiting
for external events; read and write to terminal devices, but not
read and write to disk devices, wait

, pause

.)

This means that a system call can return an error while nothing was
wrong. Usually one will want to redo the system call. That can be
automated by installing the signal handler using a call to
sigaction

with the SA_RESTART

flag set.
The effect is that upon an interrupt the system call is aborted,
the user program's signal handler is called, and afterwards
the system call is restarted from the beginning.

我們可以選擇使用迴圈再次調用,或者設定重新啟動該系統調用
(SA_RESTART),

這是是低速系統調用被訊號中斷的解決辦法,1迴圈2SA——RESTART

好啦,實驗代碼:

#include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <stdbool.h>
  5 #include <signal.h>
  6 #include <sys/types.h>
  7 #include <errno.h>
  8 #include <string.h>
  9
 10 void int_handler (int signum)
 11 {
 12         printf ("int handler %d/n",signum);
 13 }
 14
 15 int main(int argc, char **argv)
 16 {
 17         char buf[100];
 18         ssize_t ret;
 19         struct sigaction oldact;
 20         struct sigaction act;
 21
 22         act.sa_handler = int_handler;
 23         act.sa_flags=0;
 24         act.sa_flags |= SA_RESTART;
 25         sigemptyset(&act.sa_mask);
 26         if (-1 == sigaction(SIGINT,&act,&oldact))
 27         {
 28                 printf("sigaction failed!/n");
 29                 return -1;
 30         }
 31
 32         bzero(buf,100);
 33
 34         ret = read(STDIN_FILENO,buf,10);
 35         if (ret == -1)
 36         {
 37                 printf ("read error %s/n", strerror(errn    o));

 38         }
 39         printf ("read %d bytes, content is %s/n",ret,buf    );
 40         sleep (10);
 41         return 0;
 42 }

這裡我們就看第二種解決辦法SA—restart

運行看結果:

^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
^Cint handler 2
hgfd
read 5 bytes, content is hgfd

^Cint handler 2
在程式read之前不要輸入,ctrl+c這樣不會中斷read輸入後主程式就向下運行啦,這樣就不在低速的系統調用即read中啦,所以再次ctrl+c結束;

下面改程式:把程式24行注釋掉:結果

^Cint handler 2
read error Interrupted system call
read -1 bytes, content is
程式立即結束啦,

但我們和第一次相比也觀察到很奇怪的結果

根據結果
比較,其實是第二次運行是把ctrl+c讀入,而第一次就是運行啦訊號處理函數,不把ctrl+c作為READ的讀入,

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.