Finding the level of a child process in a process tree - c

I've been trying to create a process tree using fork() and print each child's level (0 for base process, 1 for its child, 2 for its grandchild etc.) in the tree. The code below only works for depth 0 and 1. Any idea how I can improve it?
Thanks.
#include <stdio.h>
#include <unistd.h>
int i;
int main()
{
pid_t baseID = getpid();
printf("Base Process ID: %d, level: 0 \n", baseID);
for (i = 0; i < 3; i++) {
int level = 1;
pid_t pid;
pid = fork();
if (pid == 0) {
pid_t childID = getpid();
pid_t parentID = getppid();
if (parentID == baseID) {
level = 1;
}
else {
// do something for grandchildren here
level++;
}
printf("Process ID: %d, Parent ID: %d, level: %d \n", getpid(), getppid(), level);
}
else {
wait(NULL);
}
}
return 0;
}

The intended process tree is the following:
0
|->1
| |->2
| | |->3
| |
| |->2
|
|->1
| |->2
|
|->1
So to be able to print the level of each process, we should just initialize the level variable to 0 outside the main for loop and just increment its value each time a child process is created.
The following code will print the level of each child process as expected:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t baseID = getpid();
printf("Base Process ID: %d, level: 0 \n", baseID);
int level = 0;
for (int i = 0; i < 3; i++) {
pid_t pid = fork();
if (pid == 0) { // Child
pid_t childID = getpid();
pid_t parentID = getppid();
level++;
printf("Process ID: %d, Parent ID: %d, level: %d \n", getpid(), getppid(), level);
} else { // Parent
wait(NULL);
}
}
return 0;
}

Related

fork() 4 children in a loop

The goal is to try and fork 4 children in a loop, but I'm not sure how to properly do that. This is what I have so far. I tried to draw it out and I think I'm not waiting to reap the child properly. And I create like 2 children every iteration. So, 8 children in total.
void main() {
int i = 0;
pid_t pid;
int status;
for(i = 0; i < 4; i++) {
pid = fork();
if(pid == 0) {
/* Child Process */
fork();
exit(0);
} else {
/* Parent Process */
wait(&status);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
}
Creating four children processes from the same parent process can be achieved by forking once on each iteration of the for loop:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0)
exit(0); // child process
// parent process
wait(NULL);
printf("At i = %d, process %d is terminated.\n", i, pid);
}
}
However, you probably want the parent process to wait for the children after it has created all of the four children, because you usually want the children to do something before exiting and concurrently with the other children:
int main() {
// create the four children processes
for (int i = 0; i < 4; i++) {
pid_t pid = fork();
if (pid == 0) {
// child process
// ... do some stuff ...
exit(0);
}
}
// wait for the four children processes to finish
for (int i = 0; i < 4; i++) {
pid_t pid = wait(NULL);
printf("Process %d is terminated.\n", pid);
}
}

How to modify code to match output Linux

Code below outputs child and parents PID output however need it to look more like the sample output below. How could I modify my code to allow this to happen.
Any help is greatly appreciated.
parent process: counter=1
child process: counter=1
parent process: counter=2
child process: counter=2
The code is (edited to fix missing semicolon and make more readable):
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void) {
int pid;
pid = fork();
if (pid < 0)
{
printf("\n Error ");
exit(1);
}
else if (pid == 0)
{
printf("\n Child Process ");
printf("\n Pid is %d ", getpid());
exit(0);
}
else
{
printf("\n Parent process ")
printf("\n Pid is %d ", getpid());
exit(1);
}
}
You have a missing ; in your code, so it wouldn't compile cleanly. Also, there is no loop outputting the text that you require.
Consider instead the following:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main()
{
pid_t pid;
char *child = "child";
char *parent = "parent";
char *me;
pid = fork();
if (pid < 0) {
perror("fork()");
exit(EXIT_FAILURE);
} else if (pid == 0)
me = child;
else
me = parent;
for (int i = 0; i < 2; ++i)
printf("%s: counter is %d\n", me, i + 1);
return EXIT_SUCCESS;
}
This calls fork() and detects whether the current process is the child or the parent. Depending on which it is, we point me to the correct string and enter a short loop that just prints our string and the counter.
The output may be
parent: counter is 1
parent: counter is 2
child: counter is 1
child: counter is 2

Not sure why 1 printf statement prints twice

UPDATE
I thought this code block was giving me an error printing a printf statement out twice, but I commented out everything in my code BESIDES this and it worked just fine! What seems to be the issue then is the work I am doing with process IDs.
Here is the entire code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid, pid1;
int n;
int temp;
int stop = 1;
if (argc == 1) {
fprintf(stderr,"Usage: ./a.out <starting value>\n");
return -1;
}
n = atoi(argv[1]);
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\n", pid);
printf("child: pid1 = %d\n", pid1);
}
else { /* parent process */
pid1 = getpid();
printf("parent: pid = %d\n", pid);
printf("parent: pid1 = %d\n", pid1);
wait(NULL);
}
while (n!=1) {
if (n%2 == 0) {
printf("%d, ", n);
temp = (n/2);
n = temp;
}else {
printf("%d, ", n);
temp = (3*n+1);
n = temp;
}
}
printf("1\n");
return 0;
}
The output I'm expecting is something like:
parent: pid = 1444
parent: pid1 = 1443
child: pid = 0
child: pid = 1444
8, 4, 2, 1
But instead I get this Output:
parent: pid = 1444
parent: pid1 = 1443
child: pid = 0
child: pid = 1444
8, 4, 2, 1
8, 4, 2, 1
Might a child a parent process be printing out the sequence a second time?
Yes, once the parent process has wait()ed on the child process, it continues down the code path and prints the sequence.
What you want is:
// ....
else if (pid == 0) { /* child process */
pid1 = getpid();
printf("child: pid = %d\n", pid);
printf("child: pid1 = %d\n", pid1);
while (n!=1) {
if (n%2 == 0) {
printf("%d, ", n);
temp = (n/2);
n = temp;
}else {
printf("%d, ", n);
temp = (3*n+1);
n = temp;
}
}
} else { /* parent process */
pid1 = getpid();
printf("parent: pid = %d\n", pid);
printf("parent: pid1 = %d\n", pid1);
wait(NULL);
}
After
wait(NULL);
You need an exit/return. The parent has done its job of bringing up the child and is done

using execv instead of execl in linux

I wrote a program to use execl and I want to have the same functionality but instead use execv.
here is my program from execl:
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
int pid, status,waitPid, childPid;
pid = fork (); / Duplicate /
if (pid == 0 && pid != -1) / Branch based on return value from fork () /
{
childPid = getpid();
printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
execl("/bin/cat","cat","-b","-t","-v",argv[1],(char*)NULL);
}
else
{
printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
waitPid = wait(childPid,&status,0); / Wait for PID 0 (child) to finish . /
}
return 1;
}
I then tried modifying it as such in order to use execv instead, but I could not get it to work (as in it would say no such file or directory found)
You call the program with ./ProgramName testfile.txt
Here is my attempting at execv:
#include <stdio.h>
#include <unistd.h>
int main ()
{
int pid, status,waitPid, childPid;
char *cmd_str = "cat/bin";
char *argv[] = {cmd_str, "cat","-b","-t","-v", NULL };
pid = fork (); / Duplicate /
if (pid == 0 && pid != -1) / Branch based on return value from fork () /
{
childPid = getpid();
printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
execv(cmd_str,argv);
}
else
{
printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
waitPid = wait(childPid,&status,0); / Wait for PID 0 (child) to finish . /
}
return 1;
}
Any help would be huge, have been stuck on this for quite a while now. Thanks!
You have a few errors in the code, which I marked down:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) // <-- missing argc/argv
{
int pid, status,waitPid, childPid;
char *cmd_str = "/bin/cat"; // <-- copy/pasta error
char *args[] = { "cat", "-b", "-t", "-v", argv[1], NULL }; // <-- renamed to args and added argv[1]
pid = fork (); // Duplicate /
if (pid == 0) // Branch based on return value from fork () /
{
childPid = getpid();
printf ("(The Child)\nProcess ID: %d, Parent process ID: %d, Process Group ID: %d\n",childPid,getppid (),getgid ());
execv(cmd_str,args); // <-- renamed to args
}
else
{
printf ("(The Parent)\nProcess ID: %d, The Parent Process ID: %d, Process Group ID: %d\n",getpid (),getppid (),getgid ());
waitPid = wait(childPid,&status,0); // Wait for PID 0 (child) to finish . /
}
return 1;
}

creating a second process in C

Im new in C programming and i have to do this:
Write a program that creates a second process, and then in both processes outputs the process ID and the owners user ID.
I don't know if thats right and how to continue from here. Here is what i have:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int ChildPID;
printf("This is the parent process number %d\n",getpid());
if ((ChildPID = fork()) == -1) {
perror("Could not fork");
exit(EXIT_FAILURE);
}
if (ChildPID == 0) {
//----In the child process
printf("This is the child process, number %d parent number %d\n", getpid(), getppid());
}
return(EXIT_SUCCESS);
}
The piece of code given below gives your solution. Here you can clearly identify parent code and child process code. Both are printing their corresponding pids.
void ExecuteChild(void);
void ExecuteParent(void);
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ExecuteChild();
else
ExecuteParent();
}
void ExecuteChild(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("CHILD[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Child Exiting -------------\n");
}
void ExecuteParent(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("PARENT[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Parent Exiting -------------\n");
}

Resources