【发布时间】:2019-08-20 02:17:49
【问题描述】:
来自APUE:
防止应用程序不得不处理中断的系统 调用,4.2BSD引入了某些自动重启 中断的系统调用。自动进行的系统调用 重新启动的是
ioctl、read、readv、write、writev、wait和waitpid。作为 我们已经提到,前五个函数被 仅当它们在慢速设备上运行时才发出信号;wait和waitpid当信号被捕获时总是被中断。因为这会导致 一些不想重新启动操作的应用程序的问题 如果它被中断,4.3BSD 允许进程禁用它 基于每个信号的功能。
是不是说在引入自动重启之前,如果进程捕捉到信号,wait和waitpid会立即停止等待并执行后续代码?
例如:
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void handler(int sig){}
void handler2(int sig){}
int main(){
pid_t pid;
int status;
signal(SIGUSR1, handler);
signal(SIGUSR2, handler2);
if((pid == fork()) < 0){
printf("fork error\n");
}else{
if(pid){
//child
//do something, needs several hours.
}else{
//parent
waitpid(pid, &status, 0);
printf("Hello world\n");
}
}
return 0;
}
如果不提供自动重启,当我在后台运行这个程序gcc test.c && ./a.out &,然后我发送一个信号kill -SIGUSR1 pid 或kill -SIGUSR2 pid,waitpid 会返回并且后面的代码waitpid(pid, &status, 0); 会执行。
如果提供自动重启,waitpid 将再次执行,而父级将继续等待。
我的理解正确吗?
【问题讨论】:
-
中断的系统调用将返回 -1(或任何用于指示错误的值)并将
errno设置为EINTR。接下来发生的事情取决于调用者如何处理这种情况。如果它是可重新启动的,它不会返回那个特定的 errno 代码,除非另有说明这样做。它会继续运行,直到由于其他原因返回为止。 -
请注意,您应该使用
sigaction()而不是signal()来获得对此的控制权,并且sigaction()提供了一个控制标志SA_RESTART来指定是否应在收到信号后恢复系统调用处理。 -
@JonathanLeffler 但是,
signal()默认情况下确实现在在 linux 和 bsd 上应用重启行为(至少)
标签: c unix signals wait interrupt