Linux管道和sigaction

时间:2018-03-26 10:08:28

标签: c linux pipe

我有一些代码,我正在捕捉SIGIO信号。我想写一个应用程序,它将被告知有关到达管道的数据。我故意不想使用select()函数。 这是代码:

void handler (int x)
{
    int fd, st;
    char buf[32];
    printf("signal_entry\n");
    fd = open("/tmp/pipe",  O_RDWR);
    memset(buf, 0, sizeof(buf));
    st = read(fd, buf, 32);
    printf("st: %d  buf: %s\n", st, buf);
    close(fd);
    printf("signal_exit\n\n");
}

int main (void)
{
    int fd, sf, fl, st, num;
    struct stat sb;

    fd = open("/tmp/pipe", O_RDWR);
    memset(&act1, 0, sizeof(act1));
    sigfillset(&act1.sa_mask);
    act1.sa_handler = handler;
    sigaction(SIGIO, &act1, NULL);
    sf = fcntl(fd, F_SETOWN, getpid());
    fl = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, fl | O_ASYNC);
    while (1) {
        printf("x\n");
        sleep(1);
    }
}

运行后每隔1秒显示“x”字母。然后我在管道/ tmp / pipe中写了一些东西:

echo "bla" > /tmp/pipe.

程序的反应是它从管道中读取数据(字符串“bla”)并显示其内容 - 这没关系。

问题是应用程序再次调用我的SIGIO处理程序。我的意思是“handler”proc被无限调用,因此main()proc中的“while”循环不再运行。

为什么会出现这种影响?我错过了什么吗?我认为每个“echo”调用只会调用一次“handler”...

2 个答案:

答案 0 :(得分:1)

echo - 命令终止后,您打开的管道" main"是EOF,所以它会不断触发SIGIO事件(即管道上的EOF)。 所以你必须在main函数中重新打开管道才能让它再次运行。

然而,在处理程序中重新打开管道没有任何意义。只需使用open()中的fd - main()中的来电。

答案 1 :(得分:0)

我想我解决了这个问题。

需要在main()中进行更改:

fd = open("/tmp/pipe", O_RDONLY | O_NONBLOCK);

当然应该删除handler()中的open()。 现在它运作正常。