这个问题更困难,但我想理解一个更简单的例子. 假设我有3个流程,并且我希望流程3在流程1之前开始,我该如何做到?或者,有可能做到吗?

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

int main() {
    sem_t semaphore;

    // Initialize semaphore with initial value 0
    if (sem_init(&semaphore, 0, 0) == -1) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }

    // Create child process 1
    if (fork() == 0) {
        // Child process 1 (Process 1) starts here
        printf("Process 1 started.\n");
        // Wait for signal from Process 3
        sem_wait(&semaphore); 
        printf("Process 1 completed its work.\n");
        exit(0);
    }

    // Create child process 2
    if (fork() == 0) {
        // Child process 2 (Process 2) starts here
        printf("Process 2 started.\n");
        printf("Process 2 completed its work.\n");
        exit(0);
    }

    // Create child process 3
    if (fork() == 0) {
        // Child process 3 (Process 3) starts here
        printf("Process 3 started.\n");
        // Signal Process 1 to start
        sem_post(&semaphore);
        exit(0);
    }

    wait(NULL);
    wait(NULL);
    wait(NULL);

    // Destroy semaphore
    sem_destroy(&semaphore);

    return 0;
}

这是我得到的输出:

Process 1 started.
Process 3 started.
Process 2 started.
Process 2 completed its work.

这就像进入一个无限循环,进程1和进程3不会终止.

推荐答案

您需要使用"共享"信号量来在进程之间共享/发送信号. 非共享信号量(就像您正在使用的那样)只能同步单个进程中的线程.

要创建共享信号量,您需要将其分配到共享内存中,这有点棘手. 最简单的方法是使用

#include <sys/mman.h>

    :

    sem_t *semaphore = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                            MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    if (semaphore == MAP_FAILED || sem_init(semaphore, 1, 0) == -1) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }

这有点低效,因为它为信号量分配了整个页面(通常为4096字节),浪费了大部分(mmap会将请求的大小四舍五入到页面大小的倍数).

如果您需要多个信号量,您可以将它们分配为一个数组,只需调用mmap即可. 如果您需要更多共享内存(例如用于在进程之间通信的缓冲区),您可以将所需的所有内容聚集在一起到一个大型 struct 中,然后用mmap分配它

C++相关问答推荐

Apple Libm的罪恶功能

你能用自己的地址声明一个C指针吗?

GCC不警告隐式指针到整数转换'

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

如何在Visual Studio代码中关闭此函数名称显示功能?

如何一次获取一个字符

为什么我不能只在内存地址中添加一个int来寻址任何数组?

我的程序在收到SIGUSR1信号以从PAUSE()继续程序时总是崩溃()

#定义SSL_CONNECTION_NO_CONST

按长度对argv中的单词进行排序

将多项式从文件.txt加载到终端时出现问题

我在C程序的Flex/Bison中遇到语法错误

如何在VSCode中创建和使用我自己的C库?

在文件描述符上设置FD_CLOEXEC与将其传递给POSIX_SPOWN_FILE_ACTIONS_ADCLOSE有区别吗?

分配给静态变量和动态变量的位置之间有区别吗?

为什么一个在线编译器拒绝这个VLA代码,而本地的Apple clang却不拒绝;t?

不兼容的整数到指针转换传递';char';到类型';常量字符*

即使客户端不发送数据,也会发生UNIX套接字读取

使用 c 中的 write() 函数将非 ASCII 字符写入标准输出

为什么写入关闭管道会返回成功