Tracing the execution of a process - c

I have this code that gets its process ID and its parent process:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
int pid;
printf("I am the original process with PID %d and PPID %d. \n", getpid(), getppid());
pid = fork();
if (pid >0){
printf("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
printf("My child’s pid is %d \n" , pid);
}
else if(pid == 0) {
printf ("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
}
else if (pid == 1){
printf ("Error – no child process was created \n");
}else{
printf ("Error – system error \n");
}
printf (" PID %d terminates \n", getpid()); /* both processes execute this instruction */
return 0;
}
OUTPUT
I am the original process with PID 1009 and PPID 964.
I am the original process with PID 1009 and PPID 964
My child’s pid is 1010
PID 1009 terminates
I am the original process with PID 1010 and PPID 1009
PID 1010 terminates
Few questions that confuses me..
how does this code is executed?
In the output, you can see that it runs the code under under if(pid == 0) while the condition if(pid > 0) is already executed. how come pid is equal to 0? while it was set already to greater than 0.
Lastly , what does fork() really do?

fork() makes multiple processes, or a "child". So the parent and child execute the code. The parent's pid is > 0 and the child's is ==0.
So, the parent and child execute at similar times starting at the fork command. So let's start with the parent. The parent checks the first statement (pid > 0) and finds it is true, so it prints out the two statements. Then it goes all the way to the print statement after the last else.
Now to the child. The child checks the first if statement, and is false. Checks the next (pid == 0) and finds it is true. So now it's going to print out that statement. Now it will skip to the print statement after the else and prints again.
Note: The parent and child can execute at different times, so if you run the code multiple times the output may be in a different order.

Related

Why child_1 will print before parent?

I have a C code that a parent process will fork() a child process:
int main(){
pid_t child_1;
child_1 = fork();
if (child_1 > 0){
printf("Parent: (PID %d)\n", getpid());
wait(NULL);
}
else if (child_1 == 0){
printf("child: %d", getpid());
}
}
And the output is:
Parent: (PID 1234)
child: 1235
But if I removed the \n in the printf of parent, the output would become:
child: 1235Parent: (PID 1234)
I'm not sure why and I've tried on different OS and the output is the same. Thanks in advance.
printf is line buffered. Which means it won't actually output until a newline is encountered or an explicit flush is done (such as when the process exits). So in your case removing the newline changes when the parent process actually outputs. Since the parent waits for the child to exit it means the parent flush will occur after the child has outputted.

fork() and parent/child process ids

I am a bit confused about why the child process in the following two programs is showing different parents ids.
First program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
pid = getpid();
ppid = getppid();
printf ("fpid is %d\n", fpid);
sleep(5);
if (fpid > 0){
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is 53560
fpid is 0
This is Parent. My pid 53559. My parent's pid 44632
MacBook-Pro:~/Desktop/$
This is Child. My pid 53560. My parent's pid 53559
Second program:
int main ( void ) {
int pid, fpid, ppid;
fpid = fork ();
printf ("fpid is is %d\n", fpid);
sleep(5);
if (fpid > 0){
pid = getpid();
ppid = getppid();
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n",pid,ppid);
}
else if (fpid ==0){
sleep(1);
pid = getpid();
ppid = getppid();
printf ("\nThis is Child. My pid %d. My parent's pid %d\n",pid,ppid);
}
else
printf ("fork failed\n");
return (0);
}
Output:
fpid is is 53635
fpid is is 0
This is Parent. My pid 53634. My parent's pid 44632
MacBook-Pro:~/Desktop$
This is Child. My pid 53635. My parent's pid 1
I understand that process 1 is the process that takes over as a parent once the original parent terminates. I guess what I want to know is: isn't the parent process being finished before the child process can process its printf in both cases? Shouldn't the outputs be the same?
Since parent and child processes run concurrently, the order of execution depends on runtime. One of them can finish earlier. When parent finishes before child reaches its getppid(), child process would be adopted by init. Hence the parent id 1.
To see child's actual parent process id:
Let the parent wait for its child termination using wait() or waitpid(), or
Let parent sleep for some perceivable amount like sleep(120) after 'This is parent' printf().
isn't the parent process being finished before the child process can process it's printf in both cases?
Very likely so, but not absolutely certain. You cannot ensure that by sleep()ing for any length of time.
Shouldn't the outputs be the same?
They could be the same, but they are unlikely to be. It's important to note when in each program getppid() is called. The parent process ID reported is the one that applied at the time of the call; it is not necessarily still applicable later, when the value is printed.

C program to get child process id's from just a parent id (minix) [duplicate]

This question already has an answer here:
Printing child processes given a pid (MINIX)
(1 answer)
Closed 6 years ago.
So given a process id passed to the system call, I need to return all child process ids. This must be written in C. I have used mproc to get the parent process of a child pid and list all processes from a certain index but cannot make the leap from that to this.
My code:
int do_getchildpids() {
// get pid from parameter
int ppid = m_in.m1_i1;
// Get the child pid of this process
pid_t cpid;
if (cpid == fork()) {
printf("Child pid for ppid %d is %d\n", ppid, getpid());
}
// ** Other attempt at this problem below **
// if mp_parent == ppid then print pid
int idx = 0;
int cpid = mproc[idx].mp_pid;
while (mproc[idx].mp_pid) {
idx++;
}
printf("Searching for children of %d...\n", ppid);
if (pid == 0) {
// for loop that gets the ppid, checks against given ppid
// prints out pid if true
if (cpid) {
// loop through proc table checking if ppid is equal to parameter passed
if (ppid == mproc[mproc[i].mp_parent].mp_pid)
printf("Child pid is %d.\n", getpid());
}
printf("Child pid is: %d.\n", getpid());
} else {
printf("Error, child pid was not set or is -1\n");
}
return 0;
}
This is a very janky solution, but if you're running linux and you want to get the children of a parent process you could use the linux pgrep command, either by using fork() and execv() or by a simple system() call. Then pipe the output to a file and read that file's contents
system("pgrep -P [parent_pid] 1>[outputfile]")
fp = fopen([outputfile], "r")
while (fscanf(fp, "%d", &child_pid) != EOF){
<add child_pid to a list you've made>
}
fclose(fp)
There's definitely a better way to do this though. Look into if it's possible to call ps or pgrep from a c program.

Creating three children in C that have the same parent

My problem is that the children does not have the same parent and does not appear correctly, here is my code:
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
pid_t pid[3];
pid[0] = fork();
if(pid[0] == 0)
{
/* First child */
pid[1] = fork();
if(pid[1] == 0)
{
/* First child continued */
printf("Hello, I'm the first child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
else
{
/* Second child */
pid[2] = fork();
if(pid[2] == 0)
{
/* Second child continued */
printf("Hello, I'm the second child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
else
{
/* Third child */
printf("Hello, I'm the first child! My PID is : %d, My PPID is: %d", getpid(), getppid());
sleep(1);
}
}
}
else
{
/* Parent */
sleep(1);
wait(0);
printf("Hello, I'm the parent! My PID is : %d, My PPID is: %d", getpid(), getppid());
}
return 0;
}
As of right now when i run the program i will get this as output in bash, where bash has the PID of 11446:
>Hello, I'm the third child! My PID is: 28738, My PPID is: 28735
>Hello, I'm the first child! My PID is: 28742, My PPID is: 28738
>Hello, I'm the second child! My PID is: 28743, My PPID is: 28738
>Hello, I'm the parent! My PID is: 28753, My PPID is: 11446
How do i get the first child to appear first, second child to appear second and the third child to appear last, and get all the children to have the PPID 28753
From man fork:
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.
Your if-else conditions are swapped.

c - printf c issues in terminal

I have the following code in my main:
//testing with fork
printf("I am process: %d\n", getpid());
pid_t pid = fork();
printf("Now I am process: %d\n", getpid());
printf("fork returned %d\n", pid);
if(pid == 0){
printf("I am child %d\n", getpid());
}
However the output on my terminal gives me this:
terminal output pic
I run my program with a param of 'config_file.txt' as you can see on the first line, and the rest of it prints out fine until it hits the fork, and my cmd line comes up in between it...any ideas on why that is or how I can fix it? Is there something wrong with the code? I was just following a simple forking tutorial.
Edit: Also, after running it my program hangs there, and I have to hit enter to get my cmd line back up.
What's happening is that the parent process is finishing before the child process. When the parent finishes the prompt is displayed, however since the child is still running it continues to print output to the console.
If you want the parent to wait until the child is done, use the wait() function:
printf("I am process: %d\n", getpid());
pid_t pid = fork();
printf("Now I am process: %d\n", getpid());
printf("fork returned %d\n", pid);
if(pid == 0){
printf("I am child %d\n", getpid());
} else {
wait(NULL);
}

Resources