POSIX信号量

3.1 POSIX信号量

​ POSIX信号量有两种:有名信号量无名信号量,无名信号量也被称作基于内存的信号量。有名信号量通过IPC名字进行进程间的同步,而无名信号量如果不是放在进程间的共享内存区中,是不能用来进行进程间同步的,只能用来进行线程同步,线程同步将在后面讲到,这里我们重点研究有名信号量。

3.1.1 创建一个信号量

​ 创建的过程还要求初始化信号量的值。根据信号量取值(代表可用资源的数目)的不同,POSIX信号量还可以分为:

  • 二值信号量:信号量的值只有0和1,这和互斥量很类型,若资源被锁住,信号量的值为0,若资源可用,则信号量的值为1;

  • 计数信号量:信号量的值在0到一个大于1的限制值(POSIX指出系统的最大限制值至少要为32767)。该计数表示可用的资源的个数。

#include <semaphore.h>
sem_t *sem_open(const char *name,int oflag, mode_t mode , int value);
 /*
返回:若成功则为指向信号量的指针,有名字的信号量作为文件被创建在/dev/shm里。若出错则为SEM_FAILED,

name参数:mq_open、sem_open、shm_open这三个函数的name参数都使用“Posix IPC名字”,它可能某个文件系统中的一个真正的路径名,也可能不是。

oflag参数:可以是0、O_CREAT或O_CREAT|O_EXCL。如果指定O_CREAT标志而没有指定O_EXCL,那么只有当所需的信号量尚未存在时才初始化它。但是如果在所需的信号量存在的情况下指定O_CREAT|O_EXCL却会报错。

mode参数:指定权限位。

value参数:指定信号量的初始值。该初始值不能超过SEM_VALUE_MAX(这个常值必须至少为32767)。二值信号量的初始值通常为1,计数信号量的初始值则往往大于1。
*/

int sem_close(sem_t *sem);
/*
 一个进程终止时,内核会对其上打开着的所有有名信号量自动执行关闭操作,不论该进程是自愿终止还是非自愿终止。   关闭一个信号量并没有将它从系统中删除。Posix有名信号量是随内核持续的。即使当前没有进程打开着某个信号量,   他的值仍然保持。
*/

int sem_unlink(const char *name);
/*
    删除创建的信号量文件
*/

3.1.2 等待一个信号量

​ 该操作会检查信号量的值,如果其值小于或等于0,那就阻塞,直到该值变成大于0,然后等待进程将信号量的值减1,进程获得共享资源的访问权限。

  • 函数sem_wait()用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减去1,表明公共资源经使用后减少,其函数原型是:

int sem_wait(sem_t *sem);

​ 成功返回0,错误返回-1,设置errno

  • 函数sem_trywait()与函数sem_wait()的区别是当信号量的值等于0时,sem_trywait()函数不会阻塞当前线程。

int sem_trywait(sem_t *sem);

​ 成功返回0,错误返回-1,设置errno,当没等到资源的时候,errno为EAGAIN

3.1.3 释放一个信号量

​ 该操作将信号量的值加1,如果有进程阻塞着等待该信号量,那么其中一个进程将被唤醒。

  • 函数sem_post()用来增加信号量的值,其函数原型是:

int sem_post(sem_t* sem);

3.1.4 综合例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
void error_print(const char* msg)
{
    perror(msg);
    exit(-1);
}

int main(int argc, char** argv)
{
    int ret;
    
    sem_t* sem = sem_open("/mysem", O_CREAT,  0666, 1);
    if(sem == NULL) 
        error_print("sem_open");

    puts("wait semahpore...\n");

    sem_wait(sem);
    puts("get");
    sleep(5);
    puts("post");
    sem_post(sem);

    sem_close(sem);
    return 0;
}

编译时需要加上-lpthread:

gcc semtest.c -o semtest -lpthread

运行两次改程序,观察现象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值