如何用Semaphore同步C语言父子进程使输出仅为a=20
Hey there! Let's break down why your code is printing both outputs, and fix it to only show a=20 while keeping that if check in the child process.
The Core Issues
Semaphores aren't shared between parent and child
When you usesem_init(&sem1, 0, 1), the second parameter0tells the system this semaphore is only shared between threads within the same process. Afterfork(), the child gets a copy of the parent's memory—sosem1andsem2are completely separate in each process. That means yoursem_wait/sem_postcalls don't actually synchronize anything; both processes can run their code without blocking each other.The variable
ais process-private
Global variables aren't shared across processes afterfork(). The child gets its own copy ofa, and the parent gets its own. So when the child setsa=10, it's only modifying its own version, and the parent'sa=20is a separate value. That's why bothifconditions trigger and print.
Fixing the Code
To make this work, we need two things:
- Shared semaphores (so parent and child can actually sync)
- Shared memory for
a(so both processes modify the same variable)
We'll use named semaphores (via sem_open) for inter-process sync, and mmap to create shared memory for a. We'll also adjust the semaphore logic to ensure the parent modifies a to 20 before the child checks its value—so the child's if (a == 10) condition fails and doesn't print.
Here's the corrected code:
#include <stdio.h> #include <semaphore.h> #include <unistd.h> #include <sys/wait.h> #include <stdlib.h> #include <sys/mman.h> #include <fcntl.h> #include <sys/stat.h> // Names for our named semaphores #define SEM_CHILD_DONE "/sem_child_done" #define SEM_PARENT_DONE "/sem_parent_done" int main() { // Create shared memory for variable 'a' int fd = shm_open("/shared_a", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); ftruncate(fd, sizeof(int)); int *a = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); *a = 0; // Initialize shared 'a' to 0 // Initialize named semaphores sem_unlink(SEM_CHILD_DONE); // Clean up if semaphores exist from prior runs sem_unlink(SEM_PARENT_DONE); sem_t *sem_child_done = sem_open(SEM_CHILD_DONE, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0); sem_t *sem_parent_done = sem_open(SEM_PARENT_DONE, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, 0); pid_t pid = fork(); if (pid == 0) { // Child process: set a=10, then wait for parent to update it to 20 *a = 10; sem_post(sem_child_done); // Notify parent we've set a=10 sem_wait(sem_parent_done); // Wait for parent to modify a to 20 if (*a == 10) { // This condition will now be false printf("a = %d\n", *a); } // Cleanup child resources sem_close(sem_child_done); sem_close(sem_parent_done); munmap(a, sizeof(int)); close(fd); } else { // Parent process: wait for child to set a=10, then update to 20 sem_wait(sem_child_done); // Wait for child to set a=10 *a = 20; if (*a == 20) { // This condition is true, so we print printf("a = %d\n", *a); } sem_post(sem_parent_done); // Notify child we've updated a // Wait for child to finish, then cleanup parent resources wait(NULL); sem_close(sem_child_done); sem_close(sem_parent_done); sem_unlink(SEM_CHILD_DONE); sem_unlink(SEM_PARENT_DONE); munmap(a, sizeof(int)); close(fd); shm_unlink("/shared_a"); } return 0; }
How This Works
- Shared
a: We useshm_openandmmapto create a shared memory region, so both parent and child access the exact sameintvalue. - Semaphore Sync:
- The child sets
a=10, then signals the parent viasem_child_done. - The parent waits for that signal, then sets
a=20, prints it, and signals the child viasem_parent_done. - The child waits for the parent's signal before checking
a—by this time,ais 20, so theif (a ==10)condition fails and nothing is printed from the child.
- The child sets
- Cleanup: We unlink semaphores and shared memory to avoid leaving resources hanging after the program exits.
Compilation Note
Don't forget to link against the real-time library when compiling:
gcc your_program.c -o your_program -lrt
内容的提问来源于stack exchange,提问作者katerina

