How to use pipes for nonblocking IPC (UART emulation)

Posted by codebauer on Stack Overflow See other posts from Stack Overflow or by codebauer
Published on 2010-12-22T11:28:07Z Indexed on 2010/12/22 11:54 UTC
Read the original article Hit count: 363

Filed under:
|
|

I would like to write some test/emulation code that emulates a serial port connection. The real code looks like this:

DUT <- UART -> testtool.exe

My plan is to use create a test application (CodeUnderTest.out) on linux that forks to launch testool.out with two (read & write) named pipes as arguments. But I cannot figure out how to make all the pipe IO non-blocking!

The setup would look like this:.

CodeUnderTest.out <- named pipes -> testTool.out (lauched from CodeUnderTest.out)

I have tried opening the pipes as following:

open(wpipe,O_WRONLY|O_NONBLOCK);
open(rpipe,O_RDONLY|O_NONBLOCK);

But the write blocks until the reader opens the wpipe. Next I tried the following:

open(wpipe,O_RDWR|O_NONBLOCK);
open(rpipe,O_RDONLY|O_NONBLOCK);

But then the reader of the first message never gets any data (doesn't block though)

I also tried adding open and close calls around each message, but that didn't work either...

Here is some test code:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

pid_t pid;
char* rpipe, *wpipe,*x;
FILE *rh,*wh;
int rfd,wfd;

void openrpipe( void )
   {
   rfd = open(rpipe,O_RDONLY|O_NONBLOCK);
   rh = fdopen(rfd,"rb");
   printf("%sopeningr %x\n",x,rh);
   }
void openwpipe( void )
   {
   //Fails when reader not already opened
   //wfd = open(wpipe,O_WRONLY|O_NONBLOCK);
   wfd = open(wpipe,O_RDWR|O_NONBLOCK);
   wh = fdopen(wfd,"wb");
   printf("%sopeningw %x\n",x,wh);
   }
void closerpipe( void )
   {
   int i;
   i = fclose(rh);
   printf("%sclosingr %d\n",x,i);
   }
void closewpipe( void )
   {
   int i;
   i = fclose(wh);
   printf("%sclosingw %d\n",x,i);
   }
void readpipe( char* expect, int len)
   {
   char buf[1024];
   int i=0;
   printf("%sreading\n",x);
   while(i==0)
      {
      //printf(".");
      i = fread(buf,1,len,rh);
      }
   printf("%sread (%d) %s\n",x,i,buf);
   }
void writepipe( char* data, int len)
   {
   int i,j;
   printf("%swriting\n",x);
   i = fwrite(data,1,len,rh);
   j = fflush(rh); //No help!
   printf("%sflush %d\n",x,j);
   printf("%swrite (%d) %s\n",x,i,data);
   }
int main(int argc, char **argv)
   {
   rpipe = "readfifo";
   wpipe = "writefifo";
   x = "";
   pid = fork();
   if( pid == 0)
      {
      wpipe = "readfifo";
      rpipe = "writefifo";
      x = "   ";
      openrpipe();
      openwpipe();
      writepipe("paul",4);
      readpipe("was",3);
      writepipe("here",4);
      closerpipe();
      closewpipe();
      exit(0);
      }
   openrpipe();
   openwpipe();
   readpipe("paul",4);
   writepipe("was",3);
   readpipe("here",4);
   closerpipe();
   closewpipe();
   return( -1 );
   }

BTW: To use the testocd above you need to pipes in the cwd:

mkfifo ./readfifo

mkfifo ./writefifo

© Stack Overflow or respective owner

Related posts about linux

Related posts about ipc