how to run multiple processes from a single process?

M

mandydhaliwal

Hi all,

I am porting a win32 c++ program on Linux which first reads a list of
processes and their paths from a file.Then this program should launch
all of thesese processes.

I tried to achieve this using fork() and execv() API calls. but
execv() method call is synchronous
and does not return untill user closes the child application or a
launch program error occurs.

Is there any other API / alternate solution available in Linux C++?
Thanks in advance.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
Y

yttrx

In said:
Hi all,

I am porting a win32 c++ program on Linux which first reads a list of
processes and their paths from a file.Then this program should launch
all of thesese processes.

I tried to achieve this using fork() and execv() API calls. but
execv() method call is synchronous
and does not return untill user closes the child application or a
launch program error occurs.

Is there any other API / alternate solution available in Linux C++?
Thanks in advance.

There are quite a few that linux supports, but im not sure why
fork() isn't doing it? You may look at posix_spawn() or posix_spawnp(),
there's an offchance that you might find them useful.




-----yttrx


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Rex Ballard

Hi all,

I am porting a win32 c++ program on Linux which first reads a list of
processes and their paths from a file.Then this program should launch
all of thesese processes.

I tried to achieve this using fork() and execv() API calls. but
execv() method call is synchronous
and does not return untill user closes the child application or a
launch program error occurs.

Is there any other API / alternate solution available in Linux C++?
Thanks in advance.

You might consider just starting a shell command which can start the
processes in the background. You are also using the fork()/exec()
wrong.

It sounds, from you description, like you are trying to exec from the
parent process instead of the child process. Normally, you fork, test
the return value of fork(void).
If the pid is zero, it is the child process, and the child should run
the exec. If it is non-zero , you are the parent, process, and you can
save that process ID.

Normally, before you exit the parent, you should wait() for each of the
children, to make sure that they are all gone (otherwise you get
zombies, which can be annoying and consume memory).

In some cases, an application will "grandfather" the subordinate
processes. The parent process forks a child, which then forks
grandchildren, then waits for the grandchildren to die, then signals
the parent. Shell commands followed by the ampersand "&", do the
fork/exec properly and the shell does the proper wait. The advantage
of this approach is that the child of the grandfather can be very small
and simple, which means that if the grandfather is terminated
abnormally (kill -9), the child zombie will be very small and consume
much less memory.

Services are a special variation, which are started by the "root"
process or grandfathered by the root process, usually under the initd
command. When the initd command kills off all the children, the system
is about to be shut down. It can wait for the signals, and if one of
the children refuses to die, the kill -9 sent by the root shutdown
process will kill all children AND the initd daemon.

http://yolinux.com/TUTORIALS/ForkExecProcesses.html

hope that helps.
 
O

OK

You might consider just starting a shell command which can start the
processes in the background. You are also using the fork()/exec()
wrong.

It sounds, from you description, like you are trying to exec from the
parent process instead of the child process. Normally, you fork, test
the return value of fork(void).
If the pid is zero, it is the child process, and the child should run
the exec. If it is non-zero , you are the parent, process, and you can
save that process ID.

Normally, before you exit the parent, you should wait() for each of the
children, to make sure that they are all gone (otherwise you get
zombies, which can be annoying and consume memory).

In some cases, an application will "grandfather" the subordinate
processes. The parent process forks a child, which then forks
grandchildren, then waits for the grandchildren to die, then signals
the parent. Shell commands followed by the ampersand "&", do the
fork/exec properly and the shell does the proper wait. The advantage
of this approach is that the child of the grandfather can be very small
and simple, which means that if the grandfather is terminated
abnormally (kill -9), the child zombie will be very small and consume
much less memory.

Services are a special variation, which are started by the "root"
process or grandfathered by the root process, usually under the initd
command. When the initd command kills off all the children, the system
is about to be shut down. It can wait for the signals, and if one of
the children refuses to die, the kill -9 sent by the root shutdown
process will kill all children AND the initd daemon.

http://yolinux.com/TUTORIALS/ForkExecProcesses.html

hope that helps.

That's a lot of totally useless babbling.

The answer is

use spawn(), not exec().
 
T

The Ghost In The Machine

In comp.os.linux.advocacy, (e-mail address removed)
<[email protected]>
wrote
Hi all,

I am porting a win32 c++ program on Linux which first reads a list of
processes and their paths from a file.Then this program should launch
all of thesese processes.

I tried to achieve this using fork() and execv() API calls. but
execv() method call is synchronous
and does not return untill user closes the child application or a
launch program error occurs.

Is there any other API / alternate solution available in Linux C++?
Thanks in advance.

You appear slightly confused. The execl()/execv() is
indeed synchronous (in a way) but should be invoked *after*
the fork.

Herewith an example of more or less proper usage. This will
fork off NCHILDREN children and then wait for all of them.
This is not all that useful an example as written; the child
simply subinvokes a rather straightforward command line, but
modifications should be fairly obvious -- e.g., one could
take arguments from the argc/argv vector, or read them from a file
after some parsing.

This example should work in either C or C++, though with
C++ one might have to replace headers such as <stdio.h>
with <cstdio>. This example is intended for UNIX(tm),
Linux, and other Unix-like systems only.


---8< >8---
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>

/* How many kids do we want? */
#define NCHILDREN 5

int main(int argc, char **argv)
{
pid_t child[NCHILDREN];
int i;

for(i = 0; i < NCHILDREN; i++)
{

child = fork();

if(child == 0)
{
/* I'm the child. Play in the sandbox; in this
case, just subinvoke /bin/ls with some args. */

char * lsvector[] = {"ls", "-l", "/usr/X11R6/bin",
(char *) NULL};

execv("/bin/ls", lsvector);

perror("execv"); /* should never get here unless execv fails! */

exit(-1);
}
else if ((int) child < 0)
{
perror("fork"); /* something went wrong */
}
else
printf("Forked off child # %d with pid %d\n", i, child);
}

/* At this point, we're in the parent and all kids are now
doing what kids do -- which in our case isn't much. */

for(i = 0; i < NCHILDREN; i++)
{
int chstatus = 0;
pid_t res = wait(&chstatus);

printf("A child exited with status %d (0x%x)\n", chstatus, chstatus);
printf("wait returned %d" ,child, res);
}

return 0; /* end program */
}
---8< >8---

Depending on needs, one can use fork() or vfork()
and wait(), wait3(), or waitpid(); the differences are
described in the relevant manpages. One advantage to using
wait(): the first dead child will return; they needn't die
in the order of their creation. vfork() is a bit of an
anachronism nowadays, but it was controversial at the time.

There's a lot of other things the kids can do, such as
close() and dup(). pipe() should be invoked by the
*parent* (the child will get a copy of the parent's
local variables/pages). One thing the child cannot do is
modify the parent's variables/pages, without such things
as mmap().

If one actually runs this program, expect a lot of slightly
scrambled output, as the children are going to output
to standard output without any sort of synchronization.
Synchronizing this output is tricky, though the parent
could set up pipes and use select() or poll() if need be.

Since this isn't really C++-specific, followups reset to COLA.

--
#191, (e-mail address removed)
Windows Vista. Because it's time to refresh your hardware. Trust us.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Robert Newson

Rex Ballard wrote:

....
Normally, before you exit the parent, you should wait() for each of the
children, to make sure that they are all gone (otherwise you get
zombies, which can be annoying and consume memory).

6.1 PROCESS STATES AND TRANSITIONS
....
9. The process executed the /exit/ system call and is in the /zombie/ state.
The process no longer exists, but leaves a record containing an exit code
and some timing statistics for its parent process to collect. The zombie
state is the final state of a process.
In some cases, an application will "grandfather" the subordinate
processes. The parent process forks a child, which then forks
grandchildren, then waits for the grandchildren to die, then signals
the parent. Shell commands followed by the ampersand "&", do the
fork/exec properly and the shell does the proper wait. The advantage
of this approach is that the child of the grandfather can be very small
and simple, which means that if the grandfather is terminated
abnormally (kill -9), the child zombie will be very small and consume
much less memory.

From what I can see[1], the only memory used by a zombie process is the
memory needed to hold the exit code and timing stats - a very small amount;
plus it takes up a process table slot. The [main] memory it was using is
released back.

[1] from my *nix books, plus a test program.
 
K

kanze

I am porting a win32 c++ program on Linux which first reads
a list of processes and their paths from a file.Then this
program should launch all of thesese processes.

I'm not sure what this has to do with C++. Unless...
I tried to achieve this using fork() and execv() API calls.
but execv() method call is synchronous and does not return
untill user closes the child application or a launch program
error occurs.

Purely Unix, and best handled in a Unix forum. But execv()
doesn't return, period. (Unless there is an error.) It
replaces the current process image with a new one, so there is
no place to return to.

The Unix process model is a bit wierd. The best (i.e. most
understandable) documentation I've read is in "Programming in a
Unix Environment", by Kernighan and Pike. It is very, very
dated, but the use of fork and exec are well explained. (Signal
handling has changed radically since it was written, however, so
once you understand the principles, you'll still want to get the
Stevens---"Advanced Unix Programming", or something like that.)

On the other hand, I wonder if a "portable" solution based on
system() wouldn't work. Append a & after the command, and it
will run asynchronously.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Rex Ballard

OK said:
That's a lot of totally useless babbling.

The answer is

use spawn(), not exec().

I believe spawn() is only on Windows, not Linux/Unix.

I could be wrong. I did try to look it up.
Let me know if you find anything other than the postfix spawn man page.
By the way, postfix is a mail deamon similar to sendmail created by
IBM.
 
T

The Ghost In The Machine

In comp.os.linux.advocacy, Rex Ballard
<[email protected]>
wrote
I believe spawn() is only on Windows, not Linux/Unix.

There is a posix_spawn() in /usr/include/spawn.h on my box.
One can also 'man posix_spawn'. It takes 6 arguments,
all pointers (3 strings, 2 structures, 1 to a pid_t).

Not horribly pretty, though NT's CreateProcess() is worse.
It's part of glibc so everyone should have it, though good
luck finding it (I used grep on the include files).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top