1

I have two C files: a.c (master) and b.c (follower).
I want to create a synchronization between master and follower using a semaphore.
According to what I have learnt I need to have a global POSIX semaphore to make this work.
How can I implement this in the b.c (follower) file using only the semaphores in a.c (master)?

Semaphore implemented for a.c file (master):

#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;
}

Semaphore in the b.c file (follower):

#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++;
    }

}
Jorengarenar
  • 2,705
  • 5
  • 23
  • 60
  • 1
    Does this answer your question? [System-wide global variable / semaphore / mutex in C++/Linux?](https://stackoverflow.com/questions/32338732/system-wide-global-variable-semaphore-mutex-in-c-linux) – Nikos C. Sep 25 '21 at 04:00
  • 1
    Specifically, see https://man7.org/linux/man-pages/man3/sem_open.3.html where it mentions that you must use `sem_open()` to create or open a named semaphore and that the name you give to the semaphore **must** start with `/`. Also make sure the name is unique, as other processes on the system also use global semaphores and you don't want your name to clash with others. – Nikos C. Sep 25 '21 at 04:01
  • @NikosC., yes its useful, but can I see a sample implementation of it? – Checker Pecker Sep 25 '21 at 04:11

1 Answers1

0

Having two different process, you have to use named semaphore, like described here:

Share POSIX semaphore among multiple processes

So your code can be edited like

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;
}

and 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++;
    }

}
Carlo Banfi
  • 186
  • 1
  • 7
  • i read all the documentation is it possible for you to show me in one of my files how to implement as I have never done it before and its confusing to me since im a beginner. I want to know how to use after intializing the semphore name. – Checker Pecker Sep 25 '21 at 05:52
  • @CheckerPecker I edited the answer including modification on your source code. Please check the use of `writercount` in `b.c`, because nothing update its value. – Carlo Banfi Sep 25 '21 at 07:29
  • thank you very much Im getting these errors: 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): undefined reference to `sem_close' /usr/bin/ld: a.c:(.text+0x2bc): undefined reference to `sem_close' /usr/bin/ld: a.c:(.text+0x2c8): undefined reference to `sem_unlink' /usr/bin/ld: a.c:(.text+0x2d4): undefined reference to `sem_unlink' collect2: error: ld returned 1 exit status – Checker Pecker Sep 25 '21 at 08:10
  • how can I avoid them? – Checker Pecker Sep 25 '21 at 08:10
  • Did you link the thread lib? E.g.: `gcc a.c -lpthread -o a.exe` – Carlo Banfi Sep 25 '21 at 08:23
  • yes i have linked – Checker Pecker Sep 25 '21 at 14:57
  • Are you in this case? https://stackoverflow.com/questions/4916881/sem-open-error-undefined-reference-to-sem-open-on-linux-ubuntu-10-10 – Carlo Banfi Sep 25 '21 at 18:32