C语言实现生产者消费者问题时如何优雅退出consumer避免core dumped
问题根因
你遇到的Quit (core dumped)、killed语句不输出的问题,是代码里存在几个严重的逻辑错误导致的:
- 共享内存申请大小错误:
mmap时传入的是sizeof(shared),shared是指针类型,64位系统下仅占8字节,远小于struct requiredmemory的实际大小,后续访问共享内存时会出现越界,直接触发段错误。 - 消费者PID存储错误:fork消费者的循环里,父进程错误把消费者PID存入了
producers数组,consumers数组全程是垃圾值。后续父进程杀消费者时,实际是向随机PID发信号,大概率会杀到无效进程甚至父进程自身,导致父进程异常退出,自然不会打印killed相关日志。 - 跳转标签错误:fork消费者出错时错误跳转到了生产者错误处理的标签,逻辑混乱。
- 信号处理的安全问题:
SIGQUIT默认行为是生成核心转储,且signal函数在不同系统下的行为不稳定,同时sem_wait被信号打断时没有做错误处理。
修复方案
1. 修复共享内存申请
把mmap的大小改为结构体的实际大小:
struct requiredmemory *shared = mmap(NULL, sizeof(struct requiredmemory), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2. 修复消费者PID存储逻辑
修改fork消费者的循环,将PID正确存入consumers数组,同时修正跳转标签:
for (c = 0; c < C; c++) { pid_t pid = fork(); if (pid < 0) goto error_forking_c; // 修正跳转标签 else if (pid) { consumers[c] = pid; // 正确存入消费者数组 } else { id = c; goto consumer; } }
3. 优化消费者退出逻辑(更干净的实现,无需发信号)
不用信号杀消费者的方式,改为共享标志位主动退出,彻底避免信号带来的异常:
- 在
struct requiredmemory里新增退出标志:struct requiredmemory { sem_t f, e, m; int total, start, count; int producer_exit; // 新增:所有生产者是否已退出 unsigned char circular_buffer[50]; }; - 父进程等待所有生产者退出后,设置标志位,并唤醒所有阻塞的消费者:
while (p--) wait(NULL); shared->producer_exit = 1; // 标记生产者全部退出 for(int i=0; i<C; i++) sem_post(full); // 唤醒所有阻塞在sem_wait(full)的消费者 // 等待所有消费者主动退出 for(int i=0; i<C; i++) waitpid(consumers[i], NULL, 0); - 消费者循环里增加退出判断,删除原有信号处理相关代码:
consumer: { count = 0; while (1) { unsigned char num = 0; sem_wait(full); sem_wait(mutex); // 生产者已退出且缓冲区为空,直接退出 if(shared->producer_exit && shared->count == 0) { sem_post(mutex); sem_post(empty); break; } num = shared->circular_buffer[shared->start]; shared->start = (shared->start + 1) % BUFFER_LEN; shared->count -= 1; shared->total += num; sem_post(mutex); sem_post(empty); count++; localtotal += num; } printf("Consumer %d : consumed %d items totalling to %d\n", id, count, localtotal); fflush(stdout); return 0; }
额外优化点
- 生产者随机数种子修改为
srand(time(NULL) ^ getpid()),避免多个生产者同时启动时种子相同,生成重复的随机数。 - 所有
printf后加fflush(stdout),避免多进程下输出缓冲区混乱。
内容的提问来源于stack exchange,提问作者Mahek Shamsukha
相关产品推荐
相关产品推荐

