I have this array of number that tells how many children processes each parent has to make or rather what is the structure of a tree.
For example, if array contains 1 4 0 0 3, then the proc tree looks like this
http://shrani.si/f/S/IW/8HrGEVJ/proctree.jpg
I think it might be solvable with a recursion, but I don't know how to read an array and determine where and how many children procs should I fork. Also, how do you create more children from a one parent if your code template is like this:
void recTreeProc(){
/* create process */
pid_t pid;
pid = fork();
if (pid == -1) {
/* error */
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
/* child process */
//call recursion?
}
else {
/* parent process */
//wait for all the children to execute
int status;
(void)waitpid(pid, &status, 0);
}
}
I can't help you with the code for the implementation of the tree and the array because i didn't get what the values means but for multiple childs you can try that :
void recTreeProc() {
/* create process */
pid_t pid;
int n = 0;
int cpid[CHILD_NB];
do {
pid = fork();
if (pid == -1) {
perror("fork failed");
exit(EXIT_FAILURE);
}
else if (pid) {
cpid[n];
}
n++;
} while(n < CHILD_NB && pid); // I want CHILD_NB childs
if (!pid) {
/* childs */
}
else {
/* parent process */
//wait for all the children to execute
int status[CHILD_NB];
n = 0;
while (n < CHILD_NB) {
(void)waitpid(cpid[n], &status[n], 0);
n++;
}
}
}
Related
can someone help me about how to create multiple child processes which have the same parent in order to do "some" part of particular job?
for example, an external sorting algorithm which is applied with child processes; each child process sorts a part of data and finally the parent merges them..
EDIT: Maybe I should mention the forking multiple child processes with loop..
Here is how to fork 10 children and wait for them to finish:
pid_t pids[10];
int i;
int n = 10;
/* Start children. */
for (i = 0; i < n; ++i) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
} else if (pids[i] == 0) {
DoWorkInChild();
exit(0);
}
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0) {
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n; // TODO(pts): Remove pid from the pids array.
}
If you want to launch several forks, you should do it recursively. This is because you must call fork from the parent process. Otherwise, if you launch a second fork, you will duplicate both parent and first child process. Here's an example:
void forker(int nprocesses)
{
pid_t pid;
if(nprocesses > 0)
{
if ((pid = fork()) < 0)
{
perror("fork");
}
else if (pid == 0)
{
//Child stuff here
printf("Child %d end\n", nprocesses);
}
else if(pid > 0)
{
//parent
forker(nprocesses - 1);
}
}
}
I think it would be worth pointing out why threads are more appropriate here:
As you are trying to do a "part" of the job in parallel i assume that your program needs to know about the result of the computation. fork()s of a process don't share more then the initial information after fork(). Every change in one process is unknow to the other and you would need to pass the information as a message (e.g. through a pipe, see "man pipe").
Threads in a process share the same adress space and therefor are able to manipulate data and have them visible toeach other "immediatly". Also adding the benefits of being more lightweight, I'd go with pthreads().
After all: You will learn all you need to know about fork() if you use pthreads anyway.
You can do this with fork. A given parent can fork as may times as it wants. However, I agree with AviD pthreads may be more appropriate.
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild > 0)
{
// In parent
secondChild = fork();
if(secondChild > 0)
{
// In parent
}
else if(secondChild < 0)
{
// Error
}
else
{
// In secondChild
}
}
else if(firstChild < 0 )
{
// Error
}
else
{
// In firstChild
}
I have a function in C which creates a child process and makes it run execvp.
int Execute(char **arg)
{
pid_t pid;
int status;
if ((pid=fork()) == 0)
{
execvp(arg[0],arg);
perror("Execvp error");
exit(1);
}
else if (pid > 0)
{
waitpid(pid, &status, 0);
}
else
{
perror("Fork error");
exit(2);
}
}
Now I want to alter the function to actually run execvp several times (for example 5), and make the parent process wait for all the children to finish. Tried wrapping it all in for loop, but execvp gets executed just once. I know that basically execvp 'replaces' the current program code, but have no idea whether the iteration does not go on.
Thank you for your help!
First, loop around the process creation collecting the child PIDs
pid_t pid[5];
int i;
for (i = 0; i < 5; i++) {
if ((pid[i]=fork()) == 0) {
execvp(arg[0],arg);
perror("Execvp error");
_exit(1);
}
if (pid[i] < 0) {
perror("Fork error");
}
}
Second, loop around the waitpid call for every valid PID.
for (i = 0; i < 5; i++) {
if (pid[i] > 0) {
int status;
waitpid(pid[i], &status, 0);
if (status > 0) {
// handle a process sent exit status error
}
} else {
// handle a proccess was not started
}
}
So I have this program where the initial process sends numbers to the child, then the child performs certain operations with numbers and sends them to the next child...
My problem is that where the program has to send the numbers starting from two (2), the first number the child gets is 3. What could the problem be?
Here is my code:
void start(int num_of_nums){
if (num_of_nums <= 0) return;
int pipefd[2];
pid_t cpid;
int pipe_res = pipe(pipefd);
if (pipe_res == -1) {
printf("pipe error in start\n");
perror("pipe error");
exit(EXIT_FAILURE);
}
//create a new process
cpid = fork();
if (cpid == -1) {
printf("fork error in start\n");
perror("fork error");
exit(EXIT_FAILURE);
}
if (cpid == 0) { // child
printf("child in start\n");
close(pipefd[1]); // close write end
int num_from_parent = pipefd[0]; //where the number is read
printf("num from parent is %d\n", num_from_parent); //prints out 3...
filter(num_from_parent);
} else { // parent
printf("parent in start\n");
close(pipefd[0]); // close read end
for (int i = 2; i <= num_of_nums + 1; i++){
write(pipefd[1], &i, sizeof(int)); //WHERE THE NUMBERS ARE SENT
}
close(pipefd[1]);
}
}
Help would be much appreciated...
I have found examples of how to fork multiple children by having something like this:
if ( fork() = 0 ) {
//In child
} else {
if ( fork() = 0 ) {
//in second child
But if I don't know how many children I am going to need, how might I do this?
For instance, if I have a linked list of commands, and I want to fork and exec for each of them... So I guess I need to know which child it is as well...
Taking you at your word that you need to do this for a linked list:
linked_list_of_commands_t *node = root;
while (node != NULL) {
int pid = fork();
if (pid == -1) {
break; // handle error
} else if (pid == 0) {
// child
execv(node->command, node->argv);
exit(1); // execv should not return, but just in case the execv call fails
} else {
node = node->next;
}
}
This will launch a separate process for every item in the list.
But the number of routines would have to be fixed, even if the execution over those branches is unbounded. So what about a while loop with some sort of switch statement logic to each routine?
How about
for (i=0; i< 1000; i++) {
pid = fork();
if (pid) {
// Error handling for pid==-1
break;
}
// Some logic dependent on value of 'i'
}
for(i = 0; i < num_children_to_spawn(); ++i) {
pid_t pid = fork();
if (pid == -1) {
exit(-1); /* error */
} else if (pid == 0) {
/* child */
do_child_things();
break;
} else {
/* parent */
}
}
Note that I didn't use a switch() because it would make it more cumbersome to break out of the loop.
pid_t children_pids[MAX_CHILDREN];
int last_child_index = 0;
for (int i=0; i < num_wanted_children; i++) {
pid_t pid = fork();
if (pid == 0)
// in child
else
children_pids[last_child_index++] = pid;
}
can someone help me about how to create multiple child processes which have the same parent in order to do "some" part of particular job?
for example, an external sorting algorithm which is applied with child processes; each child process sorts a part of data and finally the parent merges them..
EDIT: Maybe I should mention the forking multiple child processes with loop..
Here is how to fork 10 children and wait for them to finish:
pid_t pids[10];
int i;
int n = 10;
/* Start children. */
for (i = 0; i < n; ++i) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
} else if (pids[i] == 0) {
DoWorkInChild();
exit(0);
}
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0) {
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n; // TODO(pts): Remove pid from the pids array.
}
If you want to launch several forks, you should do it recursively. This is because you must call fork from the parent process. Otherwise, if you launch a second fork, you will duplicate both parent and first child process. Here's an example:
void forker(int nprocesses)
{
pid_t pid;
if(nprocesses > 0)
{
if ((pid = fork()) < 0)
{
perror("fork");
}
else if (pid == 0)
{
//Child stuff here
printf("Child %d end\n", nprocesses);
}
else if(pid > 0)
{
//parent
forker(nprocesses - 1);
}
}
}
I think it would be worth pointing out why threads are more appropriate here:
As you are trying to do a "part" of the job in parallel i assume that your program needs to know about the result of the computation. fork()s of a process don't share more then the initial information after fork(). Every change in one process is unknow to the other and you would need to pass the information as a message (e.g. through a pipe, see "man pipe").
Threads in a process share the same adress space and therefor are able to manipulate data and have them visible toeach other "immediatly". Also adding the benefits of being more lightweight, I'd go with pthreads().
After all: You will learn all you need to know about fork() if you use pthreads anyway.
You can do this with fork. A given parent can fork as may times as it wants. However, I agree with AviD pthreads may be more appropriate.
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild > 0)
{
// In parent
secondChild = fork();
if(secondChild > 0)
{
// In parent
}
else if(secondChild < 0)
{
// Error
}
else
{
// In secondChild
}
}
else if(firstChild < 0 )
{
// Error
}
else
{
// In firstChild
}