Fork() function in C - c

Below is an example of the Fork function in action. Below is also the output. My main question has to to do with the a fork is called how values are changed. So pid1,2 and 3 start off at 0 and get changed as the forks happen. Is this because each time a fork happens the values are copied to the child and the specific value gets changed in the parent? Basically how do values change with fork functions?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid1, pid2, pid3;
pid1=0, pid2=0, pid3=0;
pid1= fork(); /* A */
if(pid1==0){
pid2=fork(); /* B */
pid3=fork(); /* C */
} else {
pid3=fork(); /* D */
if(pid3==0) {
pid2=fork(); /* E */
}
if((pid1 == 0)&&(pid2 == 0))
printf("Level 1\n");
if(pid1 !=0)
printf("Level 2\n");
if(pid2 !=0)
printf("Level 3\n");
if(pid3 !=0)
printf("Level 4\n");
return 0;
}
}
Then this is the execution.
----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4")
| |
| +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3")
| |
| +---- (pid1!=0, pid2==0, pid3==0, print "Level 2")
|
+----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing)
| |
| +---- (pid1==0, pid2==0, pid3==0, print nothing)
|
+----C---- (pid1==0, pid2==0, pid3!=0, print nothing)
|
+---- (pid1==0, pid2==0, pid3==0, print nothing)
Ideally below is how I would like to see it explained as this way makes sense to me. The * are where my main confusion lies. When the child forks for example pid1 = fork(); that creates a process with all the values of the parent, but does it then pass up a value like lets say 1 to the parents pid1? Meaning the child would have pid 1=0, pid2=0 and pid3=0 and the parent then as pid1=2 and pid2 and 3 equal to 0?

System call fork() is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Therefore, we have to distinguish the parent from the child. This can be done by testing the returned value of fork()
Fork is a system call and you shouldnt think of it as a normal C function. When a fork() occurs you effectively create two new processes with their own address space.Variable that are initialized before the fork() call store the same values in both the address space. However values modified within the address space of either of the process remain unaffected in other process one of which is parent and the other is child.
So if,
pid=fork();
If in the subsequent blocks of code you check the value of pid.Both processes run for the entire length of your code. So how do we distinguish them.
Again Fork is a system call and here is difference.Inside the newly created child process pid will store 0 while in the parent process it would store a positive value.A negative value inside pid indicates a fork error.
When we test the value of pid
to find whether it is equal to zero or greater than it we are effectively finding out whether we are in the child process or the parent process.
Read more about Fork

int a = fork();
Creates a duplicate process "clone?", which shares the execution stack. The difference between the parent and the child is the return value of the function.
The child getting 0 returned, and the parent getting the new pid.
Each time the addresses and the values of the stack variables are copied. The execution continues at the point it already got to in the code.
At each fork, only one value is modified - the return value from fork.

First a link to some documentation of fork()
http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html
The pid is provided by the kernel. Every time the kernel create a new process it will increase the internal pid counter and assign the new process this new unique pid and also make sure there are no duplicates. Once the pid reaches some high number it will wrap and start over again.
So you never know what pid you will get from fork(), only that the parent will keep it's unique pid and that fork will make sure that the child process will have a new unique pid. This is stated in the documentation provided above.
If you continue reading the documentation you will see that fork() return 0 for the child process and the new unique pid of the child will be returned to the parent. If the child want to know it's own new pid you will have to query for it using getpid().
pid_t pid = fork()
if(pid == 0) {
printf("this is a child: my new unique pid is %d\n", getpid());
} else {
printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid);
}
and below is some inline comments on your code
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid1, pid2, pid3;
pid1=0, pid2=0, pid3=0;
pid1= fork(); /* A */
if(pid1 == 0){
/* This is child A */
pid2=fork(); /* B */
pid3=fork(); /* C */
} else {
/* This is parent A */
/* Child B and C will never reach this code */
pid3=fork(); /* D */
if(pid3==0) {
/* This is child D fork'ed from parent A */
pid2=fork(); /* E */
}
if((pid1 == 0)&&(pid2 == 0)) {
/* pid1 will never be 0 here so this is dead code */
printf("Level 1\n");
}
if(pid1 !=0) {
/* This is always true for both parent and child E */
printf("Level 2\n");
}
if(pid2 !=0) {
/* This is parent E (same as parent A) */
printf("Level 3\n");
}
if(pid3 !=0) {
/* This is parent D (same as parent A) */
printf("Level 4\n");
}
}
return 0;
}

I think every process you make start executing the line you create so something like this...
pid=fork() at line 6. fork function returns 2 values
you have 2 pids, first pid=0 for child and pid>0 for parent
so you can use if to separate
.
/*
sleep(int time) to see clearly
<0 fail
=0 child
>0 parent
*/
int main(int argc, char** argv) {
pid_t childpid1, childpid2;
printf("pid = process identification\n");
printf("ppid = parent process identification\n");
childpid1 = fork();
if (childpid1 == -1) {
printf("Fork error !\n");
}
if (childpid1 == 0) {
sleep(1);
printf("child[1] --> pid = %d and ppid = %d\n",
getpid(), getppid());
} else {
childpid2 = fork();
if (childpid2 == 0) {
sleep(2);
printf("child[2] --> pid = %d and ppid = %d\n",
getpid(), getppid());
} else {
sleep(3);
printf("parent --> pid = %d\n", getpid());
}
}
return 0;
}
//pid = process identification
//ppid = parent process identification
//child[1] --> pid = 2399 and ppid = 2398
//child[2] --> pid = 2400 and ppid = 2398
//parent --> pid = 2398
linux.die.net
some uni stuff

Related

Creation of process with fork

I'm trying to understand how to create fork trees,is there any simple way to understand that?
Exemple:
include<stdio.h>
include<unistd.h>
void main(){
fork();
if fork();
if fork();
fork();
sleep(10);
}
Every time you are calling fork() you are creating a Child that has the exact code the father has until this moment, but its own memory map.
Then you have to 2 processes with the same code. If you want to make them do something different you have to use fork()'s return. Fork returns the pid of the child and ''assigns'' it at Father's memory. Through that mechanism Father can refer to the child using its pid (process ID) which is only known to him. If child tries to see the exact pid created for it through fork(), it simply can't and would be zero (because fork return PID to a process for other child processes).
Example code of the above is the bellow:
void main(void)
{
char sth[20]="something";
pid_t pid;
pid = fork(); // Create a child
// At this line (so this specific comment if you may like) has 2 processes with the above code
printf("I am process with ID<%ld> and i will print sth var <%s>", getpid(),sth);
// The above printf would be printed by both processes because you haven't issued yet a way to make each process run a different code.
// To do that you have to create the following if statement and check PID according to what said above.
if (pid == 0) // If PID == 0, child will run the code
printf("Hello from child process with pid <%ld>",getpid());
printf(", created by process with id <%ld>\n",getppid());
else // Else the father would run the code
printf("Hello from father process with pid <%ld>",getpid());
}
I tried to be as naive as i could. Hope it helps somehow.
From linux manual:
fork() creates a new process by duplicating the calling process.
Basically it creates a new process, referred to as the child, which is an exact duplicate, with same code, of the calling process, referred to as the parent, except for few things (take a look at man fork). It returns the child process ID if you're the parent, 0 if you're the child or -1 (and sets errno) to the parent on failure. Here's a code example of a fork tree:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
/*
* I'm going to create a fork tree
*
*/
int main(){
pid_t pid; /*Use it for fork() calls*/
pid = fork(); /*Generating the first child*/
if(pid == 0){ /*I'm the child*/
pid_t pid_child = fork();
if(pid_child == 0){ /*I'm the grandchild*/
printf("I'M THE GRANDCHILD\n");
return 0; /*Terminates the new process*/
}else if(pid_child > 0){ /* I'm the child*/
waitpid(pid_child,NULL,0);
printf("I'M THE CHILD\n");
return 0; /*Terminates the new process*/
}
}else if(pid > 0){ /*I'm the parent*/
waitpid(pid,NULL,0); /*Waiting for the child*/
printf("I'M THE PARENT\n");
}
return 0;
}

Create multiple generations of children process

So I'm trying to understand the concept of grandchildren.
I'm able to create a given number of sons (i.e brothers) but I don't know how to create multiple generations .
This is what I did to create one grandson :
int main ()
{
//Displaying the father
printf("Initial : Father = %d\n\n", getpid());
/****** FORK *******/
pid_t varFork, varFork2;
varFork = fork();
if(varFork == -1) //If we have an error, we close the process
{
printf("ERROR\n");
exit(-1);
}
else if (varFork == 0) //if we have a son, we display it's ID and it's father's
{
printf("SON 1\n");
printf(" ID = %d, Father's ID = %d\n", getpid(), getppid());
varFork2 = fork();//creation of the second fork
if(varFork2 == -1) //If we have an error, we close the process
{
printf("ERROR\n");
exit(-1);
}
else if (varFork2 == 0) //now we have the son of the first son, so the grandson of the father
{
printf("\nGRANDSON 1\n");
printf(" ID = %d, Father's ID = %d\n", getpid(), getppid());
}
else sleep(0.1);/*we wait 0.1sec so that the father doesn't die before we can
display it's id (and before the son process gets adopted by a user process descending from the initial process)*/
}
else //in the other case, we have a father
{
sleep(0.1);//again we put the father asleep to avoid adoption
}
return 0;
}
How can I create X generations of grandsons, X being a global variable (1son, 1 grandson, 1 great-grandson, etc.) ?
How can I create X generations
Before forking, decrement X and continue forking inside the child until X is 0.
Or inside the child decrement X and only continue forking if after decrementing it X still is greater 0.
The code might look like this:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
void logmsg(const char *, int);
#define MAX_GENERATIONS (4)
int main(void)
{
pid_t pid = 0;
for (size_t g = 0; g < MAX_GENERATIONS; ++g)
{
logmsg("About to fork.", 0);
switch (pid = fork())
{
case -1:
{
logmsg("fork() failed", errno);
break;
}
case 0:
{
logmsg("Hello world. I am the new child.", 0);
break;
}
default:
{
char s[1024];
snprintf(s, sizeof s, "Successfully created child carrying PID %d.", (int) pid);
logmsg(s, 0);
g = MAX_GENERATIONS; /* Child forked, so we are done, set g to end looping. */
break;
}
}
}
logmsg("Sleeping for 3s.", 0);
sleep(3);
if (0 != pid) /* In case we forked a child ... */
{
logmsg("Waiting for child to end.", 0);
if (-1 == wait(NULL)) /* ... wait for the child to terminate. */
{
logmsg("wait() failed", errno);
}
}
logmsg("Child ended, terminating as well.", 0);
return EXIT_SUCCESS;
}
void logmsg(const char * msg, int error)
{
char s[1024];
snprintf(s, sizeof s, "PID %d: %s", (int) getpid(), msg);
if (error)
{
errno = error;
perror(s);
exit(EXIT_FAILURE);
}
puts(s);
}
The output should look similar to this:
PID 4887: About to fork.
PID 4887: Successfully created child carrying PID 4888.
PID 4887: Sleeping for 3s.
PID 4888: Hello world. I am the new child.
PID 4888: About to fork.
PID 4888: Successfully created child carrying PID 4889.
PID 4888: Sleeping for 3s.
PID 4889: Hello world. I am the new child.
PID 4889: About to fork.
PID 4889: Successfully created child carrying PID 4890.
PID 4890: Hello world. I am the new child.
PID 4890: About to fork.
PID 4889: Sleeping for 3s.
PID 4890: Successfully created child carrying PID 4891.
PID 4890: Sleeping for 3s.
PID 4891: Hello world. I am the new child.
PID 4891: Sleeping for 3s.
PID 4888: Waiting for child to end.
PID 4890: Waiting for child to end.
PID 4891: Child ended, terminating as well.
PID 4890: Child ended, terminating as well.
PID 4887: Waiting for child to end.
PID 4889: Waiting for child to end.
PID 4889: Child ended, terminating as well.
PID 4888: Child ended, terminating as well.
PID 4887: Child ended, terminating as well.
The difference with my code above compared to the proposal I made is that it counts upwards to X.

Process IDs and fork()

I have an assignment that is asking me to identify the values of the process IDs at lines A, B, C, and D, assuming that the actual pids of the parent and child are 2600 and 2603, respectfully.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid, pid1;
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if(pid == 0){ /* child process */
pid1 = getpid();
printf("child: pid = %d", pid); /* A */
printf("child: pid1 = %d", pid1); /* B */
}
else { /* parent process */
pid1 = getpid();
printf("parent: pid = %d", pid); /* C */
printf("parent: pid1 = %d", pid1); /* D */
wait(NULL);
}
}
I've already been given the solutions for the problem, but I'm having trouble understanding the fork() function. Why would it return EITHER -1, 0, or some positive number? Why does it not consistently return a certain value? For example, when we assign pid = fork(), it can be a value of -1, 0, or some positive number. Even if I know that, I don't know how the values become what they are. I know that, initially, the child process is given a copy of the parent data. Ordinarily, my tactic is to step through the code line-by-line and adjust the variables as they are modified to determine output, but this example seems nondeterministic. I feel like I'm viewing this problem completely wrong, but I don't know how to change my thought process. I've reviewed the documentation for fork() here but it didn't clarify anything for me.
Additionally, why don't we use a get function, i.e. pid.getID() in the if/else-if statements? Doesn't this mean that pid_t and int are equivalent?
A step-by-step explanation of this code would be greatly appreciated.
For reference, the solutions are 0, 2603, 2603, and 2600.
fork() creates a new process that's an almost exact duplicate of the original process. Both processes continue running, starting from the return of the fork() function. In the parent process, fork() returns the PID of the child (a positive number), while in the child process fork() returns 0 (that's how it knows that it's the child).
If, for some reason, the system wasn't able to create a new process, fork() returns -1 in the parent instead of the child's PID, and errno is set to the error code with the reason for the failure.
You could do an equivalent test using getpid(), it would just be more work:
pid_t parentPID = getpid();
fork();
pid_t myPID = getpid();
if (myPID == parentPID) {
// this is the parent
} else {
// this is the child
}
Having fork() return 0 in the child simplifies it, since you get all the information you need from that one call, instead of having to call getpid() twice.

Setting up four processes with fork() using 1 pipe

Trying to write a simple program that uses pipe/fork to create/manage 1 parent and 4 kid processes. The parent process is supposed to display a main menu like so.
Main Menu:
1. Display children states
2. Kill a child
3. Signal a child
4. Reap a child
5. Kill and reap all children
The code I'm writing now is supposed to create 4 child processes. I'm unsure if I'm setting up the four child processes correctly. I understand fork returns 0 to the child and the PID to the parent. How do I access the parent for these PID values? Where exactly do I set up the menu for the parent process?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define BUFSIZE 1024
#define KIDS 4
main()
{
//create unnamed pipe
int fd[2];
char buf[BUFSIZE];
if (pipe(fd) < 0)
{
perror("pipe failed");
exit (1);
}
//array of child pids
size_t child_pid[4];
//create 4 proccesses
int i = 0;
for (i = 0; i < KIDS; i++) {
child_pid[i] = fork();
if (child_pid[i]) {
continue;
} else if (child_pid[i] == 0) {
close(fd[0]);
printf("Child %d: pid: %zu", i+1, child_pid[i]);
break;
} else {
printf("fork error\n");
exit(1);
}
}
}
My output is:
Child 1: pid: 0
Child 2: pid: 0
Child 3: pid: 0
Child 4: pid: 0
I'm unsure if I'm setting up the four child processes correctly.
Right, you shouldn't let the children break out of their code block, so change
break;
to
sleep(99); // or whatever you want the child to do
exit(0);
How do I access the parent …?
There's getppid(), if for some reason you need it.
Where exactly do I set up the menu for the parent process?
Do that after the for loop before the end of main, that's where the parent continues execution.

How to use Fork() to create only 2 child processes?

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!

Resources