简体   繁体   中英

How to use semaphores to synchronize two processes so I can have the desired output in C?

I have two processes ( a parent and a child - I did that using fork).

在此处输入图像描述

I want to synchronize the two processes using semaphores, so that the output is just "a=20".

This is my code:

#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/time.h>
#include <fcntl.h>

sem_t sem1;
sem_t sem2;
int a=0;

int main() {
    sem_init(&sem1, 0, 1);
    sem_init(&sem2, 0, 1);

    pid_t pid = fork();

    if (pid == 0) {
        sem_wait(&sem1);
        a = 10;
       if (a == 10) {
            printf("a = %d\n", a);
       }
       sem_post(&sem2);
    } else {
        sem_wait(&sem1);
        a = 20;
        if (a == 20) {
            printf("a = %d\n", a);
        }
       sem_post(&sem2);
        wait(NULL);
    }

    sem_destroy(&sem1);
    sem_destroy(&sem2);

    return 0;
}

I want the outcome of that code to be always "a=20" but when I run it I get the result "a=20 a=10".

First the child process gives 'a' the value 10. Then the parent process overwrites the value of 'a' to 20. Then we enter the 'if' statement of parent process, checks if a=20 and prints it. Then the child process checks if a=10 but 'a' does not equal to 10 because the parent process gave to 'a' the value of 20, but "a=10" still gets printed and I cannot understand why.

The problem is I want the part where the child checks if a=10 to stay there but don't get a=10 printed on the screen. I want the output to be just a=20.

I'm assuming this is running on Linux. You have three problems.

The first is that you are trying to synchronise two processes. When you are sharing a semaphore between two processes, according to the man page , you need to

  • the second parameter must be non zero
  • the semaphore must be located in shared memory. Ordinary global memory is not shared.

Your second problem is that both the parent and the child wait on sem1 and then post to sem2 . That means one of the threads will block forever probably (according to the man page, sem_destroy causes undefined behaviour if there are processes waiting when it is called), but you can't tell which one. What you need to do is make sure the child process gets to a = 10; first but the comparison second. You need some synchronisation between the assignment and the comparison.

Your third problem is that each process has its own copy of a . This, like the semaphores needs to go into shared memory.


To expand on the synchronisation point, you need something like this (using pseudocode):

Parent
------

initialise shared memory
initialise sem1 and sem2 and a all to 0
fork

wait on sem1
set a = 20
if a == 20 print
post on sem2

Child
-----
set a = 10
post on sem1
wait on sem2
if a == 10 print

sem1 is used to signal that the child has set a to 10. sem2 is used to signal that the parent has set a to 20 and printed.

Depending on your architecture and hardware, you may have to make a volatile to disable optimisations that keep it in registers and have a memory barrier to make sure it gets flushed from CPU cache to main memory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM