简体   繁体   English

如何使用信号量同步两个进程,以便我可以在 C 中获得所需的 output?

[英]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).我有两个进程(一个父进程和一个子进程——我是用 fork 做的)。

在此处输入图像描述

I want to synchronize the two processes using semaphores, so that the output is just "a=20".我想使用信号量同步这两个进程,这样 output 就是“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".我希望该代码的结果始终为“a=20”,但是当我运行它时,我得到的结果是“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.首先子进程给'a'赋值10。然后父进程将'a'的值覆盖为20。然后我们进入父进程的'if'语句,检查是否a=20并打印它。 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.然后子进程检查 a=10 但 'a' 是否不等于 10,因为父进程给 'a' 的值为 20,但仍然打印出“a=10”,我不明白为什么。

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.问题是我希望孩子检查 a=10 是否留在那里但不要在屏幕上打印 a=10 的部分。 I want the output to be just a=20.我希望 output 只是 a=20。

I'm assuming this is running on Linux. You have three problems.我假设这是在 Linux 上运行。你有三个问题。

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.信号量必须位于共享 memory。普通全局 memory 不共享。

Your second problem is that both the parent and the child wait on sem1 and then post to sem2 .你的第二个问题是父母和孩子都在等待sem1然后发布到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.这意味着其中一个线程可能会永远阻塞(根据手册页,如果调用它时有进程在等待,sem_destroy 会导致未定义的行为),但您无法分辨是哪一个。 What you need to do is make sure the child process gets to a = 10;你需要做的是确保子进程达到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 .您的第三个问题是每个进程都有自己a . This, like the semaphores needs to go into shared memory.这个,就像信号量需要把go变成共享的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. sem1 用于表示子级已将 a 设置为 10。sem2 用于表示父级已将 a 设置为 20 并打印。

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.根据您的体系结构和硬件,您可能必须a volatile以禁用将其保留在寄存器中的优化,并具有 memory 屏障以确保它从 CPU 缓存刷新到主 memory。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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