目次
- 1 1. Introduction
- 2 2. What is the wait Function in C?
- 3 3. wait Basic Usage of the Function
- 4 4. Zombie Processes and wait Function Relationship
- 5 5. Differences with the waitpid Function
- 6 6. Synchronization in Multithreaded Environments
- 6.1 Differences Between Process Synchronization and Thread Synchronization
- 6.2 Synchronization Processing in Multithreaded Environments
- 6.3 Basics of Synchronization Using Condition Variables
- 6.4 Example of Synchronization Using Condition Variables
- 6.5 Explanation of the Sample Code
- 6.6 Notes on Thread Synchronization
- 6.7 Notes on Using the wait Function in Multithreaded Environments
- 7 7. Troubleshooting and Best Practices
- 8 8. Frequently Asked Questions (FAQ)
- 8.1 Q1: How to prevent zombie processes without using the wait function?
- 8.2 Q2: In what situations should you use waitpid?
- 8.3 Q3: What are the causes when the wait function does not return a value?
- 8.4 Q4: How to safely use the wait function in a multithreaded program?
- 8.5 Q5: Are there alternatives to the wait function?
- 8.6 Q6: What should you do if a child process does not terminate?
- 8.7 Q7: What is the meaning of the exit status obtained by the wait function?
- 8.8 Q8: How to manage multiple child processes simultaneously?
- 9 9. Summary
1. Introduction
The C language is widely used in the development of system programs and embedded systems, and process management is one of the important topics among them. This article explains the “wait function” in the C language. The wait function is a system call used to achieve synchronization between processes, and it is particularly useful for waiting for the termination of child processes. Through this article, you can learn widely from the basic usage of the wait function to advanced methods, and related topics (e.g., the waitpid function and measures against zombie processes).2. What is the wait Function in C?
Overview of the wait Function
wait function is one of the system calls used in UNIX-like systems, employed by the parent process to wait for the termination of the child process. This allows the parent process to receive the child process’s termination status.Basic Operation
wait function is used as follows.#include
#include
#include
int main() {
pid_t pid = fork();
if (pid > 0) {
// Parent process
wait(NULL); // Wait until the child process terminates
} else if (pid == 0) {
// Child process
printf("Hello from child process!\n");
}
return 0;
}In the above code, the child process is created using the fork function, and the parent process waits for the child process to terminate using the wait function.Return Value and Arguments
- Return ValueIf the child process terminates, it returns its process ID. If an error occurs, it returns
-1. - ArgumentsBy passing
int* statusas an argument, it is possible to receive the child process’s termination status.
3. wait Basic Usage of the Function
Simple Code Example
wait The following shows the basic usage of the function.#include
#include
#include
#include
int main() {
pid_t pid = fork();
if (pid > 0) {
int status;
wait(&status); // Obtain the child process's exit status
if (WIFEXITED(status)) {
printf("Child exited with status: %d\n", WEXITSTATUS(status));
}
} else if (pid == 0) {
printf("Child process running...\n");
_exit(0); // Child process termination
}
return 0;
}Explanation of the Sample Code
wait(&status)waits for the child process to terminate.WIFEXITED(status)is used to check if the child process exited normally.WEXITSTATUS(status)obtains the child process’s exit code.
wait function, the parent process can accurately grasp the child process’s termination status.4. Zombie Processes and wait Function Relationship
What Are Zombie Processes?
A zombie process is a process that occurs when a child process has terminated but the parent process has not properly collected its termination status. In this state, although the child process itself has ended, the process information remains in the system. If there are many zombie processes in the system, it can overload the process table and prevent other processes from operating normally.Example of Zombie Process Occurrence
The following is a simple example where a zombie process occurs.#include
#include
#include
int main() {
pid_t pid = fork();
if (pid > 0) {
// Parent process does nothing and waits
sleep(10);
} else if (pid == 0) {
// Child process
printf("Child process exiting...\n");
_exit(0);
}
return 0;
}In this example, since the parent process does not collect the child process’s termination status, the child process becomes a zombie after termination.Preventing Zombie Processes with the wait Function
By using the wait function, the parent process can properly collect the child process’s termination status and prevent zombie processes. The following is an example of the corrected version.#include
#include
#include
#include
int main() {
pid_t pid = fork();
if (pid > 0) {
// Parent process
wait(NULL); // Wait for child process termination to prevent zombie processes
printf("Parent process: Child process has been reaped.\n");
} else if (pid == 0) {
// Child process
printf("Child process exiting...\n");
_exit(0);
}
return 0;
}In this program, by using wait(NULL), the parent process waits for the child process to terminate, preventing the occurrence of zombie processes.Key Points for Handling Zombie Processes
- Always use
waitorwaitpidBy properly collecting the child process’s termination status, zombie processes are prevented. - Method Using Signal Handlers
SIGCHLDCapture the signal and automatically collect when the child process terminates.
#include
#include
#include
#include
#include
void sigchld_handler(int signo) {
while (waitpid(-1, NULL, WNOHANG) > 0); // Collect all terminated child processes
}
int main() {
signal(SIGCHLD, sigchld_handler); // Set SIGCHLD to handler
pid_t pid = fork();
if (pid == 0) {
// Child process
printf("Child process exiting...\n");
_exit(0);
} else if (pid > 0) {
// Parent process
printf("Parent process doing other work...\n");
sleep(10); // SIGCHLD handler activates during other work
}
return 0;
}With this method, terminated child processes are automatically collected without the parent process explicitly calling wait.5. Differences with the waitpid Function
What is the waitpid Function?
waitpid function is a system call for waiting for the termination of a child process, similar to the wait function, but it allows for more flexible process management. By using waitpid, you can specify a particular child process or wait in non-blocking mode.Basic Usage and Syntax
The syntax of thewaitpid function is as follows.#include
#include
#include
pid_t waitpid(pid_t pid, int *status, int options);pidSpecifies the ID of the child process to wait for. You can control the behavior using the following special values.pid > 0: Wait for a specific process ID.pid == 0: Wait for any child process in the same process group as the parent process.pid < -1: Wait for all processes in the specified process group.pid == -1: Wait for any child process (same as thewaitfunction).statusPointer to store the child process’s exit status.optionsSpecifies options to modify the behavior. The main values are as follows.WNOHANG: Non-blocking mode. Returns immediately if no child process has terminated.WUNTRACED: Include stopped child processes in the targets.- Return Value
- On normal termination: The PID of the terminated child process.
- If no child processes:
0(whenWNOHANGis specified). - On error:
-1.
Example of the waitpid Function
The following is an example of using the waitpid function to wait for a specific child process.#include
#include
#include
#include
int main() {
pid_t pid1 = fork();
if (pid1 == 0) {
// Child process 1
printf("Child 1 running...\n");
sleep(2);
_exit(1);
}
pid_t pid2 = fork();
if (pid2 == 0) {
// Child process 2
printf("Child 2 running...\n");
sleep(4);
_exit(2);
}
int status;
// Wait for the specific child process pid1
pid_t ret = waitpid(pid1, &status, 0);
if (ret > 0 && WIFEXITED(status)) {
printf("Child 1 exited with status: %d\n", WEXITSTATUS(status));
}
// Wait for the remaining child process
waitpid(pid2, &status, 0);
printf("Child 2 exited with status: %d\n", WEXITSTATUS(status));
return 0;
}Main Differences between wait and waitpid
| Item | wait Function | waitpid Function |
|---|---|---|
| Wait Target | Any child process | Can specify a specific child process |
| Blocking | Always blocking | Non-blocking possible |
| Option Specification | Not possible | WNOHANG, WUNTRACED, etc. |
| Flexibility | Limited | High |
When to Choose waitpid
- When you want to manage a specific child processIt is suitable for programs that generate multiple child processes and want to control each one individually.
- When you want to perform asynchronous processingIf you want to check the process termination status without blocking other processing, the
WNOHANGoption is convenient.
Selection Guide for wait and waitpid
- For simple programs, the
waitfunction is sufficient. If you just need to wait for any child process, flexibility is not required. - For complex process management, the
waitpidfunction is recommended. Especially when asynchronous processing or controlling specific processes is needed,waitpidallows for efficient management.
6. Synchronization in Multithreaded Environments
Differences Between Process Synchronization and Thread Synchronization
In C, processes and threads operate as different management units. Process synchronization (e.g.,wait or waitpid functions) controls termination status and resource sharing between multiple processes. On the other hand, thread synchronization manages resources and sequence control between threads within the same process.Synchronization Processing in Multithreaded Environments
Commonly used for synchronization between threads are condition variables and mutexes. Here, we explain the synchronization method using condition variables from thepthread library.Basics of Synchronization Using Condition Variables
By using condition variables (pthread_cond_t), waiting and notification between threads can be performed efficiently.Basic Functions of Condition Variables
pthread_cond_waitWaits until the condition is satisfied. Releases the mutex during waiting.pthread_cond_signalWakes up one waiting thread.pthread_cond_broadcastWakes up all waiting threads.
Example of Synchronization Using Condition Variables
The following is a simple example of synchronizing multiple threads using condition variables.#include
#include
#include
// Mutex and condition variable initialization
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int shared_data = 0;
void* producer(void* arg) {
pthread_mutex_lock(&mutex);
printf("Producer: producing data...\n");
shared_data = 1;
// Notify with condition variable
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return NULL;
}
void* consumer(void* arg) {
pthread_mutex_lock(&mutex);
// Wait until condition is satisfied
while (shared_data == 0) {
printf("Consumer: waiting for data...\n");
pthread_cond_wait(&cond, &mutex);
}
printf("Consumer: consumed data!\n");
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t producer_thread, consumer_thread;
// Create threads
pthread_create(&consumer_thread, NULL, consumer, NULL);
sleep(1); // Sleep to let consumer wait first
pthread_create(&producer_thread, NULL, producer, NULL);
// Wait for thread termination
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
return 0;
}Explanation of the Sample Code
- Use of MutexesUses
pthread_mutex_lockandpthread_mutex_unlockto control exclusive access to shared resources. - Waiting and Notification with Condition Variables
- The consumer thread waits for
shared_datato be updated usingpthread_cond_wait. - The producer thread notifies the consumer thread using
pthread_cond_signal.
- Coordinated Operation Between ThreadsRealizes a simple flow where the producer generates data and the consumer receives it.
Notes on Thread Synchronization
- Preventing DeadlocksIt is necessary to pay attention to the order of locking and unlocking mutexes.
- Avoiding Race ConditionsWhen threads try to change conditions simultaneously, it is necessary to properly combine condition variables and mutexes.
- Considering ScalabilityTo synchronize efficiently between multiple threads, it is important to minimize unnecessary waiting and locking.
Notes on Using the wait Function in Multithreaded Environments
wait function is for synchronization between processes and is not suitable for thread-level synchronization. For thread synchronization, using condition variables and mutexes is safer and more efficient.
7. Troubleshooting and Best Practices
Common Errors and Solutions
When usingwait and waitpid in C language, several typical errors may occur. We explain their causes and solutions.1. wait function returns an error
Cause- The child process does not exist.
- The system call was interrupted (
EINTRerror).
- Check whether the child process exists.
- If the system call is interrupted, retry in a loop.
int status;
while (wait(&status) == -1) {
if (errno != EINTR) {
perror("wait failed");
break;
}
}2. Zombie processes occur
Cause- The parent process does not reap the child process’s termination.
- In the parent process, use
waitorwaitpidappropriately. - Set a signal handler to automatically reap terminations.
3. Unstable behavior due to race conditions
Cause- When multiple parent processes attempt to wait for the same child process.
- The child process’s termination status is not correctly reaped.
- If you need to specify the process ID explicitly, use
waitpid. - Design the system so that multiple parent processes do not manage the same child process.
Best Practices
1. Proper selection of wait and waitpid
- For simple programs,
waitis sufficient. - When complex process management (control of specific child processes or asynchronous processing) is required, use
waitpid.
2. Using a signal handler
Using a signal handler allows the parent process to automatically collect the child process’s termination status without explicitly callingwait. This prevents zombie processes while keeping the parent process’s code concise.3. Thorough error handling
Sincewait and waitpid are system calls, errors may occur. Check the return value of every call and handle it appropriately.pid_t pid = wait(NULL);
if (pid == -1) {
perror("wait error");
}4. Implementing asynchronous processing
For asynchronous processing, the following design is recommended.- Do not block the main processing; periodically call
waitpidwithWNOHANG. - Poll the child process’s termination status and reap it as needed.
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("Child process %d terminated.\n", pid);
}5. Managing the number of processes
In programs that generate many child processes, you need to control the number of processes.- Limit the number of child processes created simultaneously.
- Adopt a design that does not create new processes until existing child processes have terminated.
8. Frequently Asked Questions (FAQ)
Q1: How to prevent zombie processes without using the wait function?
A:You can prevent zombie processes by using signal handlers without using the wait function. The parent process can automatically reap the child process’s exit status by catching the SIGCHLD signal. The following is an example using a signal handler.#include
#include
#include
#include
#include
void handle_sigchld(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
int main() {
signal(SIGCHLD, handle_sigchld);
if (fork() == 0) {
// Child process
_exit(0);
}
// Parent process processing
sleep(5);
printf("Parent process completed.\n");
return 0;
}Q2: In what situations should you use waitpid?
A:waitpid is suitable for the following cases.- When you want to wait for a specific child process only (specify
pid). - When you want to manage processes asynchronously (use the
WNOHANGoption). - When you want to check for stopped child processes (use the
WUNTRACEDoption).
Q3: What are the causes when the wait function does not return a value?
A:Possible causes for the wait function not returning a value (returning -1) include the following.- No child process exists.
- The process has already exited, or
forkmay have failed.
- The system call was interrupted (
EINTRerror).
- If interrupted by a signal, retry in a loop.
int status;
pid_t pid;
while ((pid = wait(&status)) == -1) {
if (errno != EINTR) {
perror("wait error");
break;
}
}Q4: How to safely use the wait function in a multithreaded program?
A:When using wait in a multithreaded program, pay attention to the following points.waitoperates at the process level, so use condition variables or mutexes for thread-level synchronization.- It is usually safer to limit child process management to the main thread. If other threads call
wait, it may cause unexpected behavior.
Q5: Are there alternatives to the wait function?
A:The following alternatives are available.waitpidfunctionIt offers high flexibility and can control specific processes.- Signal handlerIt handles child process termination asynchronously.
- Event-driven programmingYou can also manage process termination using an event loop (e.g.,
selectorpoll).
Q6: What should you do if a child process does not terminate?
A:The child process may be stopped. In this case, handle it with the following steps.WUNTRACEDoption to check for stopped child processes.- If necessary, terminate the child process using the
killsystem call.
Q7: What is the meaning of the exit status obtained by the wait function?
A:The wait function obtains the status, which includes the following information.- Normal termination:
WIFEXITED(status)returns true, and the exit code can be obtained withWEXITSTATUS(status). - Abnormal termination: If terminated by a signal,
WIFSIGNALED(status)returns true, and the terminating signal can be obtained withWTERMSIG(status).
int status;
wait(&status);
if (WIFEXITED(status)) {
printf("Exited with code: %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("Killed by signal: %d\n", WTERMSIG(status));
}Q8: How to manage multiple child processes simultaneously?
A:When managing multiple child processes, it is common to usewaitpid in a loop to reap all processes.pid_t pid;
int status;
while ((pid = waitpid(-1, &status, 0)) > 0) {
printf("Child process %d exited.\n", pid);
}9. Summary
In this article, we comprehensively covered the C languagewait function, from basic usage to advanced examples, and related topics (waitpid function and zombie process mitigation). Below we summarize the key points.wait Function Basics
waitfunction is a system call that allows a parent process to wait for a child process to terminate and to collect its termination status.wait(NULL)can be used to wait for a child process easily without checking the exit status.
Applications and Related Topics
- Zombie Process MitigationIf the termination status of a child process is not collected, a zombie process will occur. Using
waitorwaitpidappropriately can prevent this. waitpidfunctionis very useful when you want to wait for a specific child process or perform asynchronous processing.- Signal HandlerUsing the
SIGCHLDsignal allows the parent process to automatically collect termination status without explicitly callingwait.
Cautions in Multithreaded Environments
waitfunction performs interprocess synchronization, but for thread-level synchronization, using condition variables or mutexes is appropriate.- It is important to design so that multiple threads do not call
waitsimultaneously.
Troubleshooting and Best Practices
waitandwaitpidreturn values should always be checked, and error handling should be performed appropriately.- When asynchronous processing is required, using the
WNOHANGoption enables efficient process management. - Aim for simple design, avoiding unnecessary process creation and complex dependencies.
What to Learn Next
wait function and process synchronization basics understood, the next step is to learn the following topics:- Interprocess Communication (IPC)Methods for exchanging data using pipes, message queues, and shared memory.
- Asynchronous ProgrammingHow to use event-driven programming and asynchronous I/O.
forkfunction and details of process creationMemory management and process branching behavior when creating child processes.
wait function and its related knowledge. Achieving proper process management will help you develop efficient and stable programs.

