#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include<sys/types.h> #include<sys/wait.h> int g_i4event; int process_wait(void) { /********Begin********/ /*********End*********/ } int process_waitpid(void) { /********Begin********/ /*********End*********/ }进程等待的原因 **进程控制块(PCB)**是进程在整个运行过程中非常重要的一个数据结构,里面包含以下几种信息: 进程描述信息; 进程控制信息; 资源信息; 现场保护信息。 进程终止或者退出的时候,进程会关闭所有文件描述符,释放用户空间分配的内存,但是PCB却会暂时保留。假如进程正常终止, PCB 里面就记录进程的退出状态;如果是异常终止,那么 PCB 里面存放着导致该进程终止的信号。 子进程的退出状态必须由父进程回收,也就是说,父进程必须得等待子进程退出后再自己退出,否则子进程会变成僵尸进程(没有任何可执行代码,不会被调度,只有一个进程描述符用来记录退出的状态,除此之外不再占用其他任何资源)。 wait函数 #include<sys/types.h> #include<sys/wait.h> pid_t wait(int* status); 参数: status ,整型指针,指向的地址即存放退出子进程的退出状态,不关心可以设为 NULL。 等待方式是阻塞式等待,一旦子进程退出,父进程就会立刻收到 SIGCHLD 信号。 注意:父进程调用 wait,是等待任意一个已经退出的子进程,只要是有子进程退出了,那么就获取子进程退出状态然后返回。 应用示例: #include <sys/wait.h> int main() { pid_t pid = fork(); ...... if(0 == id) { /*子进程代码区域*/ sleep (5); } else (id > 0) { /*父进程代码区域*/ int status = 0; wait(&status); } return 0; ...... } waitpid函数 #include<sys/types.h> #include<sys/wait.h> pid_t waitpid( pid_t pid, int *status ,int options); 参数详解: pid:希望等待退出的子进程的进程号; status:整型指针,指向的地址即存放退出子进程的推出状态,不关心可以设为 NULL; options:设置为 0,代表阻塞式等待,如果设置为 WNOHANG, waitpid 发现没有已经退出的子进程可以收集,就返回 0,此时是非阻塞式等待。 返回值: 返回 0 表示没有已经退出的子进程;返回正值,表示有已经退出的子进程。 编程要求 在主函数的最开始会初始化一个全部变量g_i4event为0。 本关的编程任务是补全右侧代码片段中两段Begin至End中间的代码,具体要求如下: 创建子进程,创建完后,将 g_i4event 置为 1; 子进程等待 3s ,然后子进程退出; 父进程等待一秒,将 g_i4event 置为 2;然后等待子进程退出,父进程获取子进程退出的状态后将 g_i4event 置为 3; process_wait采用 wait 函数,process_waitpid 采用 waitpid 函数。 测试说明 测试过程: 用户补全框架内的代码,实现功能性代码; 接着根据程序的输出判断程序是否正确。 不要在代码中使用printf等进行输出,以免引起结果判断错误。 以下是测试样例: 测试输入:1 预期输出: You and Sloth go to have lunch! You have finished your meal!You need wait the sloth Sloth have finished your meal! You and sloth will go home. 测试输入:2 预期输出: You and Sloth go to have lunch! You have finished your meal!You need wait the sloth Sloth have finished your meal! You and sloth will go home.
时间: 2025-06-13 20:14:32 浏览: 19
<think>我们首先需要创建一个父进程和至少一个子进程。在子进程中,我们将设置一个全局变量g_i4event的值,然后退出。父进程则使用wait或waitpid等待子进程结束,并获取子进程的退出状态。根据引用[1]和[4],我们知道当子进程退出时,它会进入僵死状态,直到父进程读取其退出状态。我们可以使用wait或waitpid来回收子进程并获取其状态。步骤:1.在父进程中,创建子进程(fork)。2.在子进程中,设置全局变量g_i4event(这里我们假设这个变量有特定用途,比如记录事件),然后退出。退出时可以使用exit(status),其中status是退出状态,父进程可以获取。3.在父进程中,使用wait或waitpid等待子进程结束,并获取子进程的退出状态。注意:wait函数会阻塞父进程直到任意一个子进程结束。waitpid可以指定等待特定的子进程,并且可以设置非阻塞选项。我们将编写一个示例程序,其中:-父进程创建子进程。-子进程设置全局变量(实际上,子进程会拥有父进程全局变量的副本,修改不会影响父进程,所以这里我们主要是为了演示在子进程中修改全局变量,然后退出)。-子进程退出时返回一个状态(例如,123)。-父进程使用waitpid等待该子进程,并获取其退出状态。另外,根据引用[4]中的代码,我们可以参考使用waitpid循环回收多个子进程,但这里我们只有一个子进程。代码实现如下:</think>### 使用 wait 和 waitpid 实现父子进程等待
在 Linux 进程控制中,`wait()` 和 `waitpid()` 是用于父进程回收子进程资源的关键系统调用。以下是完整的 C 语言实现示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
// 全局事件变量
int g_i4event = 0;
int main() {
pid_t pid = fork();
if (pid < 0) { // 创建子进程失败
perror("fork error");
exit(EXIT_FAILURE);
}
else if (pid == 0) { // 子进程代码块
g_i4event = 42; // 设置全局变量
printf("[Child] PID=%d, g_i4event=%d\n", getpid(), g_i4event);
sleep(2); // 模拟子进程工作
exit(123); // 子进程退出状态
}
else { // 父进程代码块
int status;
printf("[Parent] Waiting for child PID=%d...\n", pid);
// 等待特定子进程退出(阻塞式)
pid_t ret = waitpid(pid, &status, 0);
if (ret == -1) {
perror("waitpid error");
exit(EXIT_FAILURE);
}
// 解析子进程退出状态
if (WIFEXITED(status)) {
printf("[Parent] Child exited with status: %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("[Parent] Child killed by signal: %d\n", WTERMSIG(status));
}
// 全局变量不受子进程影响(独立地址空间)
printf("[Parent] g_i4event=%d (unchanged)\n", g_i4event);
}
return EXIT_SUCCESS;
}
```
#### 关键机制说明:
1. **进程创建**:`fork()` 创建子进程,返回 `0` 在子进程,返回子进程 PID 在父进程
2. **全局变量隔离**:子进程获得父进程变量的独立副本(修改互不影响)[^1]
3. **等待机制**:
- `waitpid(pid, &status, 0)` 阻塞等待特定子进程
- 使用 `WIFEXITED` 和 `WEXITSTATUS` 解析正常退出状态
4. **僵尸进程预防**:父进程必须调用 wait 函数回收终止的子进程,否则子进程将保持僵尸状态(EXIT_ZOMBIE)直到父进程结束[^1]
#### 执行流程:
```mermaid
graph TD
A[父进程 fork] --> B{创建结果}
B -->|pid=0| C[子进程执行]
B -->|pid>0| D[父进程执行]
C --> E[设置 g_i4event=42]
C --> F[exit 123]
D --> G[waitpid 阻塞等待]
F --> H[子进程终止]
H --> I[内核发送 SIGCHLD]
I --> G
G --> J[解析退出状态]
```
#### 输出示例:
```
[Parent] Waiting for child PID=12345...
[Child] PID=12345, g_i4event=42
[Parent] Child exited with status: 123
[Parent] g_i4event=0 (unchanged)
```
阅读全文
相关推荐

















