BigSur
BigSur

Reputation: 29

how to establish a non blocking read from unix pipes?

Let‘s assume we have a pipe int InPipe[2];. How can you read the input until the pipe is empty without blocking when the whole available Data input was read?

I know this question has been asked several times, but I couldn’t assemble a suitable function.

This is my Code so far:

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
} 

Any Ideas, Suggestions, Code Snippets

Upvotes: 1

Views: 1383

Answers (2)

ryyker
ryyker

Reputation: 23228

There are a couple of key things mentioned in the comments, i.e. non-blocking IO, and performing the read in its own thread, along with some other suggestions. The example here goes into detail explaining its architecture. Only the code section is reproduced below as I believe it to be a decent illustration of several of these comments. The example code is commented throughout. Read them, they serve as a good tutorial:

// 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] = '\0';   // string ends with '\0' 
  
        // 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); 
    } 
} 

Upvotes: 3

AdamF
AdamF

Reputation: 2940

Reading from a pipe

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.

taken from linux interface programming.

You cant! the process reading from the pipe will be blocked in this situation.

Due to people comments, i am adding this section:

we can use a pipe to allow communication between two processes. To con-nect two processes using a pipe, we follow the pipe() call with a call to fork(). immediately after the fork(), one process closes its descriptor for the write end of the pipe, and the other closes its descriptor for the read end. For example, if the parent is to send data to the child, then it would close its read descriptor for the pipe, filedes[0], while the child would close its write descriptor for the pipe, filedes[1], then the code for this will be:

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;    
}

Upvotes: 3

Related Questions