信號量 sem_t 進程同步


sem_t分為有名和無名。有名的sem_t通過sem_open來創建, 而無名的sem_t通過sem_init的初始化。 用有名的sem_t來進程間同步是件很容易的事情,百度上一搜很多想相關的例子。

有名和無名的sem_t主要區別:

1. 效率:有名sem_t是放在文件,無名的sem_t是放在內存。

2.限制:有名的sem_t可以用來同步多線程,任意多進程。而無名的sem_t可以用來同步多線程,以及Fork出來的進程間的同步。

網上想關的例子很多,本文主要是測試一下用無名sem_t進程同步,比如你在使用nginx的時候,nginx會fork出很多works,如果在works間你希望能同步一些操作,那么這個時候就可以用它,注意下面API描述中的紅色部分,明確說了需要放到共享內存(shared memory)。

 

Name
sem_init - initialize an unnamed semaphore Synopsis #include
<semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value); Link with -pthread. Description sem_init() initializes the unnamed semaphore at the address pointed to by sem. The value argument specifies the initial value for the semaphore. The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes. If pshared has the value 0, then the semaphore is shared between the threads of a process, and should be located at some address that is visible to all threads (e.g., a global variable, or a variable allocated dynamically on the heap). If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since a child created by fork(2) inherits its parent's memory mappings, it can also access the semaphore.) Any process that can access the shared memory region can operate on the semaphore using sem_post(3), sem_wait(3), etc. Initializing a semaphore that has already been initialized results in undefined behavior.

 

下面是一段簡單的測試代碼

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

void *createSharedMemory(size_t size) {
    void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if (addr == MAP_FAILED) {
        return NULL;
    }
    return addr;
}

void freeSharedMemory(void *addr, size_t size)
{
    if (munmap(addr, size) == -1) {
        printf("munmap(%p, %d) failed", addr, (int)size);
    }
}

int main(int argc, char *argv[] ) {
    
    sem_t* mutex_share = createSharedMemory(sizeof(sem_t));
    sem_t mutex_not_share;
    if (mutex_share == NULL) {
        printf("creat share memory error\n");
        return 0;
    }
    if( sem_init(mutex_share,1,1) < 0  || sem_init(&mutex_not_share,1,1) < 0) {
      printf("semaphore initilization\n");
      return 0;
    }
    if (fork() == 0) {
        sem_wait(&mutex_not_share);
        for(int j = 0;j<5;j++) {
            printf("mutex_not_share child j = %d\n", j);
            usleep(50000);
        }
        sem_post(&mutex_not_share);

        sem_wait(mutex_share);
        for (int i = 0;i<5;i++) {
            printf("mutex_share child i = %d\n", i);
            usleep(50000);
        }
        sem_post(mutex_share);

    }
    else {
        sem_wait(&mutex_not_share);
        for(int j = 0;j<5;j++) {
            printf("mutex_not_share parent j = %d\n", j);
            usleep(50000);
        }
        sem_post(&mutex_not_share);
        sem_wait(mutex_share);
        for (int i = 0;i<5;i++) {
            printf("mutex_share parent i = %d\n", i);
            usleep(50000);
        }
        sem_post(mutex_share);
    }
    freeSharedMemory(mutex_share,sizeof(sem_t));
    return 0;
}

 

運行結果可以看出,如果沒有放到共享內存,就算將pshared設置為1,也起不了作用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM