OS / Linux / 系统阻塞在系统调用中时如果收到信号,系统如何处理?

今天在看《深入 Linux 内核架构》这本书的时候,看到如题的场景。

之前的处理方式是检测系统调用函数的返回值,如果返回值为 -1 并且 errno 是 EINTR ,那么就知道了该系统调用被中断打断了,需要重新调用该函数。

栗子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

volatile int signaled = 0;

void handler(int)
{
    printf("signaled called\n");
    signaled = 1;
}

int main(int argc, char *argv[])
{
    char ch;
    struct sigaction sigact;
    sigact.sa_handler = handler;
    //sigact.sa_flags = SA_RESTART;
    sigaction(SIGINT, &sigact, NULL);

    while (read(STDIN_FILENO, &ch, 1) == -1)
        printf("signaled call err info = %s\n",  strerror(errno));

    return 0;
}

运行之后不断地执行 Ctrl + C 时,会不断的显示如下内容:

signaled call err info = Interrupted system call

因为在阻塞 read 函数的时候收到了中断信号,导致系统调用函数提前返回。

上述是传统的做法,今天看书中还有另外一种做法,是 linux 参考 BSD 方案,大致流程是当系统阻塞在 read 函数中时,如果系统收到了中断信号,系统调用不会提前返回,内核会在信号处理程序执行结束之后自动重启该调用。

启动上述功能的代码是:

sigact.sa_flags = SA_RESTART;

栗子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

volatile int signaled = 0;

void handler(int)
{
    printf("signaled called\n");
    signaled = 1;
}

int main(int argc, char *argv[])
{
    char ch;
    struct sigaction sigact;
    sigact.sa_handler = handler;
    sigact.sa_flags = SA_RESTART;
    sigaction(SIGINT, &sigact, NULL);

    while (read(STDIN_FILENO, &ch, 1) != 1 && !signaled)
        ;

    return 0;
}

运行之后不断地执行 Ctrl + C 时,会不断的显示如下内容:

signaled called

 因为程序阻塞在 read 函数,收到中断信号之后,由于内核自动重启了 read 函数,导致程序还是阻塞在 read 函数中,始终无法响应 signaled 的变化,导致程序无法正常退出。

拓展

查看 errno 值含义:

/usr/include/asm-generic/errno-base.h     或者    errno.h

 

(SAW:Game Over!)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值