linux2.6下系统调用被信号中断时的响应

测试代码如下

#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读取数据,read是一个低速系统调用,按照posix.1标准,默认的方式是重启由信号中断的系统调用,

编译该代码,执行,会阻塞在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);
	}  
}

改变是使用了SA_INTERRUPT标记,它将使sigaction函数不再重启被中断的系统调用。

即阻塞在read时收到SIGUSR1信号后输出如下:

receive SIGUSR1
receive.

之后再经while迭代到read阻塞中。如果read那里改成如下形式

if(read(fileno(stdin), str, 10) < 0)
{
     if(errno == EINTR)
     {
          printf("interrupted by signal.\n");
     }
}

那么再被信号中断后,下面提示也会输出

interrupted by signal.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值