You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现无sleep()的前后台进程同步IPC,完成数组输入与排序交互

进程同步问题解决方案

需求描述

存在前台和后台两个进程,共享一个整数数组:

  • 前台进程从终端接收整数,逐个追加到共享数组
  • 后台进程在每次添加元素后,将共享数组保持升序排序
  • 所有元素添加并排序完成后,前台进程显示最终的共享数组

现有实现问题

当前代码依赖sleep()实现进程间同步:

  • 主进程创建前台进程后sleep 1秒,确保前台先执行
  • 前台、后台进程每次循环后各sleep 1秒,保证交替执行
    移除sleep()后会出现:后台进程饥饿、后台先于前台执行、数据竞争等问题,且现有代码中sem_init(&D->mutex, 7, 1)的pshared参数错误(进程间共享需设为1,而非7),且信号量初始化放在前台进程可能导致重复初始化问题。

修正方案

1. 修复信号量初始化问题

进程间共享的信号量,sem_init的第二个参数pshared必须设为1,且初始化操作要放在主进程中,避免子进程重复初始化。

2. 使用双信号量实现严格交替同步

新增两个信号量替代单一互斥锁:

  • sem_fg:控制前台进程写入权限,初始值为1(允许前台先执行)
  • sem_bg:控制后台进程排序权限,初始值为0(后台初始需等待前台写入)
    前台写入一个元素后,唤醒后台进程并等待自己的下一次写入权限;后台完成排序后,唤醒前台进程并等待下一次排序权限,彻底摆脱对sleep()的依赖。

修改后的完整代码

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <semaphore.h>

#define MAX_BUFFER_SIZE 64
#define BUFFER_NAME "/shared"

struct data {
    int buffer[MAX_BUFFER_SIZE];
    sem_t sem_fg;  // 前台进程写入信号量
    sem_t sem_bg;  // 后台进程排序信号量
};

int foreground_process(int size)
{
    int element;

    int buff_fd = shm_open(BUFFER_NAME, O_RDWR, 0666);
    struct data *D = mmap(NULL, sizeof(struct data), PROT_READ | PROT_WRITE, MAP_SHARED, buff_fd, 0);

    for (int i = 0; i < size; ++i) {
        sem_wait(&D->sem_fg);  // 等待写入权限
        printf("Enter element %d: ", i);
        scanf("%d", &element);
        
        D->buffer[i] = element;
        sem_post(&D->sem_bg);  // 唤醒后台进程排序
    }

    // 等待最后一次排序完成
    sem_wait(&D->sem_fg);
    printf("Final array: ");
    for (int i = 0; i < size; ++i)
        printf("%d ", D->buffer[i]);
    printf("\n");
    sem_post(&D->sem_bg);  // 释放后台信号量,让后台进程正常退出

    munmap(D, sizeof(struct data));
    close(buff_fd);

    exit(0);
}

int background_process(int size)
{
    int prev_element, tmp;

    int buff_fd = shm_open(BUFFER_NAME, O_RDWR, 0666);
    struct data *D = mmap(NULL, sizeof(struct data), PROT_READ | PROT_WRITE, MAP_SHARED, buff_fd, 0);

    for (int i = 0; i < size; ++i) {
        sem_wait(&D->sem_bg);  // 等待前台写入完成
        
        prev_element = D->buffer[i];
        printf("Got element %d at B[%d]!\n", D->buffer[i], i);

        // 插入排序逻辑
        for (int j = 0; j < i; ++j) {
            if (D->buffer[j] > prev_element) {
                tmp = D->buffer[j];
                D->buffer[j] = prev_element;
                prev_element = tmp;
            }
        }
        D->buffer[i] = prev_element;

        sem_post(&D->sem_fg);  // 唤醒前台进程写入下一个元素
    }

    munmap(D, sizeof(struct data));
    close(buff_fd);

    exit(0);
}

int main(void) {
    int size;
    pid_t fg_pid, bg_pid;

    pid_t wpid;
    int status;

    printf("Size: ");
    scanf("%d", &size);

    // 创建并初始化共享内存
    int buff_fd = shm_open(BUFFER_NAME, O_CREAT | O_RDWR, 0666);
    ftruncate(buff_fd, sizeof(struct data));
    struct data *D = mmap(NULL, sizeof(struct data), PROT_READ | PROT_WRITE, MAP_SHARED, buff_fd, 0);

    // 初始化信号量:pshared=1表示进程间共享
    sem_init(&D->sem_fg, 1, 1);
    sem_init(&D->sem_bg, 1, 0);

    munmap(D, sizeof(struct data));
    close(buff_fd);

    // 创建前台进程
    if ((fg_pid = fork()) == 0) foreground_process(size);
    else if (fg_pid < 0) perror("foreground process");

    // 创建后台进程(无需sleep)
    if ((bg_pid = fork()) == 0) background_process(size);
    else if (bg_pid < 0) perror("background process");

    // 等待所有子进程退出
    while ((wpid = wait(&status)) != -1)
        fprintf(stderr, "Process %d exits with status %d\n", wpid, WEXITSTATUS(status));

    // 清理共享内存和信号量
    buff_fd = shm_open(BUFFER_NAME, O_RDWR, 0666);
    D = mmap(NULL, sizeof(struct data), PROT_READ | PROT_WRITE, MAP_SHARED, buff_fd, 0);
    sem_destroy(&D->sem_fg);
    sem_destroy(&D->sem_bg);
    munmap(D, sizeof(struct data));
    close(buff_fd);
    shm_unlink(BUFFER_NAME);

    return 0;
}

方案说明

  • 双信号量sem_fg和sem_bg实现了前台写入与后台排序的严格交替,完全不需要sleep()
  • 主进程统一初始化共享内存和信号量,避免子进程重复初始化问题
  • 信号量的pshared参数设为1,确保进程间共享有效
  • 新增munmap调用,规范释放映射的内存区域

内容的提问来源于stack exchange,提问作者3rdgrade-dropout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 14:57:32