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

如何实现两个C主从程序共用的全局POSIX信号量跨进程同步

跨进程POSIX信号量同步实现方案

你当前代码使用的是进程内线程共享的无名信号量,sem_init第二个参数设为0的情况下,信号量只能在同一个进程的线程间可见,a.c和b.c是两个独立运行的进程,无法互相访问对方的信号量实例,同时writercount、readercount也是进程本地变量,两个进程各持有独立副本,判断逻辑完全失效。
要实现跨进程同步,需要改用有名POSIX信号量,同时把共享状态变量(readercount、writercount)放到共享内存中,修改方案如下:


1. a.c(主程序)修改后代码

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
// 新增跨进程通信需要的头文件
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>

sem_t *x,*y; // 改为信号量指针
pthread_t tid;
pthread_t writerthreads[100],readerthreads[100];
int *readercount, *writercount; // 改为共享内存指针

void* reader(void* param)
{
    if (*writercount > 0) { // 解引用共享变量
        sem_wait(x);
        (*readercount)++; // 解引用共享变量
        if (*readercount == 1) { // 解引用共享变量
            sem_wait(y);
        }
        sem_post(x);
        printf("%d reader is inside\n",*readercount); // 解引用共享变量

        //read all the files in the directory

        sleep(3);
        sem_wait(x);
        (*readercount)--; // 解引用共享变量
        if (*readercount == 0) { // 解引用共享变量
            sem_post(y);
        }
        sem_post(x);
        printf("%d Reader is leaving\n",*readercount+1); // 解引用共享变量
    } else {
        printf("Nothing to view\n");
    }
    return NULL;
}

void* writer(void* param)
{
    printf("Master is trying to upload\n");
    sem_wait(y);
    printf("Master is uploading\n");

    //create file in a directory

    sem_post(y);
    (*writercount)++; // 解引用共享变量
    printf("Master is leaving\n");
    return NULL;
}

int main()
{
    int a,i = 0,b;
    // 初始化共享内存存储readercount和writercount
    int shm_fd = shm_open("/shm_rwcount", O_CREAT | O_RDWR, 0666);
    ftruncate(shm_fd, 2 * sizeof(int));
    void *shm_ptr = mmap(NULL, 2 * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    readercount = (int*)shm_ptr;
    writercount = (int*)shm_ptr + 1;
    *readercount = 0;
    *writercount = 0;

    // 创建有名信号量,天然支持跨进程访问
    x = sem_open("/sem_x", O_CREAT | O_RDWR, 0666, 1);
    y = sem_open("/sem_y", O_CREAT | O_RDWR, 0666, 1);

    while (1) {
        printf("Enter 1 to View  / 2 to Upload / 3 to Exit:");
        scanf("%d",&b);
        if (b == 1) {
            pthread_create(&readerthreads[i],NULL,reader,NULL);
        } else if (b == 2) {
            pthread_create(&writerthreads[i],NULL,writer,NULL);
        } else {
            // 退出前清理资源
            sem_close(x);
            sem_close(y);
            sem_unlink("/sem_x");
            sem_unlink("/sem_y");
            munmap(shm_ptr, 2 * sizeof(int));
            shm_unlink("/shm_rwcount");
            exit(0);
        }
        pthread_join(writerthreads[i],NULL);
        pthread_join(readerthreads[i],NULL);
        i++;
    }

    return 0;
}

2. b.c(从程序)修改后代码

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
// 新增跨进程通信需要的头文件
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>

sem_t *x,*y; // 改为信号量指针
pthread_t tid;
pthread_t readerthreads[100];
int *readercount, *writercount; // 改为共享内存指针

void* reader(void* param)
{
    if (*writercount > 0) { // 解引用共享变量
        sem_wait(x);
        (*readercount)++; // 解引用共享变量
        if (*readercount == 1) { // 解引用共享变量
            sem_wait(y);
        }
        sem_post(x);
        printf("%d Follower is inside\n",*readercount); // 解引用共享变量
        //read all the files in the directory
        sleep(3);
        sem_wait(x);
        (*readercount)--; // 解引用共享变量
        if (*readercount == 0) { // 解引用共享变量
            sem_post(y);
        }
        sem_post(x);
        printf("%d Follower is leaving\n",*readercount+1); // 解引用共享变量
    } else {
        printf("Nothing to view\n");
    }
    return NULL;
}

int main()
{
    int a,i = 0,b;
    // 打开主程序创建的共享内存
    int shm_fd = shm_open("/shm_rwcount", O_RDWR, 0666);
    void *shm_ptr = mmap(NULL, 2 * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    readercount = (int*)shm_ptr;
    writercount = (int*)shm_ptr + 1;

    // 打开主程序创建的有名信号量
    x = sem_open("/sem_x", O_RDWR);
    y = sem_open("/sem_y", O_RDWR);

    while (1) {
        printf("Enter 1 to View  / 3 to Exit:");
        scanf("%d",&b);
        if (b == 1) {
            pthread_create(&readerthreads[i],NULL,reader,NULL);
        } else {
            // 退出前清理资源
            sem_close(x);
            sem_close(y);
            munmap(shm_ptr, 2 * sizeof(int));
            exit(0);
        }
        pthread_join(readerthreads[i],NULL);
        i++;
    }

}

3. 编译运行说明

  • 两个程序编译时都需要加-pthread和-lrt参数,示例编译命令:
    gcc a.c -o master -pthread -lrt
    gcc b.c -o follower -pthread -lrt
    
  • 运行顺序:先启动master主程序,再启动follower从程序
  • 若程序异常退出导致信号量/共享内存残留,可手动删除/dev/shm/路径下对应sem_x、sem_y、shm_rwcount文件后再重新运行

内容的提问来源于stack exchange,提问作者Checker Pecker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:24:03