wait ()函数原型
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
wait()函数的参数是一个指向int类型的整数指针,用于存储子进程的退出状态信息。它返回子进程的进程ID(PID),如果出错则返回-1。
wait()函数的行为如下:
-
如果当前没有子进程或所有子进程都已经结束,则wait()函数将阻塞父进程,直到有一个子进程结束。
-
当有子进程结束时,wait()函数会返回结束的子进程的PID,并将子进程的退出状态存储在传入的status指针所指向的位置。通过解析status,可以获取子进程的退出状态和其他信息。
- 如果status指针为NULL,wait()函数将丢弃子进程的退出状态。
- 如果status不为NULL,可以使用一些宏来解析它,例如WIFEXITED、WEXITSTATUS、WIFSIGNALED和WTERMSIG。这些宏用于检查子进程的退出状态,以确定其是正常退出还是被信号终止。
-
如果在wait()函数调用时有多个子进程同时结束(例如,在父进程中启动了多个子进程),wait()函数将返回任意一个结束子进程的PID。
需要注意的是,wait()函数只能等待父进程的直接子进程,不能等待其他进程。
waitpid()函数原型
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
pid
:指定要等待的子进程ID。- 如果pid > 0,则表示等待特定PID的子进程结束。
- 如果pid = -1,则表示等待任意一个子进程结束,与wait()函数相同。
- 如果pid = 0,则表示等待与调用waitpid()函数的父进程在同一进程组中的任意子进程结束。
- 如果pid < -1,则表示等待指定进程组标识符为pid绝对值的任意子进程结束。
status
:指向int类型的指针,用于存储子进程的退出状态。options
:用于设置额外的选项。- 可以使用常量宏来指定选项,例如WNOHANG、WUNTRACED等。
- 如果不需要使用选项,可以将其设置为0。
返回值:
- 如果成功等待到一个子进程结束,则返回该子进程的PID。
- 如果出错,返回-1,并设置errno来指示错误的原因。
pid_t waitpid(pid_t pid, int *status, int options);option=0
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork(); // 创建一个子进程,在父进程中fork返回的的是子进程的pid号,在子进程fork返回的是0
if (pid == -1) { // 如果fork失败,返回-1
perror("fork"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序并返回失败状态
} else if (pid == 0) { // 如果是子进程
// 在子进程中执行某些操作
printf("This is the child process:%d\n",getpid()); // 打印子进程的消息
sleep(2); // 子进程睡眠2秒钟
exit(EXIT_SUCCESS); // 退出子进程并返回成功状态
} else {
// 在父进程中等待子进程结束
int status; // 保存子进程的退出状态
pid_t result; // 保存waitpid函数的返回值
do {
printf("This is the father process:%d\n",getpid()); // 打印进程的消息
result = waitpid(pid, &status, 0); // 等待子进程结束,并获取子进程的退出状态
if (result == -1) { // 如果waitpid失败,返回-1
perror("waitpid"); // 打印错误信息
exit(EXIT_FAILURE); // 退出程序并返回失败状态
}
if (WIFEXITED(status)) { // 如果子进程正常退出
printf("Child process exited with status: %d\n", WEXITSTATUS(status)); // 打印子进程的退出状态
} else if (WIFSIGNALED(status)) { // 如果子进程被信号终止
printf("Child process terminated by signal: %d\n", WTERMSIG(status)); // 打印终止子进程的信号编号
} else if (WIFSTOPPED(status)) { // 如果子进程被信号暂停
printf("Child process stopped by signal: %d\n", WSTOPSIG(status)); // 打印暂停子进程的信号编号
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); // 循环直到子进程正常退出或被信号终止
printf("Parent process finished\n"); // 打印父进程结束的消息
}
return 0; // 返回0表示程序执行成功
}
pid_t waitpid(pid_t pid, int *status, int options);option=WNOHANG非阻塞型
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程
printf("Child process\n");
sleep(5);
_exit(0);
} else if (pid > 0) {
// 父进程
int status;
pid_t childpid;
// 等待子进程结束,但不阻塞父进程
childpid = waitpid(pid, &status, WNOHANG);
if (childpid == 0) {
printf("No child process has finished yet.\n");
} else if (childpid > 0) {
if (WIFEXITED(status)) {
printf("Child process %d exited with status: %d\n", childpid, WEXITSTATUS(status));
}
} else {
perror("waitpid");
return 1;
}
} else {
// fork失败
perror("fork");
return 1;
}
return 0;
}
pid_t waitpid(pid_t pid, int *status, int options);option= WUNTRACED
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
void signal_handler(int signum) {
// 信号处理函数为空,什么都不做
}
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("Child process\n");
signal(SIGUSR1, signal_handler); // 注册信号处理函数,但无实际操作
pause(); // 暂停子进程,等待信号
} else if (pid > 0) {
int status;
pid_t childpid;
sleep(1); // 等待一段时间,确保子进程进入pause状态
kill(pid, SIGUSR1); // 发送SIGUSR1信号给子进程,唤醒它
childpid = waitpid(pid, &status, WUNTRACED);
if (childpid > 0) {
if (WIFEXITED(status)) {
printf("Child process %d exited with status: %d\n", childpid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("Child process %d terminated by signal: %d\n", childpid, WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("Child process %d stopped by signal: %d\n", childpid, WSTOPSIG(status));
}
} else {
perror("waitpid");
return 1;
}
} else {
perror("fork");
return 1;
}
return 0;
}
总结:
wait和waitpid是用于等待子进程状态改变的函数。
wait函数:
- 函数签名:pid_t wait(int *status)
- 功能:父进程调用wait函数等待任一子进程结束,并获取子进程的终止状态
- 参数:
- status:用于存储子进程的终止状态信息的指针
- 返回值:
- 成功时,返回结束的子进程的PID
- 失败时,返回-1
waitpid函数:
- 函数签名:pid_t waitpid(pid_t pid, int *status, int options)
- 功能:父进程调用waitpid函数等待指定的子进程结束,并获取子进程的终止状态
- 参数:
- pid:要等待的子进程的PID,有多种取值方式:
-
0:等待指定PID的子进程
- -1:等待任一子进程,与wait函数相同
- 0:等待与调用进程属于同一进程组的任一子进程
- <-1:等待组ID为pid的绝对值的任一子进程
-
- status:用于存储子进程的终止状态信息的指针
- options:一些选项标志,用于指定等待行为,例如WUNTRACED和WNOHANG
- pid:要等待的子进程的PID,有多种取值方式:
- 返回值:
- 成功时,返回结束的子进程的PID
- 失败时,返回-1
两者的区别:
- waitpid函数比wait函数更灵活,可以指定等待的子进程PID,以及一些选项标志。
- waitpid函数相对于wait函数,更适用于多进程并发控制的场景。
- waitpid函数的功能更强大,但使用也更复杂,需要显式地指定要等待的子进程和相关选项。
希望以上总结对你有帮助,如果还有其他问题,请随时提问。
20230814