我正在尝试如何在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/