如何用fork与pipe实现FCFS队列的入队与查询执行分离?
解决方案:基于Fork和Pipe实现FCFS任务队列
问题根源
原代码的核心错误是fork后父子进程的内存空间相互独立,父进程向队列中添加的任务,子进程完全看不到,导致处理进程永远无法执行任务。必须通过管道(Pipe)实现父子进程间的任务传递,管道本身就具备FCFS的特性,无需额外维护队列结构。
修正后的代码
SERVER.C
#include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #define BUFFER_SIZE 16 int main(int argc, char* argv[]) { // 创建管道,用于父子进程传递任务 int pipe_fd[2]; if (pipe(pipe_fd) == -1) { perror("pipe"); return 1; } // 创建FIFO,用于接收客户端请求 if (mkfifo("fifo", 0666) == -1) { perror("mkfifo"); close(pipe_fd[0]); close(pipe_fd[1]); return 1; } int pid = fork(); if (pid == -1) { perror("fork"); close(pipe_fd[0]); close(pipe_fd[1]); unlink("fifo"); return 1; } if (pid == 0) { // 子进程:处理任务(从管道读取并执行) close(pipe_fd[1]); // 关闭写端 char task[BUFFER_SIZE]; ssize_t bytes_read; while (1) { // 阻塞读取管道,有任务才处理 bytes_read = read(pipe_fd[0], task, BUFFER_SIZE); if (bytes_read > 0) { printf("执行任务:%s\n", task); // 这里可以替换为实际的任务执行逻辑 } else if (bytes_read == 0) { // 管道写端关闭,退出循环 break; } else { perror("read pipe"); break; } } close(pipe_fd[0]); _exit(0); } else { // 父进程:接收客户端请求,写入管道 close(pipe_fd[0]); // 关闭读端 int fd_fifo = open("fifo", O_RDONLY); if (fd_fifo == -1) { perror("open fifo"); close(pipe_fd[1]); kill(pid, SIGTERM); unlink("fifo"); return 1; } char buffer[BUFFER_SIZE]; ssize_t bytes_read; while (1) { // 阻塞读取FIFO的客户端请求 bytes_read = read(fd_fifo, buffer, BUFFER_SIZE); if (bytes_read > 0) { // 将请求写入管道,传递给子进程 write(pipe_fd[1], buffer, bytes_read); } else if (bytes_read == 0) { // FIFO写端关闭,继续等待新客户端连接 continue; } else { perror("read fifo"); break; } } close(fd_fifo); close(pipe_fd[1]); unlink("fifo"); wait(NULL); } return 0; }
CLIENT.C
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #define BUFFER_SIZE 16 int main(int argc, char* argv[]) { if (argc != 2 || strlen(argv[1]) >= BUFFER_SIZE - 1) { fprintf(stderr, "用法:%s <任务内容>(长度不超过15字符)\n", argv[0]); return 1; } int fd_fifo = open("fifo", O_WRONLY); if (fd_fifo == -1) { perror("连接服务器失败"); return 1; } ssize_t bytes_written = write(fd_fifo, argv[1], strlen(argv[1]) + 1); if (bytes_written == -1) { perror("发送任务失败"); close(fd_fifo); return 1; } printf("已发送任务:%s(写入字节数:%zd)\n", argv[1], bytes_written); close(fd_fifo); return 0; }
关键说明
- 管道的核心作用:父进程将从FIFO接收到的客户端任务写入管道,子进程从管道阻塞读取,天然实现FCFS顺序处理,无需额外维护队列结构。
- 阻塞特性优化:
read操作在管道/FIFO无数据时会自动阻塞,避免了原代码中空轮询的资源浪费。 - 资源清理:添加了管道、FIFO的关闭和删除操作,防止残留系统资源。
- 客户端优化:增加参数合法性检查,修复原代码中
strdup后重复strcpy的冗余操作。
内容的提问来源于stack exchange,提问作者Leonardo Alves
相关产品推荐
相关产品推荐

