PDA

View Full Version : create and listen to a process



frs
07-12-2010, 04:18 PM
(Using C on ubuntu)

In my program I need to fork a process and execute a .bin in the child process. Then I want to create a pipe that "connects" the stdout of the child to the stdout of the parent. I know basically how to do this using write() and read() in the pipes.
The problem is that the parent should wait until the child sends a specific message (a string), or until a timeout occurs. In the first case both processes should run in "parallel" ( I don't know if its the correct term..), in the second case the child must abort and the parent go on. And I don't have a clue how to accomplish any of this things. Any suggestions ?

I made a very basic skeleton, comments?



int status;
int fd[2]; /* pipe */

if( pipe(fd) !=0 )
{
perror("Failed to create pipe");
exit(EXIT_FAILURE);
}

pid_t pid=fork();

if( pid<0)
{
perror("Failed to fork");
exit(EXIT_FAILURE);
}

else if(pid == 0) /* child */
{
if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1);
perror("Child unabled to start sixad");

exit(EXIT_FAILURE);
}

Salem
07-12-2010, 11:07 PM
Well reading a descriptor with a timeout is achieved by using the select() or poll() calls. These allow you to wait for something to arrive, or timeout if you choose.

As for detecting the demise of the child (with it's exit status), then look at the waitpid() call. This too has a "poll" mechanism.

frs
07-13-2010, 09:28 AM
if I use waitpid(), the calling process suspends its course until the child has terminated, isn't that correct?

frs
07-13-2010, 10:05 AM
I've the following question.



pid_t pid = fork();

if(pid == 0) /* child */
{
if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1);
{
perror("Child unabled to start sixad");
exit(EXIT_FAILURE);
}
printf("here");
}


The message "here" is only printed when execl() has finished?

Salem
07-13-2010, 10:57 AM
There is NO return is execl() is successful. You're running a different program after that point.

Besides, your if statement has a very telling ; at the end of it.

And how much manual page of waitpid did you actually read to miss WNOHANG ?

frs
07-13-2010, 11:58 AM
Thank you for the answers. WNOHANG returns immediately if no child has exited, I don't want that. The idea is forking, suspend the parent and exec( a program I can't modify ).
The exec program sends some messages to stdout and the parent should only continue after one specific message is received.

I apologize for some naive questions but I'm an electronics student, not informatics. I don't have much knowledge about processes and OS's.

frs
07-13-2010, 11:59 AM
When I fork() , the stdout and stdin are shared by both parent and child?

Elkvis
07-13-2010, 01:05 PM
When I fork() , the stdout and stdin are shared by both parent and child?

yes. when you fork, the child process gets a copy of *ALL* open file descriptors, including sockets, message queues, shared memory segments, etc (some of these may be platform-dependent). you can close the child's stdout descriptor, and then dup() it to use your pipe, and then you can listen to that file descriptor for output. I have actually written std::iostream-derived classes that do exactly this with stdin and stdout, so you can read/write a child process just like an ordinary file.

frs
07-16-2010, 11:00 AM
here's my effort. I've redirected stdout of the child to a pipe. The resulting output is on below.I still have some problems..

1- Can anyone explain why the parent process only reads from the pipe after the child has terminated?

2- Also, why "Connected PLAYSTATION(R)3 Controller (00:23:06:A4:E6:AA)" isn't sent into the pipe? this message is sent with syslog() instead of printf().



int fd[2];

if( pipe(fd) !=0 )
{
perror("Failed to create pipe");
exit(EXIT_FAILURE);
}

switch ( fork() )
{
case -1:
perror("Failed to fork");
exit(EXIT_FAILURE);
break;

case 0:

if( dup2(fd[1],STDOUT_FILENO) ==-1 )
{
perror("Fail redirecting stdout");
exit(EXIT_FAILURE);
}
close(fd[0]);

if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1)
perror("Child unable to execute sixad");
exit(EXIT_FAILURE);
break;

default:
printf("parent\n");
close(fd[1]);
char buf[500];

while(1)
{
printf("while\n");
if ( read(fd[0], buf, sizeof(buf)) <= 0)
{
perror("Fail reading from pipe:\n ");
exit(EXIT_FAILURE);
}

printf("Read from pipe:\n %s",buf);
}
}


Output:


parent
while

(sixad source code: syslog(LOG_INFO, "Connected PLAYSTATION(R)3 Controller (%s)", bda); )

Output Continuation:


sixad[7953]: sixad started, press the PS button now
sixad[7969]: Connected PLAYSTATION(R)3 Controller (00:23:06:A4:E6:AA)

(I pressed ctrl+c in the console)

Output Continuation


^C
sixad[7953]: Exit
Read from pipe:
sixad settings:
Enable LEDs: 1
js# as LED #: 1
Start LED #: 1
LED # increase: 1
LED animation: 1
Buttons: 1
Sens. buttons: 1
Axis: 1
Accelerometers: 1
Acceleration: 0
Speed: 0
Position: 0
Rumble: 0
Debug: 0
while
Fail reading from pipe:
: Success

Note: sixad settings are printed with printf