C 命名管道,读取失败,文件描述符不正确

C 命名管道,读取失败,文件描述符不正确,c,linux,pipe,C,Linux,Pipe,我从Linux下的管道开始,我的代码有问题。 我想测试通过fifo发送一个整数,所以我编写了一个小程序来测试它 首先,我打开只读描述符,然后打开文档中精确描述的只读描述符。 我将数字发送到管道并关闭写入描述符 然而,当我试图从管道中读取时,它说我的文件描述符不好,我不明白为什么它不工作,因为描述符是好的,并且有好的选项(O_RDONLY | O_NONBLOCK) 这是我的密码: void main(void) { int modePipeWrite, modePipeRead;

我从Linux下的管道开始,我的代码有问题。 我想测试通过fifo发送一个整数,所以我编写了一个小程序来测试它

首先,我打开只读描述符,然后打开文档中精确描述的只读描述符。 我将数字发送到管道并关闭写入描述符

然而,当我试图从管道中读取时,它说我的文件描述符不好,我不明白为什么它不工作,因为描述符是好的,并且有好的选项(O_RDONLY | O_NONBLOCK)

这是我的密码:

void main(void)
{
    int modePipeWrite, modePipeRead;

    if(mkfifo("test.fifo", 0777) == -1)
    {
        perror("mkfifo");
        exit(EXIT_FAILURE);
    }
    if(modePipeRead = open("test.fifo", O_RDONLY | O_NONBLOCK) == -1)
    {
        perror("openRead");
        exit(EXIT_FAILURE);
    }
    if(modePipeWrite = open("test.fifo", O_WRONLY | O_NONBLOCK) == -1)
    {
        perror("openWrite");
        exit(EXIT_FAILURE);
    }


    int n = 0;

    if(write(modePipeWrite, &n, sizeof(n)) == -1)
    {
        perror("write");
    }
    printf("Send value: %d\n", n);

    close(modePipeWrite);


    int mode;

    while(1)
    {
        if(read(modePipeRead, &mode, sizeof(mode)) == -1)
        {
            perror("read");
        }
        printf("Received value: %d\n", getpid(), mode);
        sleep(1);
    }
}
以及输出:

./a.out
Send value: 0

read: Bad file descriptor
Received value: -1877110288

read: Bad file descriptor
Received value: -1877110288

read: Bad file descriptor
Received value: -1877110288

我不明白这里会出什么问题。如果有人有什么建议,我会很高兴听到的。

您的代码有几个问题,如果您在编译时启用了所有警告,就会发现这些问题。如果使用gcc,则以下选项是很好的/必需的: -沃尔-韦斯特拉-沃罗-迂腐

一个问题是没有将open()的返回值分配给文件描述符。您需要在赋值周围添加大括号,或将其移出if语句

下面是一个工作示例,使用线程读取:

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

#include <pthread.h>

static void *reader(void *arg)
{   
    int fd, val;

    if ((fd = open("test.fifo", O_RDONLY)) == -1) {
        perror("openRead");
        exit(EXIT_FAILURE);
    }

    if (read(fd, &val, sizeof val) == -1)
        perror("read");
    else
        printf("Received value: %d\n", val);

    close(fd);
    return NULL;
}

int main(void)
{   
    int modePipeWrite, modePipeRead;
    pthread_t readerid;


    if (mkfifo("test.fifo", 0777) == -1) {
        perror("mkfifo");
        exit(EXIT_FAILURE);
    }
    pthread_create(&readerid, NULL, reader, NULL);
    sleep(1);

    if ((modePipeWrite = open("test.fifo", O_WRONLY)) == -1) {
        perror("openWrite");
        exit(EXIT_FAILURE);
    }

    int n = 1234;

    if (write(modePipeWrite, &n, sizeof n) == -1)
        perror("write");
    else
        printf("Sent value: %d\n", n);

    sleep(1);
    close(modePipeWrite);

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态void*读卡器(void*arg)
{   
int-fd,val;
如果((fd=open(“test.fifo”,仅限ordu))=-1){
perror(“openRead”);
退出(退出失败);
}
如果(读取(fd,&val,sizeof val)=-1)
佩罗(“阅读”);
其他的
printf(“收到的值:%d\n”,val);
关闭(fd);
返回NULL;
}
内部主(空)
{   
int modePipeWrite,modePipeRead;
pthread\u t readerid;
如果(mkfifo(“test.fifo”,0777)=-1){
佩罗(“mkfifo”);
退出(退出失败);
}
pthread_create(&readerid,NULL,reader,NULL);
睡眠(1);
如果((modePipeWrite=open(“test.fifo”,仅限O_wr))=-1){
perror(“openWrite”);
退出(退出失败);
}
int n=1234;
if(write(modePipeWrite,&n,sizeof n)=-1)
佩罗(“书面”);
其他的
printf(“发送值:%d\n”,n);
睡眠(1);
关闭(modePipeWrite);
返回0;
}

我无法立即解释问题的确切性质,但管道是进程间通信的一种机制。它们既不适合也不适合单个进程与自身进行通信。我想在完成对管道的读取之前,不应该关闭管道。也许,@mustaccio,但他将读取和写入端作为单独的文件打开,所以这一点都不清楚。我怀疑这是(1)在非阻塞模式下打开两端,(2)在同一进程中,以及(3)在读取之前关闭写入端的部分或全部组合。可能删除
O_NONBLOCK
?请注意,从用户程序的角度来看,Linux中有两种不同类型的管道:命名管道,也称为FIFO,以及通过
pipe()
函数创建的匿名管道。后者是目前最常用的。我不知道它有那么简单。。。非常感谢你的帮助,它正如我所期待的那样工作。只是一个问题,我如何将一个整数从shell写入管道?因为当我在执行“cat 4>test.fifo”时,读取值变为2612,但当我在另一个程序中执行此操作时,它是正常的。4只是一个ASCII值。您需要将其转换为四字节整数,或者——更好的做法是——读取程序中的文本并将其转换为整数。(也许fdopen()和fscanf()会有用?)我认为可以告诉shell将4作为整数值进行解释。无论这与主题有什么关系,我都会在后面深入探讨。再次感谢;)