Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 非阻塞读取管道_C_Linux_Pipe_Glibc - Fatal编程技术网

C 非阻塞读取管道

C 非阻塞读取管道,c,linux,pipe,glibc,C,Linux,Pipe,Glibc,可以在管道上执行非阻塞I/O吗?fcntl无法设置O_非块。Linux编程接口的第918页包含一个表“从管道或FIFO(p)读取n字节的语义”。此表列出了管道和FIFO的行为,其中一列标题为O_NONBLOCK enabled?这意味着您可以在管道上设置O_NONBLOCK标志。这是正确的吗?以下代码未能设置标志,但fcntl(2)未报告错误 #include <fcntl.h> #include <sys/wait.h> #include <stdlib.h>

可以在管道上执行非阻塞I/O吗?fcntl无法设置O_非块。Linux编程接口的第918页包含一个表“从管道或FIFO(p)读取n字节的语义”。此表列出了管道和FIFO的行为,其中一列标题为O_NONBLOCK enabled?这意味着您可以在管道上设置O_NONBLOCK标志。这是正确的吗?以下代码未能设置标志,但fcntl(2)未报告错误

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

#define SLEEP 1

int
main(int argc, char *argv[]) {
    pid_t childPid;
    int pfd[2];
    int nread, flags;
    int c = 'a';    

    setbuf(stdout, NULL);

    if (pipe(pfd) == -1) {
        printf("error: pipe");
        exit(EXIT_FAILURE);
    }

    switch (childPid = fork()) {
    case -1:
        printf("error: fork");
        exit(EXIT_FAILURE);
    case 0:         /* child */
        if (close(pfd[0]) == -1) {
            printf("child: close pfd read");
            exit(EXIT_FAILURE);
        }
        sleep(SLEEP);
        _exit(EXIT_SUCCESS);
    default:
        break;
                /* parent falls through */
    }
    if (close(pfd[1]) == -1) {
        printf("parent: close pipe write");
        exit(EXIT_FAILURE);
    }

    flags = fcntl(pfd[0], F_GETFD);
    flags |= O_NONBLOCK;
    if (fcntl(pfd[0], F_SETFD, flags))
        perror("fcntl");

    /* verify flags set correctly */
    flags = fcntl(pfd[0], F_GETFD);
    if (!(flags & O_NONBLOCK))  {
        printf("failed to set O_NONBLOCK\n");
        exit(EXIT_FAILURE);
    }

    wait(NULL);
    exit(EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
#包括
#定义睡眠1
int
main(int argc,char*argv[]){
pid_t childPid;
int-pfd[2];
国际nread,旗帜;
int c='a';
setbuf(标准输出,空);
如果(管道(pfd)=-1){
printf(“错误:管道”);
退出(退出失败);
}
开关(childPid=fork()){
案例1:
printf(“错误:fork”);
退出(退出失败);
案例0:/*儿童*/
如果(关闭(pfd[0])=-1){
printf(“子项:关闭pfd读取”);
退出(退出失败);
}
睡眠;
_退出(退出成功);
违约:
打破
/*父母破产*/
}
如果(关闭(pfd[1])=-1){
printf(“父:关闭管道写入”);
退出(退出失败);
}
标志=fcntl(pfd[0],F_GETFD);
标志|=O|U非块;
if(fcntl(pfd[0],F_设置,标志))
perror(“fcntl”);
/*验证标志设置是否正确*/
标志=fcntl(pfd[0],F_GETFD);
如果(!(标志和O_非块)){
printf(“未能设置O_非块\n”);
退出(退出失败);
}
等待(空);
退出(退出成功);
}

管道和O_非阻塞没有什么特殊之处。下面的示例按预期工作。我没有检查每个调用的每个retval,以使示例更具可读性。实际应用程序必须进行检查

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

int main()
{
    int fds[2];
    pid_t pid;
    char buf[100];

    pipe(fds);

    pid = fork();

    if ( pid )
    {
        while (1 )
        {
            memcpy( buf, "abcdefghi\0",10);
            write( fds[1], buf, 10);
            sleep(2);
        }
    }
    else
    {
        int retval = fcntl( fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | O_NONBLOCK);
        printf("Ret from fcntl: %d\n", retval);
        while (1)
        {
            ssize_t r=read( fds[0], buf, 10 );
            printf("read: %d\n", r);

            if ( r > 0 )
            {
                printf("Buffer: %s\n", buf);
            }
            else
            {
                printf("Read nothing\n");
                perror("Error was");
                sleep(1);
            }
        }
    }
}
请将
F_SETFD
更改为
F_SETFL
,并将其更改为get操作。您不会更改
文件描述符标志
,而是更改
文件状态标志
:-)

man 3 fcntl

文件描述符标志 以下命令操作与文件关联的标志 描述符。目前,只定义了一个这样的标志:FD_CLOEXEC 关闭exec标志。如果FD_CLOEXEC位为0,则文件描述符 将在execve(2)中保持打开状态,否则它将关闭

文件状态标志 每个打开的文件描述都有特定的相关状态标志ini‐ 通过open(2)初始化,并可能通过fcntl()修改。重复文件 描述符(由dup(2)、fcntl(F_DUPFD)、fork(2)等组成)指 相同的打开文件描述,因此共享相同的文件状态 旗帜

F_SETFL(内部) 将文件状态标志设置为arg指定的值。文件 访问模式(O_RDONLY、O_WRONLY、O_RDWR)和文件创建标志 arg中的(即O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)被忽略。 在Linux上,此命令只能更改O_APPEND、O_ASYNC、, O_DIRECT、O_NOATIME和O_NONBLOCK标志。这是不可能的 更改O_数据同步和O_同步标志;请参阅下面的BUGS


它看起来像是
F_GETFD
操作中的一个bug。我已经确认,这实际上设置了描述符非阻塞,操作也不阻塞,但是
F_GETFD
仍然返回零。抓好了Klaus,我感觉这是我在做的傻事。谢谢你抽出时间。
flags = fcntl(pfd[0], F_GETFD);
flags |= O_NONBLOCK;
if (fcntl(pfd[0], F_SETFD, flags))