Determining how many processes run using fork - c

I have this snippet code, and I would like to determine how many processes run_morecompute. I am learning OS and I am struggling with the concept of forking.
Thank you
void run_morecompute(int i){
printf("hello world");
}
void run_compute(int i) {
int cpid = fork();
if (cpid == 0)
run_morecompute(i);
}
int main (){
int pid;
for (int i = 0; i < 4; i++) {
pid = fork();
if (pid == 0){
printf("\n%d",i);
run_compute(i);
}
}
}

If you change
printf("hello world");
to
printf("hello world from %d", getpid());
It will add the process ID to the output. It may help you understand how many processes get created.
I'd suggest changing the loop in main to just call run_morecompute() until you get a handle on what is happening. The additional fork() in run_compute() makes things more complicated.
The top level process forks 4 child processes that call run_compute(). Those 4 children then become parents and fork 3 more children each. Then those 12 children fork 2 more processes each... etc.
Hope that helps.

Related

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).

How can I print multiple things in a row with using only fork() and if?

after hours of searching I ended up here. Here's my problem:
I have an exercise I need to do.The code given is this:
int main(){
int x,y,z....;
//
fill the gap
//
printf("A");
//
fill the gap
//
printf("B");
return(0);
}
I must print exactly "AAAAABBB" with using ONLY fork(),if and exit().
(no "wait", no multiple "printf", no "sleep". no "for")
How could I do it? I have tested it in online IDEs but I just cant print them in this exact way. The output is always confusing (AABBBAA, ABABABAA etc.) I can't seem to understand how to give priority to the parent or child without using anything but fork() and if.
Any tip is appreciated.
What you are supposed to be learning here is that fork() duplicates your process - at the point of the fork(). It returns a Process IDentifier (PID) number to the parent process, and zero to the child process.
So by simply watching the return of the fork(), the execution path can determine if they are the parent or child process.
Thus to implement the problem, I took the approach of controlling everything from the single parent process, and having the child simply output a letter, then exit() - which terminates the process.
It would be much nicer with a for() loop, but that was not allowed.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pid = fork();
if (pid != 0)
pid = fork();
if (pid != 0)
pid = fork();
if (pid != 0)
pid = fork();
if (pid != 0)
pid = fork();
if (pid == 0)
{
// child process only
printf("A");
exit(0);
}
pid = fork();
if (pid != 0)
pid = fork();
if (pid != 0)
pid = fork();
if (pid == 0)
{
// child process only
printf("B");
exit(0);
}
return 0;
}
Note: I suspect that it may occasionally get mixed up due to system load, scheduling, etc. But in all my tests I received the correct answer.

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;
}

Spawning C child process for different jobs?

So I am trying do a application which fork()s 2 children.
first does a for(i=1; i<=50000; i++) loop
the second a for(i=50000; i<=100000; i++) loop
the parent does for(asciic=65; asciic<=90; asciic++)-> loop for printing A to Z letters
I need all three to do they're work simultaneous not one after another.
I've looked over the internet and I couldn't found a proper way, all I could find are loops which create the children processes but they do almost the same thing and most are created one after another.
Any help is appreciated.
To be more understood, this is what I've done before posting:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t child_pid,child_pid1;
int i=0;
int stare;
int asciic;
child_pid=fork();
child_pid1=fork();
if (child_pid==0) {
//printf("Father PID: %d -> Child 1: %d\n",getppid(),getpid());
for(i=1; i<=50000; i++){
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else if (child_pid1==0) {
//printf("Father PID: %d -> Child 2: %d\n",getppid(),getpid());
for(i=50000; i<=100000; i++) {
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else {
//printf("PID-ul procesului parinte: %d\n", getpid());
pid_t rez=waitpid(child_pid,&stare,WNOHANG);
pid_t rez1=waitpid(child_pid1,&stare,WNOHANG);
while(rez==0 || rez1==0){
for(asciic=65; asciic<=90; asciic++){
printf("%d- %c\n",getpid(),asciic);
}
rez=waitpid(child_pid,&stare,WNOHANG);
rez1=waitpid(child_pid1,&stare,WNOHANG);
}
}
return 0;
}
If I comment out the loops I can see that the children have different PIDs, 1 child has the right parent PID and other it has other parent PID.
Your 2 lines with forks:
child_pid=fork();
child_pid1=fork();
do not create 2 children, but three: the parent creates a first child in the first fork(). From that moment there are 2 processes: parent and child. And each of them executes the second fork(). You will have in total 1 parent, 2 children and 1 grandchild.
In order to have just 1 parent and 2 children, you will have to:
pid1 = fork();
if (pid1 < 0) {
/* Error in fork() */
} else if (pid1 == 0) {
/* first child */
exit(0);
}
pid2 = fork();
if (pid2 < 0) {
/* Error in fork() */
} else if (pid2 == 0) {
/* second child */
exit(0);
}
/* parent */
Moreover, even when your code is correct, you cannot "see" if the processes are running concurrently or not just looking at their outputs. In fact, even if there are multiple processes executing "at the same time", you may see that one of the processes finishes before another one starts. That is because typically the kernel does time multiplexing to offer each child some CPU time. You can see concurrency if the processes take longer to complete, for example adding some sleep().
The problem is here:
child_pid=fork();
child_pid1=fork(); // This line will be executed by both parent and first child!!!
You need to move the second fork into the parent part of the first if, and then have a separate if for the second child.
fork() returns the pid_t of the child to the caller (parent), or -1 if it failed. In the child, 0 is returned. You can simply test
if (fork())
{
//do one thing
}
else
{
//do something else
}

Recursive Fibonacci using Fork in C (Pt 2)

I'm attempting to write a function that recursively computes the resulting fibonacci number from a given int n using forks in C.
Here is the function specification: If doPrint is true, print it. Otherwise, provide it to the parent process. The solution should be recursive and it must fork a new child for each call. Each process should call doFib() exactly once. The method signature cannot be changed. Helper functions cannot be used.
This is a continuation of this question: Recursive Fibonacci using Fork (in C)
Unfortunately, I never figured out a solution to the problem in the last post, however this is my modified code. I thought I had it figured out (psuedo code wise) but came to find out that I still am unsure about a few pieces.
At this point, this is solely for my amusement. This is not homework and won't be covered in my class again (after the most recent test, which has passed).
static pid_t root_pid;
// Function to return exit code for PID
static int exitcode(pid_t pid)
{
pid_t retpid;
int status;
retpid = waitpid(pid, &status, 0);
if (pid != retpid)
{
printf("waitpid error\n");
}
return WEXITSTATUS(status);
}
static void doFib(int n, int doPrint)
{
root_pid = getpid();
pid_t pid1;
int status1;
pid_t pid2;
int status2;
if(n < 2) // Base case, exit back to parent?
{
exit(n);
}
else // if not base case, fork child processes
{
pid1 = fork();
if (pid1 == 0) // Child Process 1 (for fib(n-1))
{
doFib(n-1, doPrint);
exit(n-1);
}
else if (pid1 > 0) // Parent Process
{
pid2 = fork();
if (pid2 == 0) // Child Process 2 (for fib(n-2))
{
doFib(n-2, doPrint);
exit(n-2);
}
// Get value from child process 1
status1 = exitcode(pid1);
// Get value from child process 2
status2 = exitcode(pid2);
// When to print?
if (getpid() == root_pid)
{
int result = status1 + status2;
if (doPrint)
{
printf("%d\n", result);
}
else
{
exit(result);
}
}
}
}
}
A few questions...
Do I need to call both of these functions for each child process?
doFib(n-1, doPrint); exit(n-1);
Is my base case at the beginning correct? (n < 2)
Is my base case at the end correct? (when to print)
Thank you for any help.
The answer for "when to print" really comes down to what you want to print ... if you only want to print the final answer, then you'll most likely need a flag that indicates when you're in the root parent process, and use the if statement to test if you are indeed the root parent so that you only print a single number. If on the other-hand you want to print the entire sequence up to the final number, then an if statement is not needed.
For instance, a good flag value would be the PID of the root process. You could save this in a global variable called root_pid in the first couple lines of main() before you start your forking off of separate child processes. That way all the child processes will have the same value set for root_pid, and the if statement can simply be if (getpid() == root_pid).
So do something like this:
//fib.c
#include <unistd.h>
pid_t root_pid
int main()
{
root_pid = getpid();
//... rest of your program
}
And as mentioned above, make your if statement inside of doFib the following:
if (getpid() == root_pid)
{
//...print results
}
else
{
exit(result)
}

Resources