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;
}
Related
My program has to create multiple children, i take the number of children from terminal. Then, I need to group them and every group has different tasks.
I created the children but the problem is that I can't give them separated tasks, I can't distinguish children. Only thing I can do is, every children works on the same part(like printing pids).
How can I separate them and give them specific tasks?
For example, first 4 children should call a function, other 3 should print something and other 3 should write to a file etc.
pid_t pid[10];
pid[0] = fork();
if(pid[0] > 0)
{
for(int i = 0; i < 9; i++)
{
if(pid[i] > 0)
{
pid[i + 1] = fork();
}
}
}
for(int i = 0; i < 10; i++)
{
if(pid[i] == 0)
{
printf("child %d, parent %d\n", getpid(), getppid());
exit(1);
}
}
I think you should take a look at how the fork() function works. Here is the man page, here a useful answer and here a useful tutorial.
When you use fork() in your code, know that the child process continue from where the parent was. So when you call fork() in the first for loop, all the child processes continue the loop that the parent has begun. I don't think this is the behavior you expect.
Anyway, here's a possible solution for your problem. In this way your processes do some stuff divided in small groups. Note the exit(0) function at the end of the work. It is important to be sure that every process does only its work and not also its parent's work:
pid_t pid[10];
for (int i = 0; i < 9; i++)
{
pid[i] = fork();
//First group
if (pid[i] == 0 && i < 4){
//Insert here the code for the first group or call a fuction
exit(0);
}
//Second group
if (pid[i] == 0 && i >=4 && i < 8){
//Insert here the code for the second group or call a fuction
exit(0);
}
//Third group
if (pid[i] == 0 && i >=8){
//Insert here the code for the third group or call a fuction
exit(0);
}
if (pid[i] < 0){
perror("Something wrong with the fork");
exit(1);
}
}
int flag = 0;
flag |= (fork() == 0) << 0;
flag |= (fork() == 0) << 1;
flag |= (fork() == 0) << 2;
printf("this process works on problem %d\n", flag);
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
}
}
I'm trying to write a small program that forks processes from a single parent. Currently my code does this a few times but then the children create more child processes, which I want to eliminate.
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c > 0 ) {
printf("parentID = %d, childID = %d\n", getppid(i), getpid(i));
}
}
}
I'm not sure how to modify it so that fork is only forking from the parent though.
EDIT: thanks for the help, got the solution:
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c > 0 ) {
printf("parentID = %d, childID = %d\n", getppid(i), getpid(i));
}
else {
exit(0);
}
}
}
nothing in the posted code is recognizing the child (0 == pid)
so a child hits (and skips) the two 'if' statements.
hits the end of the loop,
branches back to the top of the loop, calls fork()....etc.
Suggest: adding
elseif( 0 == pid )
{ // then child ...
exit( EXIT_SUCCESS );
}
The child process does not enter any part of the if block, and just loops back to the top of the for loop creating more children. Also, the if (n > 0) block gets run for the parent, not the child, since fork returns 0 to the parent and the child's pid to the parent.
Change if (n > 0) to if (n == 0), and call exit() at the bottom of the block to prevent the child from continuing. Also, getpid() and getppid() don't take any arguments.
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c == 0 ) {
printf("parentID = %d, childID = %d\n", getppid(), getpid());
exit(0); // <-- here
}
}
}
I'm trying to use the multiple fork() calls to create several children with different task
I found a code on
Multiple child process
Which is really close for what I want , yet I couldn't fully understand it
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild != 0)
{
// In parent
secondChild = fork();
if(secondChild != 0)
{
// In parent
}
else
{
// In secondChild
}
}
else
{
// In firstChild
}
My questions are:
How many process have been created (I assume that we have 4 since it's 2 forks!)?
In this part of the code
firstChild = fork();
if(firstChild != 0)
{
// In parent
secondChild = fork();
if(secondChild != 0)
{
// In parent
}
Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).
How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent)
Thank you (please feel free to tell me if I'm not totally getting the Fork concept)
How many process have been created (I assume that we have 4 since it's 2 forks!)?
Depending on the result of your forks it should be 0 to 2. Probably 2 if nothing goes wrong. There's a parent process that forks 2 children processes.
Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).
Yes. In your case the code is checking for a return value of fork being non zero. That's not a very good idea since it covers 2 distinct cases:
It could be less than zero indicating an error, or ...
It could be greater than zero indicating to the parent the pid of the newly spawned process
Anyway ... considering all goes well and both the forks succeed, you will end up with a parent process having 2 different children.
How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent
Something like this should do the trick:
firstChild = fork();
if (firstChild < 0) {
exit(EXIT_FAILURE);
perror("fork");
}
secondChild = fork();
Notice that by not checking the return value of fork() any more I'm getting a child process continuing execution at the same place as the parent. So the next fork will actually be executed by both the parent and the children each spawning a new process. So I'll get something like this ...
parent─┬─child1───(child1's child)
└─child2
I can't think of any way you can get this with only 2 forks though:
parent─┬─child1
├─child3
└─child2
Note: It's customary on stackoverflow to only limit yourself to one question per topic.
The following code shows how to create 4 process (1 parent 3 children) with only 2 forks
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int *list;
void calculate_average(int );
void calculate_maximum(int);
void calculate_minimum(int);
void calculate_average(int count)
{
int i, total = 0;
for (i = 0; i < count; i++)
total += list[i];
double average = total / count;
printf("average is %f\n",average);
}
void calculate_maximum(int count)
{
int i;
int maximum = list[0];
for (i = 1; i < count; i++)
if (list[i] > maximum)
maximum = list[i];
printf("maximum is %d\n",maximum);
}
void calculate_minimum(int count)
{
int i;
int minimum = list[0];
for (i = 1; i < count; i++)
if (list[i] < minimum)
minimum = list[i];
printf("minimum is %d\n",minimum);
}
int main(int argc, char *argv[])
{
pid_t pid, pid1;
int num_of_args = argc-1;
int i;
/* allocate memory to hold array of integers */
list = malloc(sizeof(int)*num_of_args);
for (i = 0; i < num_of_args; i++)
list[i] = atoi(argv[i+1]);
printf("The %d number of input ingeters are\n",num_of_args);
for (i = 0; i < num_of_args; i++)
printf("%d\n",list[i]);
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
return 1;
}
else if (pid == 0) { /* P2 */
pid1=getppid();
calculate_average(num_of_args);
}
else { /* P1 */
pid1=getpid();
wait(NULL);
}
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
return 1;
}
else if (pid == 0) { /* could be either P3 or P4 */
if (getppid() == pid1) { /* P3 */
calculate_minimum(num_of_args);
}
else { /* P4 */
calculate_maximum(num_of_args);
}
}
else {
wait(NULL);
}
return 0;
}
Note that one of the children will be a parent for a grandchild
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++;
}
}
}