测试代码如下
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<string.h> static void sigfunc(int signo) { if(signo == SIGUSR1) { printf("receive sigusr1\n"); } } int main() { char str[10]; if(signal(SIGUSR1, sigfunc) == SIG_ERR) return -1; while(1) { memset(str, 0, sizeof(str)); read(fileno(stdin), str, 10); printf("read from stdin\n"); printf("%s",str); } return 0; }
编译该代码,执行,会阻塞在read上,此时使用kill(1)发送一个SIGUSR1信号给该程序,若自动重启由信号中断的系统,则不会立马输出read from stdin。
kill -USR1 pid
测试结果表明linux系统确实重启了read系统调用。
另附上apue上的一段话:
对于中断的read,write系统调用,(read)允许该系统调用成功返回,返回已经收到的部分数据量,(write)允许该系统调用成功返回,返回也写的部分数据量。
我的理解是:
测试代码中的read是一个字节都没有读,所以重启了,但是上面一段话的意思是已经读/写了,但未读/写完时,依照posix标准,返回成功,即不重设errno
//上面的是linux下的默认处理方法,使用sigaction可以改变
代码如下:
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<string.h> typedef void (*Sigfunc)(int); Sigfunc signal_intr(int signo, Sigfunc func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_flags |= SA_INTERRUPT; if(sigaction(signo, &act, &oact) < 0) return (SIG_ERR); return oact.sa_handler; } void sigfunc(int) { printf("receive SIGUSR1\n"); } int main() { char str[10]; if(signal_intr(SIGUSR1, sigfunc) == SIG_ERR) return -1; while(1) { memset(str, 0, sizeof(str)); read(fileno(stdin), str, 10); printf("receive.\n"); printf("%s", str); } }
即阻塞在read时收到SIGUSR1信号后输出如下:
receive SIGUSR1 receive.
if(read(fileno(stdin), str, 10) < 0) { if(errno == EINTR) { printf("interrupted by signal.\n"); } }
那么再被信号中断后,下面提示也会输出
interrupted by signal.