在上面代码的基础上, 队列成员finished初始值为0,当父进程将全部200个整数全部放入队列后,将finished置为1,并等待10个子进程结束。 子进程依次不断地从队列中取出一个整数,并判断这个整数是不是素数,如果是素数,则输出这个进程的进程号以及这个整数。当然,每次从队列中取数之前,首先需要判断finished是否为1并且队列是否为空,如果是,则子进程结束。
时间: 2024-03-14 12:45:56 浏览: 57
根据你的要求,以下是修改后的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAXSIZE 20
struct queue_st {
int finished; // 父进程是否已将所有200个整数放入了队列
int head; // 队列头
int tail; // 队列尾
int nums[MAXSIZE]; // 队列中的整数
};
// 判断是否是素数
int is_prime(int n) {
if (n < 2) {
return 0;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
// 子进程的处理函数
void child_process(int id, int fd, struct queue_st *queue) {
int n;
while (1) {
// 队列为空且父进程已经将所有整数放入队列
if (queue->head == queue->tail && queue->finished == 1) {
break;
}
// 队列为空但父进程还未将所有整数放入队列
if (queue->head == queue->tail) {
sleep(1);
continue;
}
// 从队列中取出一个整数
n = queue->nums[queue->head];
queue->head = (queue->head + 1) % MAXSIZE;
// 判断是否是素数
if (is_prime(n)) {
printf("Child %d: %d\n", id, n);
}
}
// 关闭管道并退出子进程
close(fd);
exit(0);
}
int main() {
int fd[2];
pipe(fd);
// 创建子进程池
for (int i = 0; i < 10; i++) {
pid_t pid = fork();
if (pid == 0) {
close(fd[1]);
struct queue_st queue = { 0, 0, 0 };
child_process(i, fd[0], &queue);
}
}
// 创建队列
struct queue_st queue = { 0, 0, 0 };
// 将200个整数放入队列
for (int i = 30000000; i <= 30000200; i++) {
while (queue.finished == 1) {
sleep(1);
}
queue.nums[queue.tail] = i;
queue.tail = (queue.tail + 1) % MAXSIZE;
if (queue.tail == queue.head) {
queue.head = (queue.head + 1) % MAXSIZE;
}
if (queue.tail == 0) {
queue.finished = 1;
}
}
// 关闭管道并等待子进程结束
close(fd[0]);
close(fd[1]);
for (int i = 0; i < 10; i++) {
wait(NULL);
}
return 0;
}
```
在修改后的代码中,我们首先在子进程的处理函数中增加了判断队列是否为空和父进程是否已经将所有整数放入队列的逻辑。如果队列为空且父进程已经将所有整数放入队列,则子进程退出。如果队列为空但父进程还未将所有整数放入队列,则子进程等待一秒后重新检查队列状态。
在主函数中,我们创建了一个结构体 `queue` 表示队列,并增加了对队列成员 `finished` 的修改逻辑。在将200个整数放入队列后,我们将 `finished` 置为1,表示父进程已经将所有整数放入队列了。
最后,我们需要注意在子进程退出时,需要关闭管道并调用 `exit()` 函数。在主函数中,我们需要等待10个子进程结束后再退出。
阅读全文