我分配了一个整数大小的共享内存段。
stdout的预期结果应该是:
P: 1
C: 2
但它是:
C: 1
P: 2
为什么在父完成并解锁共享内存段之前,子进程没有被阻塞?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>
#define SHMSEGSIZE sizeof(int)
int main(void){
pid_t pid;
int shmID;
int *shared_mem;
/* initializing shared memory */
shmID = shmget(IPC_PRIVATE, SHMSEGSIZE, IPC_CREAT | 0644);
shared_mem = (int *)shmat(shmID, 0, 0);
*shared_mem = 0;
/* initializing semaphore */
sem_t sem;
int pshared = 1; // !=0 for processes, =0 for threads
int value = 1; // number of processes at a time
sem_init(&sem, pshared, value); // initialize the semaphore
pid = fork();
if(pid>(pid_t)0){ // parent
sem_wait(&sem);
sleep(6);
*shared_mem += 1;
printf("P: %d\n", *shared_mem);
sem_post(&sem);
exit(EXIT_SUCCESS);
} // parent
if(pid==(pid_t)0){ // child
sleep(3);
sem_wait(&sem);
*shared_mem += 1;
sem_post(&sem);
printf("C: %d\n", *shared_mem);
exit(EXIT_SUCCESS);
} // child
/* fork() failed */
printf("Failed to fork().");
exit(EXIT_FAILURE);
}
编译:
gcc -o executable sem.c -pthread
答案 0 :(得分:2)
sem_t
本身必须在共享内存中,如果它是“pshared”。
struct my_shared_mem {
sem_t sem;
int value;
};
... later ...
struct my_shared_mem *shared;
shmID = shmget(IPC_PRIVATE, sizeof(*shared), ...);
shared = shmat(shmID, ...);
shared->value = 0;
sem_init(&shared->sem, 1, 1);
...
答案 1 :(得分:1)
每当fork时,子进程都会继承父进程的地址空间的副本。因此,变量sem将被复制到子地址空间。父母所做的任何更改都不会反映在孩子身上。 (sem_wait
基本上减少了信号量的值)
如前所述,一种方法是将信号量放在共享内存段中。
另一种方法是使用semget
调用创建系统范围的信号量(请参阅man semget
)。这里的接口比pthread库一点复杂一点。您必须使用semctl
设置值(使用union semun
)并使用semop
执行信号量操作(使用struct sembuf
)。该信号量是具有密钥的IPC(在semget
调用中传递)。您可以使用ipcs -s