将信号量分享给流程

时间:2014-11-04 20:24:06

标签: c fork shared-memory semaphore qnx

我想通过使用共享内存来共享所有进程的信号量。 首先,我正在映射对象" 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

1 个答案:

答案 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;
        }
    }
}