我想通过使用共享内存来共享所有进程的信号量。 首先,我正在映射对象" sem"在父进程中共享内存。 在分叉过程之后,我也在做同样的事情,但是使用" sem"在孩子进程的地址空间。 它应该在所有进程的共享内存中使用一个信号量,但它不起作用。分享信号量有问题。我无法使用命名信号量。
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
void doSomething();
void shareSem();
void recieveSem();
sem_t sem;
int main(int argc, char *argv[]) {
shareSem();
sem_init(&sem, 1, 1);
for(int i = 0; i < 1; i++){
int pid = fork();
if(pid == 0)
recieveSem();
};
doSomething();
return 0;
}
void doSomething() {
int i, time;
for (i = 0; i < 3; i++) {
// P operation
if (sem_wait(&sem) == 0) {
// generate random amount of time (< 30 seconds)
time = (int) ((double) rand() / RAND_MAX * 5);
printf("Process %i enters and sleeps for %d seconds...\n", getpid(), time);
sleep(time);
printf("Process %i leaves the critical section\n", getpid());
// V operation
sem_post(&sem);
}
else
printf("Process id: %d :error\n", getpid());
}
}
void shareSem()
{
int fd, status;
fd = shm_open("/swp_es", O_RDWR | O_CREAT, 0777);
if(fd == -1) {
printf("shm_creator1");
}
status = ftruncate(fd, sizeof(sem));
if(status != 0) {
printf("shm_creator2");
}
void *ptr = mmap(&sem, sizeof(sem), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(ptr == MAP_FAILED) {
printf("shm_creator3");
}
}
void recieveSem()
{
int fd;
fd = shm_open("/swp_es", O_RDWR, 0777);
if(fd == -1) {
printf("shm_user");
}
void *ptr = mmap(&sem, sizeof(sem), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(ptr == MAP_FAILED) {
printf("shm_user");
}
//munmap(buffer, sizeof(buffer));
}
结果是:
Process 4534308 enters and sleeps for 2 seconds...
Process id: 4534309 :error
Process id: 4534309 :error
Process id: 4534309 :error
Process 4534308 leaves the critical section
Process 4534308 enters and sleeps for 0 seconds...
Process 4534308 leaves the critical section
Process 4534308 enters and sleeps for 1 seconds...
Process 4534308 leaves the critical section
答案 0 :(得分:0)
您遗漏mmap()
未必将共享内存段映射到您提供的特定地址。此外,在某些系统上,地址有特定的对齐要求,如果您指定的指针不满足,mmap()
将失败。传递NULL
作为地址更加便携,只需让系统选择即可。然后系统选择的位置,将你的信号量放在那里。
另外,你做得太难了。如果您fork()
是子进程,那么它将继承父进程的内存映射。你不必重新创建它们。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
void doSomething(sem_t *sem);
int main(int argc, char *argv[]) {
int shm_fd = shm_open("/swp_es", O_RDWR | O_CREAT, 0600);
sem_t *sem;
int i;
if (shm_fd == -1) {
printf("Failed to create/open a shared memory object\n");
return 1;
}
if (ftruncate(shm_fd, sizeof(*sem)) != 0) {
printf("Failed to resize the shared memory object\n");
return 1;
}
sem = mmap(NULL, sizeof(*sem), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if(sem == MAP_FAILED) {
printf("Failed to mmap() the shared memory object\n");
return 1;
}
/* It's safe to unlink once the shared memory is mapped */
if (shm_unlink("/swp_es") < 0) {
printf("warning: failed to unlink the shared memory object\n");
}
if (sem_init(sem, 1, 1) != 0) {
printf("Failed to initialize the semaphore\n");
return 1;
}
for(i = 0; i < 1; i++){
int pid = fork();
if (pid < 0) {
printf("Failed to fork()\n");
return 1;
} else if (pid == 0) {
printf("Child %d successfully fork()ed\n", i);
}
};
doSomething(sem);
return 0;
}
void doSomething(sem_t *sem) {
int i;
for (i = 0; i < 3; i++) {
if (sem_wait(sem) == 0) {
int time = (int) (rand() / (RAND_MAX * 5.0));
printf("Process %i enters and sleeps for %d seconds...\n", getpid(), time);
sleep(time);
printf("Process %i leaves the critical section\n", getpid());
sem_post(sem);
}
else {
printf("Process id: %d :error in sem_wait()\n", getpid());
break;
}
}
}