系統調用可分為兩類:慢速系統調用和其他系統調用
- 慢速系統調用:可能會使進程永遠阻塞的一類,如果在阻塞期間收到一個信號,該系統調用就被中斷,不再繼續執行(早期);也可以設定系統調用是否重啟。如:read、write、pause、wait等等
- 其他系統調用:getpid、getppid、fork...
結合pause,回顧慢速系統調用:
- 想中斷pause,信號不能被屏蔽
- 信號的處理方式必須是捕捉(默認、忽略都不可以)
- 中斷后返回-1,設置errno為EINTR(表“被信號中斷”)
可修改sa_flags參數來設置被信號中斷系統調用是否重啟。SA_INTERRURT 不重啟。SA_RESTART重啟。
擴展了解:
sa_flags還有許多可選參數,適用不同情況,如:捕捉到信號后,在執行捕捉函數期間,不希望屏蔽該信號,可將sa_flags設置為SA_NODEFER,除非sa_mask中包含該信號。
?
1. 測試代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>void int_handler(int signum)
{printf("int handler %d\n", signum);
}int main(int argc, char **argv)
{char buf[100];ssize_t ret;struct sigaction oldact;struct sigaction act;act.sa_handler = int_handler;act.sa_flags = 0;act.sa_flags |= SA_RESTART;sigemptyset(&act.sa_mask);if (-1 == sigaction(SIGINT, &act, &oldact)) {printf("sigaction failed!\n");return -1;}bzero(buf, 100);ret = read(STDIN_FILENO, buf, 10);if (ret == -1) {printf("read error %s\n", strerror(errno));}printf("read %d bytes, content is %s\n", (int)ret, buf);sleep(10);return 0;
}
輸出結果:
?
?
2. 測試代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>void int_handler(int signum)
{printf("int handler %d\n", signum);
}int main(int argc, char **argv)
{char buf[100];ssize_t ret;struct sigaction oldact;struct sigaction act;act.sa_handler = int_handler;act.sa_flags = 0;// act.sa_flags |= SA_RESTART;sigemptyset(&act.sa_mask);if (-1 == sigaction(SIGINT, &act, &oldact)) {printf("sigaction failed!\n");return -1;}bzero(buf, 100);ret = read(STDIN_FILENO, buf, 10);if (ret == -1) {printf("read error %s\n", strerror(errno));}printf("read %d bytes, content is %s\n", (int)ret, buf);sleep(10);return 0;
}
輸出結果:
?
參考資料
1.?linux SA_RESTART的問題
2.?44-中斷系統調用與自動重啟動