信号量 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,也起不了作用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值