2014-11-04 79 views
0

我想通过使用共享内存来共享信号到所有进程。 首先,我将对象“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

你缺少一个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; 
     } 
    } 
} 
+0

谢谢你,它的工作。 – Stark 2014-11-05 12:35:52