无法使用writefds从select()获得正确的响应

时间:2013-05-30 07:37:39

标签: linux select

父接收SIGPIPE通过FIFO管道向中止的子进程发送字符。 我试图使用select()函数来避免这种情况。在附带的示例代码中, 即使在管道另一端的子节点终止后,select()也会重新运行OK。 测试中     RedHat EL5(Linux 2.6.18-194.32.1.el5)     GNU C库稳定版本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);
}

1 个答案:

答案 0 :(得分:2)

来自Linux select(3) man page

  

当呼叫时,描述符应被视为已准备好写入   无论是否清除,O_NONBLOCK清除的输出功能都不会阻塞   该函数将成功传输数据。

当管道关闭时,它不会阻塞,因此被select视为“准备好”。

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

虽然select()poll()都在POSIX标准中,但poll()poll()更老,更有限。一般来说,我建议人们默认使用select(),如果他们有充分的理由,则只使用{{1}}。 (参见one example。)