1

父进程通过 FIFO 管道接收 SIGPIPE 发送字符到中止的子进程。我试图避免这种情况,使用 select() 函数。在附加的示例代码中,即使在管道另一端的子节点终止后,select() 也会返回 OK。在
RedHat EL5 中测试(Linux 2.6.18-194.32.1.el5) GNU C Library 稳定版 2.5 任何帮助表示赞赏。谢谢你。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>

static void sigpipe_fct();

main()
{
struct stat st;
int  i, fd_out, fd_in, child;
char buf[1024];
#define p_out "/tmp/pout"

    signal(SIGPIPE, sigpipe_fct);

    if (stat(p_out, &st) != 0)  {
        mknod(p_out, S_IFIFO, 0);
        chmod(p_out, 0666);
    }
    /* start receiving process */
    if ((child = fork()) == 0)  {
        if ((fd_in = open(p_out, O_RDONLY)) < 0)  {
            perror(p_out);
            exit(1);
        }
        while(1)  {
           i = read(fd_in, buf, sizeof(buf));
           fprintf(stderr, "child %d read %.*s\n", getpid(), i, buf);
           lseek(fd_in, 0, 0);
        }
    }
    else  {
        fprintf(stderr,
           "reading from %s - exec \"kill -9 %d\" to test\n", p_out, child);
        if ((fd_out = open(p_out, O_WRONLY + O_NDELAY)) < 0) { /*  output */
            perror(p_out);
            exit(1);
        }
        while(1)  {
            if (SelectChkWrite(fd_out) == fd_out)  {
                fprintf(stderr, "SelectChkWrite() success write abc\n");
                write(fd_out, "abc", 3);
            }
            else
                fprintf(stderr, "SelectChkWrite() failed\n");
            sleep(3);
        }
    }
}

static void sigpipe_fct()
{
    fprintf(stderr, "SIGPIPE received\n");
    exit(-1);
}

SelectChkWrite(ch)
int ch;
{
#include <sys/select.h>
fd_set  writefds;
int     i;

    FD_ZERO(&writefds);
    FD_SET (ch, &writefds);

    i = select(ch + 1, NULL, &writefds, NULL, NULL);

    if (i == -1)
        return(-1);
    else if (FD_ISSET(ch, &writefds))
        return(ch);
    else
        return(-1);
}
4

1 回答 1

2

从 Linuxselect(3)手册页

当对带有 O_NONBLOCK 清除的输出函数的调用不会阻塞时,无论该函数是否会成功传输数据,都应认为描述符已准备好写入。

当管道关闭时,它不会阻塞,因此它被认为是“准备就绪” select

顺便说一句,#include <sys/select.h> 你的SelectChkWrite()函数内部是非常糟糕的形式。

虽然select()poll()都在 POSIX 标准中,select()但比poll(). 一般来说,我建议人们poll()默认使用,并且仅select()在有充分理由的情况下使用。(见这里的一个例子。)

于 2013-05-30T07:49:37.453 回答