I am trying to make a processor farm in C. I start with opening message queues, and afterwards try to make worker processes: (note that NROF_WORKERS is 5)
static void
makechildren (void) {
// Only the parent should fork. Any children created will become workers.
pid_t processID;
pid_t farmerPID = getpid(); // To identify who the farmer is
// Loop creating processes, indexed by NROF_WORKERS
int i = 0;
while (i < NROF_WORKERS){
if (getpid() == farmerPID){
i++;
printf ("Parent is creating a child!%d\n", getpid());
processID = fork();
}
}
if (processID < 0){
perror("fork() failed");
exit(1);
}
else {
// If parent, start farming
if (processID == farmerPID) {
printf("Parent reporting in!%d\n");
}
// If child, become a worker
if (processID == 0) {
printf("Child reporting in!%d\n", getpid());
join();
}
}
}
As you can see, I want the parent to report any time a child is created, and afterwards I want the parent and all children to report. However, this is all I get:
Parent is creating a child!11909
Parent is creating a child!11909
Parent is creating a child!11909
Parent is creating a child!11909
Parent is creating a child!11909
Child reporting in!11914
Now, I do notice the difference in 11909 and 11914 is 5. So my question: are the other processes created? If so, how come they don't report? And if not, what am I doing wrong? Also, the parent is not reporting at all, how is this caused?
All of the children are created, but will loop forever in the while loop, as i is incremented only for the parent:
int i = 0;
while (i < NROF_WORKERS){
if (getpid() == farmerPID){
i++; // <---- This is happening for the parent process only.
printf ("Parent is creating a child!%d\n", getpid());
processID = fork();
}
}
The only child to terminate is the last one, for which the i is equal to NROF_WORKERS.
Also parent is "not reporting" since the processID you are checking to be equal to the parent PID is never equal to it, as it is equal to the latest fork result, i.e. the latest created child PID:
.........
processID = fork();
.........
.........
if (processID == farmerPID) {
printf("Parent reporting in!%d\n");
}
You always print the farmerPid! But as the message is printed 5 times, you effectively created 5 processes:
while (i < NROF_WORKERS){
if (getpid() == farmerPID){
i++;
printf ("Parent is creating a child!%d\n", getpid());
processID = fork();
}
}
If you want to print the children pids then your code must makes a difference in between parent and child, as in:
while (i < NROF_WORKERS){
if (getpid() == farmerPID){
i++;
printf ("Parent is creating a child!\n");
processID = fork();
if (processID==0) { // child
printf("I am the child %d\n",getpid());
} else { // parent
printf("Parent just created child %d\n",processID);
}
}
}
Related
I have the following code in my main function
pid_t pid;
pid = fork(); //Two processes are made
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
{
printf("Exitstatus [");
for (int i = 0; i < noOfTokens; i++)
{
printf("%s ", commands[i]);
}
printf("\b] = %d\n", WEXITSTATUS(status));
}
}
else if (pid == 0) //Child process. Executes commands and prints error if something unexpected happened
{
if (runBGflag==1) insertElement(getpid(),ptr);
execvp(commands[0], commands);
printf ("exec: %s\n", strerror(errno));
exit(1);
}
In a nutshell, a child process is made and if the runBackGround flag is set, the parent process will not wait for the child process to exit, but rather continue running. If a background process is made, the PID of the background process is stored in a list. At a later point, this function is called
void delete_zombies(void)
{
pid_t kidpid;
int status;
char buffer[1337];
while ((kidpid = waitpid(-1, &status, WNOHANG)) > 0)
{
removeElement(kidpid,buffer,1337);
printf("Child %ld terminated\n", kidpid);
printf("its command was %s\n",buffer);
}
}
This function simply checks if any child processes have died and in that case deletes them. It will then search for the childs PID in the list, remove it and print it out.
The problem is, the delete_zombies function will find that a child has died and will then try to remove it from the list, but it only finds an empty list, as if the child process never inserted its PID into the list.
This is really strange, because delete_zombies only finds a dead child process, when there was one created with the background flag set, so we know insertElement must have been called, but strangely when the parent checks in the list nothing is there
Is the cause for that, that child process and parent process have seperate lists, or is the PID maybe wrong?
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 the following code in which I'm trying to create sub processes by forking. I want that exactly 3 sub processes are made. However, when I run the code I seem to be getting more, probably because of the children processes forking grandchildren. What am I missing here, how can I prevent this.
Code:
for(j = 0; j < 3 ; j++){
if((pid = fork()) == 0){ // child process
dosomething();
exit(0); // terminate child process
}
else if((pid = fork()) > 0){
printf("I'm in parent of the client spawn loop\n");
// exit(0);
}
}
Output:
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
I'm in parent of the client spawn loop
Don't do the second fork call as it will create a new child. The first is enough:
for (j = 0; j < 3; ++j)
{
pid_t pid = fork();
if (pid == 0)
{
printf("In child (j = %d)\n", j);
exit(0);
}
else if (pid > 0)
{
printf("In parent (j = %d)\n", j);
}
}
Will print "In child" three times, with j equal to 0, 1 and 2. The same for the parent printing.
In your real code you should check for errors though.
Don't call fork() more than once in the loop.
The parent shouldn't call fork() again, that will create yet another child and introduce another child-parent split point.
You should have, in the loop:
const int pid = fork();
if(pid == 0)
{
doSomething();
exit();
}
I'm starting to learn some C and while studying the fork, wait functions I got to a unexpected output. At least for me.
Is there any way to create only 2 child processes from the parent?
Here my code:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main ()
{
/* Create the pipe */
int fd [2];
pipe(fd);
pid_t pid;
pid_t pidb;
pid = fork ();
pidb = fork ();
if (pid < 0)
{
printf ("Fork Failed\n");
return -1;
}
else if (pid == 0)
{
//printf("I'm the child\n");
}
else
{
//printf("I'm the parent\n");
}
printf("I'm pid %d\n",getpid());
return 0;
}
And Here is my output:
I'm pid 6763
I'm pid 6765
I'm pid 6764
I'm pid 6766
Please, ignore the pipe part, I haven't gotten that far yet. I'm just trying to create only 2 child processes so I expect 3 "I'm pid ..." outputs only 1 for the parent which I will make wait and 2 child processes that will communicate through a pipe.
Let me know if you see where my error is.
pid = fork (); #1
pidb = fork (); #2
Let us assume the parent process id is 100, the first fork creates another process 101. Now both 100 & 101 continue execution after #1, so they execute second fork. pid 100 reaches #2 creating another process 102. pid 101 reaches #2 creating another process 103. So we end up with 4 processes.
What you should do is something like this.
if(fork()) # parent
if(fork()) #parent
else # child2
else #child1
After you create process , you should check the return value. if you don't , the seconde fork() will be executed by both the parent process and the child process, so you have four processes.
if you want to create 2 child processes , just :
if (pid = fork()) {
if (pid = fork()) {
;
}
}
You can create n child processes like this:
for (i = 0; i < n; ++i) {
pid = fork();
if (pid > 0) { /* I am the parent, create more children */
continue;
} else if (pid == 0) { /* I am a child, get to work */
break;
} else {
printf("fork error\n");
exit(1);
}
}
When a fork statement is executed by the parent, a child process is created as you'd expect. You could say that the child process also executes the fork statement but returns a 0, the parent, however, returns the pid.
All code after the fork statement is executed by both, the parent and the child.
In your case what was happening was that the first fork statement created a child process. So presently there's one parent, P1, and one child, C1.
Now both P1 and C1 encounter the second fork statement. The parent creates another child (c2) as you'd expect, but even the child, c1 creates a child process (c3). So in effect you have P1, C1, C2 and C3, which is why you got 4 print statement outputs.
A good way to think about this is using trees, with each node representing a process, and the root node is the topmost parent.
you can check the value as
if ( pid < 0 )
process creation unsuccessful
this tells if the child process creation was unsuccessful..
fork returns the process id of the child process if getpid() is used from parent process..
You can create a child process within a child process. This way you can have 2 copies of the original parent process.
int main (void) {
pid_t pid, pid2;
int status;
pid = fork();
if (pid == 0) { //child process
pid2 = fork();
int status2;
if (pid2 == 0) { //child of child process
printf("friends!\n");
}
else {
printf("my ");
fflush(stdout);
wait(&status2);
}
}
else { //parent process
printf("Hello ");
fflush(stdout);
wait(&status);
}
return 0;
}
This prints the following:
Hello my friends!
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
}