Parameters of the waitpid() - c

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
int status;
int pid = fork();assigned to variable "pid"
if(pid == 0)
{
printf("I am the child with pid = %d\n", getpid());
}
else
{
printf("I am the parent with pid = %d\n", getpid());
waitpid(pid, &status, 0); // line 51
}
return 0;
}
In line number 51, please clarify the "pid" parameter. what will this process wait for?

fork returns 0 for the child process, -1 on error, and something else for the parent process. The else begins the part for the parent process, that means pid in waitpid contains the child's PID.
Citing man wait:
The waitpid() system call suspends execution of the calling
process
until a child specified by pid argument has changed state. By default,
waitpid() waits only for terminated children, but this behavior is mod-
ifiable via the options argument [...]
In short, waitpid waits for the child process to terminate.

If the fork is successful, fork returns 0 to the child, and returns to the parent the (positive) pid of the newly forked child process. In this statement, the parent waits the child's termination.

on success fork will return child id to parent and 0 to child,
waitpid(pid, &status, 0);
parameter.. ) pid - particular child ID.
parameter.. ) &status - exit status that will send to parent by child
parameter.. ) option
0 - option is indicated that
parent will wait till child is terminated.

Related

Example of waitpid() in use?

I know that waitpid() is used to wait for a process to finish, but how would one use it exactly?
Here what I want to do is, create two children and wait for the first child to finish, then kill the second child before exiting.
//Create two children
pid_t child1;
pid_t child2;
child1 = fork();
//wait for child1 to finish, then kill child2
waitpid() ... child1 {
kill(child2) }
Syntax of waitpid():
pid_t waitpid(pid_t pid, int *status, int options);
The value of pid can be:
< -1: Wait for any child process whose process group ID is equal to the absolute value of pid.
-1: Wait for any child process.
0: Wait for any child process whose process group ID is equal to that of the calling process.
> 0: Wait for the child whose process ID is equal to the value of pid.
The value of options is an OR of zero or more of the following constants:
WNOHANG: Return immediately if no child has exited.
WUNTRACED: Also return if a child has stopped. Status for traced children which have stopped is provided even if this option is not specified.
WCONTINUED: Also return if a stopped child has been resumed by delivery of SIGCONT.
For more help, use man waitpid.
The syntax is
pid_t waitpid(pid_t pid, int *statusPtr, int options);
1.where pid is the process of the child it should wait.
2.statusPtr is a pointer to the location where status information for the terminating process is to be stored.
3.specifies optional actions for the waitpid function. Either of the following option flags may be specified, or they can be combined with a bitwise inclusive OR operator:
WNOHANG
WUNTRACED
WCONTINUED
If successful, waitpid returns the process ID of the terminated process whose status was reported. If unsuccessful, a -1 is returned.
benifits over wait
1.Waitpid can used when you have more than one child for the process and you want to wait for particular child to get its execution done before parent resumes
2.waitpid supports job control
3.it supports non blocking of the parent process
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main (){
int pid;
int status;
printf("Parent: %d\n", getpid());
pid = fork();
if (pid == 0){
printf("Child %d\n", getpid());
sleep(2);
exit(EXIT_SUCCESS);
}
//Comment from here to...
//Parent waits process pid (child)
waitpid(pid, &status, 0);
//Option is 0 since I check it later
if (WIFSIGNALED(status)){
printf("Error\n");
}
else if (WEXITSTATUS(status)){
printf("Exited Normally\n");
}
//To Here and see the difference
printf("Parent: %d\n", getpid());
return 0;
}

How to get child PID in C?

I'm creating child processes in a for-loop. Inside the child process, I can retrieve the child PID with getpid().
However, for some reason when I try to store the value of getpid() into a variable declared by the parent process, the change is nullified when I check for it in the parent process. I'm assuming this has to do with some sort of process variable scope. Not really familiar with C, so can't be too sure.
Anyhow what is a way of storing the result of getpid() of a child PID (when called from the child process) into a variable in the parent process?
Or maybe another approach is storing fork() into a variable in the parent and calling some function on that variable to retrieve the child's PID? I don't know how to do this either, so if this is the better way, how would you do this?
fork already returns the child's pid. Just store the return value.
look at man 2 fork:
RETURN VALUES
Upon successful completion, fork() returns a value of 0 to the child process and
returns the process ID of the child process to the parent process. Otherwise, a
value of -1 is returned to the parent process, no child process is created, and
the global variable errno is set to indicate the error.
As mentioned in previous answer that "fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process." So, the code can be written in this way:
pid = fork(); /* call fork() from parent process*/
if (0 == pid)
{
/* fork returned 0. This part will be executed by child process*/
/* getpid() will give child process id here */
}
else
{
/* fork returned child pid which is non zero. This part will be executed by parent process*/
/* getpid() will give parent process id here */
}
This link is very helpful and explains in detail.
if fork() is successfully created then it returns 0 value in the child process.
int main(void)
{
int id;
id= fork();
if(id==0)
{
printf("I am child process my ID is = %d\n" , getpid());
}
}
If you are calling fork in the following way:
pid = fork()
Then pid is in fact your child PID. So you can print it out from the parent.
Yes, the child process's pid is already returned with fork(), fork() is called once but return twice, different return value in parent and child process, so you can do this:
pid_t pid, pid_c;
pid = fork();
if (pid == -1) { // error
perror("Falied to fork");
} else if(pid == 0) { // execute in child process
// you can get child's pid by getpid() in child process:
pid_t tmp_pid_c = getpid();
execl("bin/ls", "ls", "./", NULL);
} else {
// you can also get child's pid that already returned by fork() in parent process
pid_c = pid;
}
There are two main functions to get the process id of parent process and child. getpid() and getppid()

How can parents waits all child processes finish then exit when it receives SIGINT?

I'm writing a multi process program in C.
I hope parents process can wait all child processes finish then exit when
it receives SIGINT.
I have two questions.
How can parents record each pid of child process it forked.
Child process may finish before recording function run on
main process.
If parents has no idea about how many child processes it has. How can he wait
all child process finish.
Thanks in advance.
You record the pid of child processes as you fork them (if required).
call waitpid in a loop with pid = 0 it will either return a pid of a process that exited or return -1 and if errno = ECHILD you have no slaves left.
Keep calling wait(2) in a loop. Every time wait() returns, you'll get back the PID of the exited child and its status. The status will tell you, whether it exited normally (with an exit code) or due to a signal. Something like this (not tested):
#include <sys/types.h>
#include <sys/wait.h>
...
pid_t pid;
int status;
...
while ((pid = wait(&status)) > 0) {
printf("Child %lu ", (unsigned long)pid);
if (WIFEXITED(status))
printf("exited with status %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("killed by signal %d\n", WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("stopped by signal %d\n", WSTOPSIG(status));
else if (WIFCONTINUED(status))
printf("resumed\n");
else
warnx("wait(2) returned for no discernible reason");
}

Understanding how the child process executes in this code

I was given this starter code for a project, but am having difficulty understanding how the child process executes.
int pid ;
int child_info = -1;
if ( argv[0] == NULL ) /* nothing succeeds */
return 0;
if( (pid= fork()==-1)
perror("fork");
else if ( pid == 0 ){
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
execvp(argv[0], argv);
perror("cannot execute command");
exit(1);
}
else { //check if wait error or print out exit status
if ( wait(&child_info) == -1 )
perror("wait");
else {
printf("Exit status: %d, %d\n", child_info>>8, child_info&0377);
}
}
return child_info;
}
Looking at the code, the current process forks and in this case, the child inherits all of the relevant properties of the parent process, since there are no timers, signals or anything involved. However, the pid values of the new processes are in the 18000 range, so how can execvp(argv[0], argv) be executed since in this case, pid != 0.
From the fine manual for fork:
Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the child process to the parent process.
The first branch of the if is an error condition and will be executed in the parent process if there was an error. The second branch (pid == 0) is executed in the child process, the child does a bit of signal housekeeping and does the exec. The third branch is in the parent when there was no error.
In the parent, pid will be non-zero but in the new child process, pid will be zero.
It gets executed in the child process, where pid will be 0.
http://linux.die.net/man/2/fork
Fork returns the pid of the child to the parent process and 0 to the child process. so when asking for pid == 0 means "is this the child process?". If so, it executes the program passed through command line arguments.
There's only one new process created; the child.
fork() in the child process returns 0, which is what you're checking for.
fork() in the parent process (your original process) returns the child process' pid.
By checking the return of fork() for 0 you know if you're the parent or child; you're the child if it's 0.

What exactly does fork return?

On success, the PID of the child
process is returned in the parent’s
thread of execution, and a 0 is
returned in the child’s thread of execution.
p = fork();
I'm confused at its manual page,is p equal to 0 or PID?
I'm not sure how the manual can be any clearer! fork() creates a new process, so you now have two identical processes. To distinguish between them, the return value of fork() differs. In the original process, you get the PID of the child process. In the child process, you get 0.
So a canonical use is as follows:
p = fork();
if (0 == p)
{
// We're the child process
}
else if (p > 0)
{
// We're the parent process
}
else
{
// We're the parent process, but child couldn't be created
}
p = fork();
/* assume no errors */
/* you now have two */
/* programs running */
--------------------
if (p > 0) { | if (p == 0) {
printf("parent\n"); | printf("child\n");
... | ...
Processes are structured in a directed tree where you only know your single-parent (getppid()). In short, fork() returns -1 on error like many other system functions, non-zero value is useful for initiator of the fork call (the parent) to know its new-child pid.
Nothing is as good as example:
/* fork/getpid test */
#include <sys/types.h>
#include <unistd.h> /* fork(), getpid() */
#include <stdio.h>
int main(int argc, char* argv[])
{
int pid;
printf("Entry point: my pid is %d, parent pid is %d\n",
getpid(), getppid());
pid = fork();
if (pid == 0) {
printf("Child: my pid is %d, parent pid is %d\n",
getpid(), getppid());
}
else if (pid > 0) {
printf("Parent: my pid is %d, parent pid is %d, my child pid is %d\n",
getpid(), getppid(), pid);
}
else {
printf("Parent: oops! can not create a child (my pid is %d)\n",
getpid());
}
return 0;
}
And the result (bash is pid 2249, in this case):
Entry point: my pid is 16051, parent pid is 2249
Parent: my pid is 16051, parent pid is 2249, my child pid is 16052
Child: my pid is 16052, parent pid is 16051
If you need to share some resources (files, parent pid, etc.) between parent and child, look at clone() (for GNU C library, and maybe others)
Once fork is executed, you have two processes. The call returns different values to each process.
If you do something like this
int f;
f = fork();
if (f == 0) {
printf("I am the child\n");
} else {
printf("I am the parent and the childs pid is %d\n",f);
}
You will see both the messages printed. They're being printed by two separate processes. This is they way you can differentiate between the two processes created.
This is the cool part. It's equal to BOTH.
Well, not really. But once fork returns, you now have two copies of your program running! Two processes. You can sort of think of them as alternate universes. In one, the return value is 0. In the other, it's the ID of the new process!
Usually you will have something like this:
p = fork();
if (p == 0){
printf("I am a child process!\n");
//Do child things
}
else {
printf("I am the parent process! Child is number %d\n", p);
//Do parenty things
}
In this case, both strings will get printed, but by different processes!
fork() is invoked in the parent process. Then a child process is spawned. By the time the child process spawns, fork() has finished its execution.
At this point, fork() is ready to return, but it returns a different value depending on whether it's in the parent or child. In the child process, it returns 0, and in the parent process/thread, it returns the child's process ID.
Fork creates a duplicate process and a new process context. When it returns a 0 value it means that a child process is running, but when it returns another value that means a parent process is running. We usually use wait statement so that a child process completes and parent process starts executing.
I think that it works like this:
when pid = fork(), the code should be executed two times, one is in current process, one is in child process.
So it explains why if/else both execute.
And the order is, first current process, and then execute the child.

Resources