A some point in my program, it is necessary for me to start a child process (Im on linux, btw, ubuntu gutsy). The process streams DV to stdout, but can be controlled in an "interactive mode" through commands to stdin.

How does one establish streams going both ways? If you use the good ol C libs, you can use popen (but that is only one way commication) or you can use pipe(). My understanding is that when you call exec(), all existing streams are closed, and all of your local variables destroyed. And Im pretty sure (please correct if wrong) that even though a file descriptor is represented as an interger, passing that integer to the child process would be worthless.

How do I create two way communication with a newly fork'd and exec'd process that ties back to the parent? (I would much rather have a c++ solution, but a C solution would work just as well)

Thanks

Recommended Answers

All 7 Replies

Link.

Enjoy!

The example was great. Now I have to ask, how can I use this in c++?
C++ (interfaces) do not directly deal with file descriptors as far as I can tell.

If I use your example to open up 4 file descriptors, dup2 them to the appropriate stdin/stdout, can I then use plain C++ <iostream> classes to interface with cin/cout?

Does using "unistd.h" and <iostream> cause any conflicts (such as <iostream> redefining cin and cout after I have already configured them the way I want using unistd.h.

Thanks for the help.

Accidentally posted twice, sorry

The example was great. Now I have to ask, how can I use this in c++?
C++ (interfaces) do not directly deal with file descriptors as far as I can tell.

If I use your example to open up 4 file descriptors, dup2 them to the appropriate stdin/stdout, can I then use plain C++ <iostream> classes to interface with cin/cout?

Does using "unistd.h" and <iostream> cause any conflicts (such as <iostream> redefining cin and cout after I have already configured them the way I want using unistd.h.

Thanks for the help.

Unfortunately the standard decided that such lowly things as file descriptors are too device-dependent, so there is no standard way to do that.

That said, many compiler systems provide a way to create an iostream connected to a file descriptor. Check your compiler documentation.

If you are up to it, a better solution would be to derive an iostream class that does it. Since this is a common problem, solutions by other people exist.
http://www.josuttis.com/cppcode/fdstream.hpp.html (very compact and simple)
http://www.boost.org/doc/libs/1_35_0/libs/iostreams/doc/index.html (very powerful)

Hope this helps.

Those libraries were extremely helpful. I really had no idea what I was trying to get myself into.

So, with the example you gave me earlier, I create my four file descriptors. In the parent, I use the fdstream header you linked to to create streams using the parent side file descriptors. Now the child...

(right after the fork statement)

if ( childpid == 0 )   /* in the child */
{
    close(PARENT_WRITE);
    close(PARENT_READ);

    dup2(CHILD_READ,  0);  close(CHILD_READ);
    dup2(CHILD_WRITE, 1);  close(CHILD_WRITE);

Correct me if I am wrong. At this point, I can now call exec(), and the file descriptors from my pipes will still be in place for std in/out on the CHILD PROCESS.

If not, how do I make sure the pipe still exists after I make the exec() call?

Thanks

You are correct. The process file table and the current working directory are not modified by exec(), so the new executable inherits it all.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.