如何从 unix 管道建立非阻塞读取?

how to establish a non blocking read from unix pipes?

假设我们有一个管道 int InPipe[2];。当读取整个可用数据输入时,如何在管道为空之前读取输入而不阻塞?

我知道这个问题已经被问过好几次了,但是我找不到assemble合适的函数。

到目前为止,这是我的代码:

int InPipe[2];
char buffer[1024];
int rc;
while (true){
    read(InPipe[0], buffer, sizeof(buffer));
    fprintf(stdout, “%s“, buffer);
    bzero(&buffer, sizeof(buffer)); // Clearing Buffer
} 

任何想法、建议、代码片段

从管道读取

Attempts to read from a pipe that is currently empty block until at least one byte has been written to the pipe. If the write end of a pipe is closed, then a process reading from the pipe will see end-of-file (i.e., read() returns 0) once it has read all remaining data in the pipe.

取自linux界面编程。

你不能!在这种情况下,从管道读取的进程将被阻塞。

由于人们的评论,我添加了这一部分:

我们可以使用 pipe 来允许两个进程之间的通信。要使用管道连接两个进程,我们在 pipe() 调用之后调用 fork()。在 fork() 之后,一个进程立即关闭其管道写入端的描述符,另一个进程关闭其读取端的描述符。例如,如果父进程要向子进程发送数据,那么它将关闭管道的读描述符filedes[0],而子进程将关闭管道的写描述符filedes[1],然后代码为:

int filedes[2];    

if (pipe(filedes) == -1)   /* Create the pipe */        
    errExit("pipe");    

switch (fork())        /* Create a child process */
{                              
case -1:        
    errExit("fork");    
case 0:             /* Child */       
    if (close(filedes[1]) == -1)            /* Close unused write end */            
        errExit("close");        

    /* Child now reads from pipe */        
    break;    

default: /* Parent */        
    if (close(filedes[0]) == -1)            /* Close unused read end */            
        errExit("close");        
    
    /* Parent now writes to pipe */        
    break;    
}

评论中提到了一些关键事项,即非阻塞 IO、在自己的线程中执行读取,以及其他一些建议。 The example here 详细解释了它的架构。下面只转载了代码部分,因为我认为它是对其中一些评论的一个很好的说明。示例代码在整个过程中都有注释。阅读它们,它们是一个很好的教程:

// C program to demonstrate use of fork() and pipe() 
#include<stdio.h> 
#include<stdlib.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<string.h> 
#include<sys/wait.h> 
  
int main() 
{ 
    // We use two pipes 
    // First pipe to send input string from parent 
    // Second pipe to send concatenated string from child 
  
    int fd1[2];  // Used to store two ends of first pipe 
    int fd2[2];  // Used to store two ends of second pipe 
  
    char fixed_str[] = "forgeeks.org"; 
    char input_str[100]; 
    pid_t p; 
  
    if (pipe(fd1)==-1) 
    { 
        fprintf(stderr, "Pipe Failed" ); 
        return 1; 
    } 
    if (pipe(fd2)==-1) 
    { 
        fprintf(stderr, "Pipe Failed" ); 
        return 1; 
    } 
  
    scanf("%s", input_str); 
    p = fork(); //Note - the return of fork can be less than, greater
                //       than or equal to zero.  Each is significant in
                //       knowing how to direct program flow, as shown 
                //       in this section...
  
    if (p < 0) 
    { 
        fprintf(stderr, "fork Failed" ); 
        return 1; 
    } 
  
    // Parent process 
    else if (p > 0) 
    { 
        char concat_str[100]; 
  
        close(fd1[0]);  // Close reading end of first pipe 
  
        // Write input string and close writing end of first 
        // pipe. 
        write(fd1[1], input_str, strlen(input_str)+1); 
        close(fd1[1]); 
  
        // Wait for child to send a string 
        wait(NULL); 
  
        close(fd2[1]); // Close writing end of second pipe 
  
        // Read string from child, print it and close 
        // reading end. 
        read(fd2[0], concat_str, 100); 
        printf("Concatenated string %s\n", concat_str); 
        close(fd2[0]); 
    } 
  
    // child process 
    else
    { 
        close(fd1[1]);  // Close writing end of first pipe 
  
        // Read a string using first pipe 
        char concat_str[100]; 
        read(fd1[0], concat_str, 100); 
  
        // Concatenate a fixed string with it 
        int k = strlen(concat_str); 
        int i; 
        for (i=0; i<strlen(fixed_str); i++) 
            concat_str[k++] = fixed_str[i]; 
  
        concat_str[k] = '[=10=]';   // string ends with '[=10=]' 
  
        // Close both reading ends 
        close(fd1[0]); 
        close(fd2[0]); 
  
        // Write concatenated string and close writing end 
        write(fd2[1], concat_str, strlen(concat_str)+1); 
        close(fd2[1]); 
  
        exit(0); 
    } 
}