[英]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);
}
為什么read函數不會在管道的文件描述符上阻塞?
也許我應該關閉管道的末端,但是由於它們共享相同的內存空間,因此當我調用讀或寫時會返回錯誤“壞文件描述符”。
如果管道確實是一個不好的解決方案,也許您可以指導我使用其他方法(舉個例子,這太神奇了!:))
非常感謝 !
編輯:解決方案
非常感謝您的回答,這里是具有預期行為的代碼
#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
可能已經發生,並且如果沒有,可能很快就會發生。 如果要觀察讀取器線程實際上阻塞了read
,則需要在調用write
之前進行延遲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.