How to use pipes for nonblocking IPC (UART emulation)
- by codebauer
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