如何在管道文件描述符的线程块中创建 read()?

how to make read() in thread block on a pipe's file descriptor?

我正在试验如何在 C 中的线程和主函数之间进行通信 以下代码中存在我不理解的行为:

#include <pthread.h>

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

void* output(void* pipe1);

int main(int argc, const char *argv[])
{
    pthread_t   tid0;
    int         pipe1[2];
    char        buffer[200];

// Creating the pipe
    pipe(pipe1);
// Creating the thread and passing the pipe as argument
    pthread_create(&tid0, NULL, output, &pipe1);
// Input from user
    scanf("%s", buffer);
// Writing to the pipe
    write(pipe1[1], buffer, strlen(buffer));
    return 0;
}

void* output(void* pipe1) {
     char buffer[200];

// Reading the pipe and print the buffer
     read(((int*)pipe1)[0], buffer, strlen(buffer));
     printf("thread say: %s\n", buffer);
     pthread_exit(NULL);
}

为什么读取函数不会阻塞管道的文件描述符?

也许我应该关闭管道的末端,但由于它们共享相同的内存space,当我调用读取或写入时返回错误"bad file descriptor"。

如果管道确实是一个糟糕的解决方案,也许你可以指导我使用其他方法(举个例子,它会很棒!:))

非常感谢!

编辑:解决方案

非常感谢您的回答,这里是具有预期行为的代码

#include <pthread.h>

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

void* output(void* pipe1);

int main(int argc, const char *argv[])
{
    pthread_t   tid0;
    int         pipe1[2];
    char        buffer[200];

// Creating the pipe
    pipe(pipe1);
// Creating the thread and passing the pipe as argument
    pthread_create(&tid0, NULL, output, &pipe1);

// Input from user
    scanf("%s", buffer);
// Writing to the pipe
    if (write(pipe1[1], buffer, strlen(buffer)) < 0) {
        perror("write");
        exit(1);
    }
    // join so the main "wait" for the thread
    pthread_join(tid0, NULL);
    return 0;
}


void* output(void* pipe1) {
    char        buffer[200];
    int         nread;

// Reading the pipe and print the buffer
    nread = read(((int*)pipe1)[0], buffer, sizeof buffer - 1);
    if (nread < 0) {
        fprintf(stderr, "ERROR\n");
        perror("read");
        exit(1);
    }
    buffer[nread] = '[=11=]';
    fprintf(stderr, "thread say: %s\n", buffer);
    pthread_exit(NULL);
}
char buffer[200];
read(((int*)pipe1)[0], buffer, strlen(buffer));

您正在对未初始化的缓冲区调用 strlen。这允许使您的程序崩溃。相反,你很幸运,它所做的只是告诉 read 读取零字节,所以 read 没有做任何事情就返回了。

你真正想要的是

ssize_t nread = read(((int *)pipe1)[0], buffer, sizeof buffer - 1);
if (nread < 0) {
    perror("read");
    return 0;
}
buffer[nread] = '[=11=]';

read 想要被告知的是 space 你给它读了多少,而不是可能或可能还没有在 space 中。那是 sizeof buffer,减一所以我们总是有 space 添加字符串终止符。

时使用strlen是正确的,因为你只想写实际的字符串,而不是任何可能超出字符串末尾的垃圾;但是 write 不会将字符串终止符写入管道,因此 read 不会 读取 一个,因此您必须手动添加它。当然,还要经常检查错误。

此外,请记住线程 运行 同时 。即使修复了这个错误,write 可能在 reader-thread 调用 read 时已经发生,如果没有,它可能很快就会发生。如果你想观察 reader-thread 实际上阻塞在 read 你需要在调用 write.

之前延迟