如何用POSIX创建两个子进程分配任务,计算前20个数的平方?
POSIX多进程拆分任务实现:计算前20个自然数平方并合并排序
核心思路
- 用**管道(Pipe)**实现父子进程间的通信,每个子进程对应一个管道传递计算结果
- 父进程创建两个子进程:Son_1处理1-20的奇数平方,Son_2处理1-20的偶数平方
- 子进程完成计算后将结果写入管道并退出;父进程等待两个子进程终止后,读取所有结果并排序输出
完整代码实现
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #define MAX_NUM 20 // 冒泡排序:适合初学者理解的简单排序实现 void sort(int arr[], int size) { for (int i = 0; i < size - 1; i++) { for (int j = 0; j < size - i - 1; j++) { if (arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } int main() { int pipe_odd[2], pipe_even[2]; pid_t pid_son1, pid_son2; int results[MAX_NUM]; int count = 0; // 创建两个管道:分别用于奇数、偶数结果的传递 if (pipe(pipe_odd) == -1 || pipe(pipe_even) == -1) { perror("管道创建失败"); exit(EXIT_FAILURE); } // 创建Son_1:处理奇数 pid_son1 = fork(); if (pid_son1 == -1) { perror("创建Son_1失败"); exit(EXIT_FAILURE); } else if (pid_son1 == 0) { // 子进程关闭无关管道端,只保留奇数管道的写端 close(pipe_odd[0]); close(pipe_even[0]); close(pipe_even[1]); // 计算奇数平方并写入管道 for (int i = 1; i <= MAX_NUM; i += 2) { int square = i * i; write(pipe_odd[1], &square, sizeof(square)); } close(pipe_odd[1]); exit(EXIT_SUCCESS); } // 创建Son_2:处理偶数 pid_son2 = fork(); if (pid_son2 == -1) { perror("创建Son_2失败"); exit(EXIT_FAILURE); } else if (pid_son2 == 0) { // 子进程关闭无关管道端,只保留偶数管道的写端 close(pipe_odd[0]); close(pipe_odd[1]); close(pipe_even[0]); // 计算偶数平方并写入管道 for (int i = 2; i <= MAX_NUM; i += 2) { int square = i * i; write(pipe_even[1], &square, sizeof(square)); } close(pipe_even[1]); exit(EXIT_SUCCESS); } // 父进程操作:关闭管道写端,只保留读端 close(pipe_odd[1]); close(pipe_even[1]); // 等待两个子进程完全终止 wait(NULL); wait(NULL); // 读取奇数平方结果 int num; while (read(pipe_odd[0], &num, sizeof(num)) > 0) { results[count++] = num; } // 读取偶数平方结果 while (read(pipe_even[0], &num, sizeof(num)) > 0) { results[count++] = num; } // 关闭管道读端 close(pipe_odd[0]); close(pipe_even[0]); // 排序结果 sort(results, count); // 输出最终结果 printf("排序后的前20个自然数平方:\n"); for (int i = 0; i < count; i++) { printf("%d ", results[i]); } printf("\n"); return EXIT_SUCCESS; }
关键细节解释
- 管道机制:
pipe()创建的管道是半双工的,每个管道有读端(索引0)和写端(索引1),父子进程通过管道直接传递整数数据,无需格式化字符串 - 进程创建:
fork()复制当前进程,返回0代表子进程,返回正整数是子进程PID(父进程持有),返回-1则创建失败 - 管道端管理:必须关闭无关的管道端,否则会导致
read()函数一直阻塞,等待不存在的写端数据 - 等待子进程:
wait(NULL)会阻塞父进程,直到一个子进程结束,调用两次确保两个子进程都完成计算 - 排序替换:如果想使用更高效的排序,可以替换为标准库的
qsort()函数,只需添加比较函数:
然后调用int compare(const void *a, const void *b) { return (*(int*)a - *(int*)b); }qsort(results, count, sizeof(int), compare);即可
编译与运行
编译命令:
gcc -o square_process square_process.c
运行后输出:
排序后的前20个自然数平方: 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400
内容的提问来源于stack exchange,提问作者Mario Serna León
相关产品推荐
相关产品推荐

