如何实现两个 C 程序使用的全局 POSIX 信号量?

Posted

技术标签:

【中文标题】如何实现两个 C 程序使用的全局 POSIX 信号量?【英文标题】:How to implement global POSIX semaphore to be used by two C programs? 【发布时间】:2021-09-25 03:26:17 【问题描述】:

我有两个 C 文件:a.c (master) 和 b.c (follower)。 我想使用信号量在 master 和 follower 之间创建同步。 根据我了解到的情况,我需要一个全局 POSIX 信号量才能完成这项工作。 如何仅使用 a.c (master) 中的信号量在 b.c (follower) 文件中实现这一点?

a.c 文件(主)实现的信号量:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

sem_t x,y;
pthread_t tid;
pthread_t writerthreads[100],readerthreads[100];
int readercount = 0, writercount = 0;

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;
    sem_init(&x,0,1);
    sem_init(&y,0,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 
            exit(0);
        
        pthread_join(writerthreads[i],NULL);
        pthread_join(readerthreads[i],NULL);
        i++;
    

    return 0;

b.c 文件中的信号量(关注者):

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

sem_t x,y;
pthread_t tid;
pthread_t readerthreads[100];
int readercount = 0, writercount = 0;

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;
    sem_init(&x,0,1);
    sem_init(&y,0,1);

    while (1) 
        printf("Enter 1 to View  / 3 to Exit:");
        scanf("%d",&b);
        if (b == 1) 
            pthread_create(&readerthreads[i],NULL,reader,NULL);
         else 
            exit(0);
        
        pthread_join(readerthreads[i],NULL);
        i++;
    


【问题讨论】:

这能回答你的问题吗? System-wide global variable / semaphore / mutex in C++/Linux? 具体而言,请参阅 man7.org/linux/man-pages/man3/sem_open.3.html,其中提到您必须使用 sem_open() 来创建或打开命名信号量,并且您为信号量提供的名称必须/。还要确保名称是唯一的,因为系统上的其他进程也使用全局信号量,并且您不希望您的名称与其他进程发生冲突。 @NikosC.,是的,它很有用,但我可以看到它的示例实现吗? 【参考方案1】:

有两个不同的进程,你必须使用命名信号量,如下所述:

Share POSIX semaphore among multiple processes

所以你的代码可以像这样编辑

a.c

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>

sem_t *x,*y;
pthread_t tid;
pthread_t writerthreads[100],readerthreads[100];
int readercount = 0, writercount = 0;

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;
    x = sem_open("/semaphore_x", O_CREAT | O_EXCL, S_IRWXU | S_IRWXG  | S_IRWXO, 1);
    y = sem_open("/semaphore_y", O_CREAT | O_EXCL, S_IRWXU | S_IRWXG  | S_IRWXO, 1);
    
    if( x == NULL || y == NULL) 
        printf("Unable to open named semaphores\n");
        exit(-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("/semaphore_x");
            sem_unlink("/semaphore_y");
            exit(0);
        
        pthread_join(writerthreads[i],NULL);
        pthread_join(readerthreads[i],NULL);
        i++;
    

    return 0;

b.c

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>

sem_t *x,*y;
pthread_t tid;
pthread_t readerthreads[100];
int readercount = 0, writercount = 0;

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;
    x = sem_open("/semaphore_x", O_RDWR);
    y = sem_open("/semaphore_y", O_RDWR);

    if( x == NULL || y == NULL) 
        printf("Unable to open named semaphores\n");
        exit(-1);
    

    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);
            exit(0);
        
        pthread_join(readerthreads[i],NULL);
        i++;
    


【讨论】:

我阅读了所有文档,您是否可以在我的一个文件中向我展示如何实现,因为我以前从未这样做过,而且由于我是初学者,这让我感到困惑。我想知道初始化信号量名称后如何使用。 @CheckerPecker 我编辑了答案,包括修改您的源代码。请检查b.cwritercount 的使用,因为没有更新它的值。 非常感谢我收到这些错误:a.c:(.text+0x1a5): undefined reference to sem_open' /usr/bin/ld: a.c:(.text+0x1cc): undefined reference to sem_open' /usr/bin/ld: a.c:(.text+0x2ad):未定义引用 sem_close' /usr/bin/ld: a.c:(.text+0x2bc): undefined reference to sem_close' /usr/bin/ld: a.c:(.text+0x2c8): 未定义引用 sem_unlink' /usr/bin/ld: a.c:(.text+0x2d4): undefined reference to sem_unlink' collect2: error: ld 返回 1 个退出状态 我怎样才能避免它们? 你链接线程库了吗?例如:gcc a.c -lpthread -o a.exe

以上是关于如何实现两个 C 程序使用的全局 POSIX 信号量?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 POSIX 信号量值设置为 1?

linux c编程:Posix信号量

C++11 的 std::thread 是不是与 POSIX 信号量兼容?

POSIX信号量互斥锁自旋锁读写锁

无法处理的 POSIX 信号的返回码

从 C++ 中的 posix 信号处理程序获取对象属性