gpt4 book ai didi

c - 如何在管道的文件描述符上的线程 block 中进行 read() ?

转载 作者:行者123 更新时间:2023-11-30 16:32:04 24 4
gpt4 key购买 nike

我正在尝试如何在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);
}

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

也许我应该关闭管道的末端,但由于它们共享相同的内存空间,因此当我调用 read 或 write 时会返回错误“错误文件描述符”。

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

非常感谢!

编辑:解决方案

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

#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] = '\0';
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] = '\0';

read 想要知道的是您要给它读入多少空间,而不是该字符串中可能存在或尚未存在的任何字符串的长度空间。这是 sizeof buffer 减一,这样我们总是有空间来添加字符串终止符。

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

此外,请记住线程同时运行。即使修复了此错误后,当读取器线程调用 read 时,write 可能已经发生,如果还没有发生,它可能很快就会发生。如果您想观察读取线程在读取时实际阻塞,则需要在调用写入之前延迟。

关于c - 如何在管道的文件描述符上的线程 block 中进行 read() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50309109/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com