簡體   English   中英

如何使管道的文件描述符上的線程塊中的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);
}

為什么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不會讀取一個終止符,因此您必須手動添加它。 並且,當然,請始終檢查錯誤。

另外,請記住線程同時運行。 即使修復了此錯誤,在讀者線程調用readwrite可能已經發生,並且如果沒有,可能很快就會發生。 如果要觀察讀取器線程實際上阻塞了read ,則需要在調用write之前進行延遲。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM