Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Developing a correct understanding of waitpid() and getpid()

Tags:

c

unix

pid

waitpid

I am learning about forks, execl and parent and child processes in my systems programming class. One thing that is confusing me is waitpid() and getpid(). Could someone confirm or correct my understanding of these two functions?

getpid() will return the process ID of whatever process calls it. If the parent calls it, it returns the pid of the parent. Likewise for the child. (It actually returns a value of type pid_t, according to the manpages).

waitpid() seems more complex. I know that if I use it in the parent process, without any flags to prevent it from blocking (using WNOHANG), it will halt the parent process until the child process terminates. I'm a little unsure as to how waitpid() manages all this, however. waitpid() also returns pid_t. What is the value of the pid_t waitpid() returns? How does this change depending on whether or not a parent or child calls it, and whether or not a child process is still running, or has terminated?

like image 535
Chris T Avatar asked Jan 29 '23 10:01

Chris T


2 Answers

Your understanding of getpid is correct, it returns the PID of the running process.

waitpid is used (as you said) to block the execution of a process (unless WNOHANG is passed) and resume execution when a (or more) child of the process ends. waitpid returns the pid of the child whose state has changed, -1 on failure. It also can return 0 if WNOHANG has specified but the child has not changed the state. See:

man waitpid

RETURN VALUE

waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned.

Depending on the arguments passed to waitpid, it will behave differently. Here I'l quote the man page again:

man waitpid

pid_t waitpid(pid_t pid, int *wstatus, int options);

...

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 modifiable via the options argument, as described below:

The value of pid can be:

  • < -1: meaning wait for any child process whose process group ID is equal to the absolute value of pid.
  • -1: meaning wait for any child process.
  • 0: meaning wait for any child process whose process group ID is equal to that of the calling process.
  • > 0: meaning 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 (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.
  • WCONTINUED (since Linux 2.6.10) also return if a stopped child has been resumed by delivery of SIGCONT.
  • I'm a little unsure as to how waitpid() manages all this

waitpid is a syscall and the OS handles this.

  • How does this change depending on whether or not a parent or child calls it, and whether or not a child process is still running, or has terminated?

wait should only be called by a process that has executed fork(). So the parent process should cal wait()/waitpid. If the child process hasn't called fork(), then it doesn't need to call either one of these functions. If however the child process has called fork(), then it also should call wait()/waitpid().

The behaviour of these function is very well explained in the man page, I quoted the important parts of it. You should read the whole man page to get a better understanding of it.

like image 196
Pablo Avatar answered Feb 03 '23 06:02

Pablo


waitpid "shall only return the status of a child process" (from the POSIX spec). So the pid_t waitpid returns belongs to one of the current or former children of the process calling waitpid. For example, if a child has recently terminated, it returns that child's PID.

waitpid is only useful when called from a parent process. If called from a process that does not have any children, it returns ECHILD.

waitpid can check the status of children that have terminated, or that has recently stopped or continued (e.g., ^Z from a shell). The various pid/option argument combinations in the spec tell you the various types of information you can return. For example, the WCONTINUED option requests status of recently-continued children instead of recently-terminated children.

like image 20
cxw Avatar answered Feb 03 '23 06:02

cxw