Code (with fork) that shouldn't loop is looping - c

So I have the following C code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
int i = 0, n;
n = 5;
pid_t pid;
printf("i=%d Right before the loop\n", i, getpid(), getppid());
for (i = 0; i < n; i++){
pid = fork();
if (pid <= 0){
printf("something happens in loop #%d. pid = %d\n", i, pid);
break;
}
printf("End of loop #%d\n", i);
}
printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());
return 0;
}
I have only one question:
Why does
printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());
get executed many times as if it was inside the loop? I have tried to figure out through so many ways but I cannot find the reason.

The reason is that fork() works by making a child process that is a copy of the parent that starts running at the fork() call. So every child process runs that printf command.
Example:
Here's a less complicated example:
#include <stdio.h>
int main(){
int pid = fork();
if (pid == 0){
// child code
printf("child pid: 0\n");
}else{
// parent code
printf("parent pid: %d\n", pid);
}
// executed by both
printf("This text brought to you by process %d.\n", pid);
}
You have to do something like this if you want to restrict some code to only be run by the child or parent.
On my machine, when I just ran it, it outputs:
parent pid: 12513
This text brought to you by process 12513.
child pid: 0
This text brought to you by process 0.
My operating system ran the parent process first, but it didn't have to.

If you are not aware of fork() and using it, it is dangerous.
This is one of the basic system calls in Linux used for creating a new process. Refer to Man page to know what it does. And here is one helpful link to make you understand better. fork().
To know more about it you could also refer here- fork() wiki. It uses methods like copy-on-write and shares the resources with child.
Once you have used fork() to create the new process, you can use exec(...) to change the program that the process is executing. After reading about each of them, you may refer to this post on so.

Related

How to write a program that creates 2 parent processes and one child for each?

I'm not sure what does this code do.
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
for(int i=0; i<2; i++)
{
int pid=fork();
if(pid==0)
{
printf("child process \n");
printf("Child pid id [%d], parent pid is [%d]\n", (int) getpid(), (int) getppid());
} else if(pid>0)
{
int stats;
wait(&stats);
printf("parent process \n");
printf("Child pid id [%d], parent pid is [%d]\n", (int) getpid(), (int) getppid());
}
}
return 0;
}
I call fork() and assign it's value to variabe pid. Then we go to int stats, next line returns pid=0, then the program displays child process and then the parent process. It works pretty nice, but only when i<1. I thought that it is possible to do the same thing once again, but it's strange. fork() creates a new child process, so if it is used only once, if should create a child process, which parent is an IDE. Why am I wrong and what should I change to make 2 parents and 1 child for each, basically 4 processes?
I am not completely sure what you mean by "2 parents". In any case, you need to return the child so that they do not loop again:
printf("Child pid id [%d], parent pid is [%d]\n", (int) getpid(), (int) getppid());
return 0;
Otherwise you will have the children spawning other processes.

Fork wait and pipe in C

I have this assignment where we are supposed to create a specific amount of child processes, lets say 3, and make the parent wait for each child to finish. Also we're supposed to have a pipe that all processes write to so that once the parent is done waiting, it would use the pipe's to output the sum of all the children's results.
This is my code so far but it seems that wait(NULL) isn't working as expected. I am not sure what I'm doing wrong.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
wait(NULL);
printf("Child %d terminated\n", child);
}
}
printf("Parent terminated\n");
return 0;
}
First of all, it's better to first run all child processes and then wait for all of them, instead of waiting for each one sequentially.
In addition, the child processes should exit immediately and not keep running the forked code.
Thirdly, you must pay attention and wait for all children after the loop, and not only for the first one that terminates:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
for (int i=0; i<3; i++) {
pid_t child = fork();
if (child > 0) {
printf("Child %d created\n", child);
}
else if (child == 0) {
printf("In child %d. Bye bye\n", i);
return 0; // exit the child process
}
}
while (wait(NULL) > 0); // wait for all child processes
printf("Parent terminated\n");
return 0;
}
EDIT:
The code above is just an improvement to the example given in the question. In order to implement the pipe of information from the child processes to the parent, a pipe can be created (using pipe()) and the write-end file descriptor would be accessible from child processes.
Here's a good example to do so.

Fork() code not working as expected - Hierarchy making

Good afternoon.
I am currently working on a C program that takes one and only one parameter which designates the number of "child generation"s to be created (the own father counts as 1 already). "wait()" system calls are not to be used for this exercise (the version with "wait" calls happens to work exactly as expected).
For instance, the call $program 4 should generate a hierarchy like this:
Process A creates B
Process B creates C
Process C creates D
The printed messages are not important, as they are merely orientative for the task. With the following code (which happens to work exactly how I want with a "wait()" call) states that all the child processes derive from the same father, which I don't understand why it's happening.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int counter; pid_t result; int i;
/*
We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
*/
if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
int lim = atoi(argv[1]);
//We eliminate the impossible cases
if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
}
else {
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
}
else if (result) {
break; //Father process
}
else {
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
}
}
}
The hierarchy generated by the code above is not the one I expected...
All help is greatly appreciated.
Thank you
With the following code (which happens to work exactly how I want with
a "wait()" call) states that all the child processes derive from the
same father, which I don't understand why it's happening.
I don't see that in my tests, nor do I have any reason to expect that it's actually the case for you. HOWEVER, it might appear to be the case for you if what you see is some or all of the child processes reporting process 1 as their parent. That would happen if their original parent terminates before the child's getppid() call is handled. Processes that are orphaned in that way inherit process 1 as their parent. If the parent wait()s for the child to terminate first then that cannot happen, but if instead the parent terminates very soon after forking the child then that result is entirely plausible.
Here's a variation on your loop that will report the original parent process ID in every case:
pid_t my_pid = getpid();
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
} else if (result) {
break; //Father process
} else {
pid_t ppid = my_pid; // inherited from the parent
my_pid = getpid();
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
}
}
You are missing a crucial function call.
for (i = 0; i < lim; i++) {
fflush(stdout); // <============== here
result = fork();
Without it, your fork duplicates parent's stdout buffer into the child process. This is why you are seeing parent process output repeated several times --- its children and grandchildren inherit the output buffer.
Live demo (with fixed formatting for your reading convenience).

`fork()` sons are executing in reverse order [duplicate]

This question already has answers here:
In fork() which will run first, parent or child?
(2 answers)
Closed 8 years ago.
I have a code similar to this:
for (i = 0; i < 3; i++)
{
pid = fork();
if (pid == 0)
{
son_function();
}
if (pid < 0)
{
exit(1);
}
}
void son_function(void)
{
printf("my pid=%d\n", getpid());
printf("%d: alpha\n", getpid());
printf("%d: beta\n", getpid());
printf("%d: charlie\n", getpid());
exit(0);
}
For some reason I can't understand, the order of execution of son_function() is in reverse order. What I mean is that son_function() is printing the PID numbers from the largest to the smallest.
Another thing that freaks me is that the prints for every son will be in the one after the other, there's no way that two prints from two different processes will print to the screen at the same time.
Sample can be seen here: http://ideone.com/uBYyRX
Multiple processes can output to the console at the same time, at least under Windows and Linux.
The reason you may see all of one process before all of the other is due to the way your particular OS schedules threads. A better way to see this behavior is to change son_function to look something like the code below, where each child sleeps for a different amount of time. The reason who lines get interleaved (as noted before) is because printf buffers lines of output.
void son_function()
{
srandom(getpid());
int sleepTime = random() % 4; // random sleep between 0 and 3 seconds
printf("pid [%d] sleep time is %d\n", getpid(), sleepTime);
printf("my pid = %d\n", getpid());
sleep(sleepTime);
printf("alpha = %d\n", getpid());
sleep(sleepTime);
printf("beta = %d\n", getpid());
sleep(sleepTime);
printf("charlie = %d\n", getpid());
sleep(sleepTime);
}
To execute the child process in the correct order just add the wait function inside the loop before calling the fork function.
so it will wait till the child terminates and the child process will be terminated in the correct order.
for (i = 0; i < 3; i++)
wait();
pid = fork();
execute the code after adding the wait function.

Can a process have two PIDs?

I'm studying computer systems and I've made this very simple function which uses fork() to create a child process. fork() returns a pid_t that is 0 if it's a child process. But calling the getpid() function within this child process returns a different, nonzero pid. In the code I have below, is newPid only meaningful in the context of the program, and not to the operating system? Is it possibly only a relative value, measured against the pid of the parent?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void unixError(char* msg)
{
printf("%s: %s\n", msg, strerror(errno));
exit(0);
}
pid_t Fork()
{
pid_t pid;
if ((pid = fork()) < 0)
unixError("Fork error");
return pid;
}
int main(int argc, const char * argv[])
{
pid_t thisPid, parentPid, newPid;
int count = 0;
thisPid = getpid();
parentPid = getppid();
printf("thisPid = %d, parent pid = %d\n", thisPid, parentPid);
if ((newPid = Fork()) == 0) {
count++;
printf("I am the child. My pid is %d, my other pid is %d\n", getpid(), newPid);
exit(0);
}
printf("I am the parent. My pid is %d\n", thisPid);
return 0;
}
Output:
thisPid = 30050, parent pid = 30049
I am the parent. My pid is 30050
I am the child. My pid is 30052, my other pid is 0
Lastly, why is the child's pid 2 higher than the parent's, and not 1? The difference between the main function's pid and its parent is 1, but when we create a child it increments the pid by 2. Why is that?
From fork man page :
Return Value
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
Fork does not returns the pid of the child, only in the parent. Therefore, the child process does not have two pids.
Try this
int main(int argc, const char * argv[])
{
pid_t thisPid, parentPid, newPid;
int count = 0;
thisPid = getpid();
parentPid = getppid();
printf("thisPid = %d, parent pid = %d\n", thisPid, parentPid);
if ((newPid = Fork()) == 0) {
count++;
printf("I am teh child. My pid is %d\n", getpid());
exit(0);
}
else
printf("I am the parent. My pid is %d, my child pid is %d\n", thisPid, newPid);
return 0;
}
Pids are one-per process. There will NEVER be more than 1 pid for a process - the internal data structures that handle the process in the OS only have a single PID field in them.
Beyond that, when you call fork() you are cloning the process that called fork, producing an exactly duplicate of it - all file handles, all memory, etc.. EXCEPT for its PID. That's why fork returns different values depending on if you're the child or parent process. This differing return values lets the program know if it's a child or a parent. The child gets 0, and can therefore know it's the child.
No, a pid is assigned to exactly one process at a time.
Process ids do not need to follow any rules when being assigned to processes. So if it looks as if a child pid is the increment of the parent's pid this is just luck.
By the pid of certain processes it is not possible to draw any conclusions regarding the processes relationship.
PIDs are not sequential on assignment (the actually follow no rules) and one process has only one PID at a time. Also there can never be two processes that share the same PID.

Resources