信号量主要用于进程间(不是线程)的互斥,通过sem_p()函数加锁使用资源,sem_v函数解锁释放资源,在加锁期间,CPU从硬件级别关闭中断,防止pv操作被打断。
semget函数
int semget(key_t key, int nsems, int semflg);
--功能:用来创建和访问一个信号量集
--参数
key:信号集的key值
nsems:信号集中信号量的个数
semflg:由九个权限标志构成,他们的用法和创建文件时使用的mode模式标志是一样的
--返回值:成功返回一个非负整数,即该信号集的标识码,失败返回-,并且更新errno
shmctl函数
int semctl(int semid, int semnum, int cmd, ...);
--功能:用于控制信号量集
--参数
semid:由semget返回的信号集标识码
semnum:信号集中信号量的序号(信号量的序号从0开始,和数组类似)
cmd:将要采取的动作(有5个可取值)
最后一个参数根据命令不同而不同
--返回值:成功返回0;失败返回-1并且更新errno
semop函数
int semop(int semid, struct sembuf *sops, unsigned nsops);
--功能:
--参数
semid:semget函数的返回值
sops:是个指向一个结构体的指针
nsops:信号量的个数
--返回值:成功返回0,失败返回-,并且更新errno
semop函数续
--sembuf结构体
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_num是信号量的编号
sem_op是信号量一次PV操作是加减的数值,一般只会用到两个值,一个是"-1",也就是P操作,等待信号量变得可用;另一个是"+1",也就是V操作,发出信号量已经变得可用。
sem_flg的两个取值IPC_NOWAIT或SEM_UNDO,SEM_UNDO是进程完成P操作后直接被终止了,那么系统会自动执行V操作,恢复成默认值
//信号量API
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h> //这个定义不可少
union semun
{
int val; // Value for SETVAL
struct semid_ds *buf; // Buffer for IPC_STAT, IPC_SET
unsigned short *array; // Array for GETALL, SETALL
struct seminfo *__buf; // Buffer for IPC_INFO(Linux-specific)
}; /**
* sem_setval - 设置信号量的资源值
* semid:由semget返回的信号集标识码
* val:资源值
* 成功返回0,失败返回-1
* */
int sem_setval(int semid, int val)
{
int ret = ;
//union semun必须自定义
union semun su;
su.val = val;
//semctl()第二个参数是序号,这里取第一个信号量
ret = semctl(semid, , SETVAL, su);
if (ret == -)
{
perror("semctl() err");
}
return ret;
} /**
* sem_setval - 获取信号量的资源值
* semid:由semget返回的信号集标识码
* 成功返回可用资源值,失败返回-1
* */
int sem_getval(int semid)
{
int ret = ;
//semctl()第二个参数是序号,这里取第一个信号量
//当使用GETVAL命令时,调用中的最后一个参数被忽略
//成功返回该信号量的可用资源值
ret = semctl(semid, , GETVAL, );
if (ret == -)
{
perror("semctl() err");
}
printf("getval=%d\n", ret);
return ret;
} /**
* sem_p - 信号量P操作
* semid:由semget返回的信号集标识码
* 成功返回0,失败返回-1
* */
int sem_p(int semid)
{
int ret=;
//通过struct sembuf结构体的sem_op属性设置P操作
//sem_flg默认设置为0
struct sembuf sbuf={,-,};
ret=semop(semid,&sbuf,);
if(ret==-)
perror("semop() err");
return ret;
} /**
* sem_v - 信号量V操作
* semid:由semget返回的信号集标识码
* 成功返回0,失败返回-1
* */
int sem_v(int semid)
{
int ret=;
//通过struct sembuf结构体的sem_op属性设置P操作
//sem_flg默认设置为0
struct sembuf sbuf={,,};
ret=semop(semid,&sbuf,);
if(ret==-)
perror("semop() err");
return ret;
} int main()
{
//创建或者访问信号量集
int semid = ;
//第二个参数创建几个信号量
semid = semget(0x1234, , | IPC_CREAT | IPC_EXCL);
if (semid == -)
{
if (errno == EEXIST)
{
printf("该信号量集已经存在!\n");
semid = semget(0x1234, , );
} else
{
perror("semget() err");
return -;
}
}
//设置第0个信号量的s(可用资源)的值为1
sem_setval(semid, );
sem_getval(semid);
sem_p(semid);
printf("dddddd\n");
sem_v(semid);
return ;
}

Linux 信号量详解一的更多相关文章

  1. Linux信号量详解

    1.什么是信号量信号量是一种特殊的变量,访问具有原子性.只允许对它进行两个操作:1)等待信号量当信号量值为0时,程序等待:当信号量值大于0时,信号量减1,程序继续运行.2)发送信号量将信号量值加1. ...

  2. Linux 系统结构详解

    Linux 系统结构详解 Linux系统一般有4个主要部分: 内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统 ...

  3. Linux Ptrace 详解

    转 https://blog.csdn.net/u012417380/article/details/60470075 Linux Ptrace 详解 2017年03月05日 18:59:58 阅读数 ...

  4. [转帖]Linux文件系统详解

    Linux文件系统详解 https://www.cnblogs.com/alantu2018/p/8461749.html 贼复杂.. 从操作系统的角度详解Linux文件系统层次.文件系统分类.文件系 ...

  5. Linux命令详解之—tail命令

    tail命令也是一个非常常用的文件查看类的命令,今天就为大家介绍下Linux tail命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux tail命令主要用来从指定点开始将文 ...

  6. Linux命令详解之—less命令

    Linux下还有一个与more命令非常类似的命令--less命令,相比于more命令,less命令更加灵活强大一些,今天就给大家介绍下Linux下的less命令. 更多Linux命令详情请看:Linu ...

  7. Linux命令详解之—more命令

    Linux more命令同cat命令一样,多用来查看文件内容,本文就为大家介绍下Linux more命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux的more命令类似 ca ...

  8. 【转】linux命令详解:md5sum命令

    [转]linux命令详解:md5sum命令 转自:http://blog.itpub.net/29320885/viewspace-1710218/ 前言 在网络传输.设备之间转存.复制大文件等时,可 ...

  9. Linux命令详解之—cat命令

    cat命令的功能是连接文件或标准输入并打印,今天就为大家介绍下Linux中的cat命令. 更多Linux命令详情请看:Linux命令速查手册 Linux 的cat命令通常用来显示文件内容,也可以用来将 ...

随机推荐

  1. 深入浅出JavaScript之this

    JavaScript中的this比较灵活,根据在不同环境下,或者同一个函数在不同方式调用下,this都有可能是不同的.但是有一个总的原则,那就是this指的是,调用函数的那个对象. 下面是我的学习笔记 ...

  2. Android面试一天一题(1Day)

    写在前面 该博客思路源于在简书看到goeasyway博主写的Android面试一天一题系列,无copy之意,仅为让自己总结知识点,成长一点点.先感谢各位大神的无私分享~! 关于题目,大部分则出自And ...

  3. 纯C#的ini格式配置文件读写

    虽然C#里都是添加app.config 并且访问也很方便 ,有时候还是不习惯用他.那么我们来做个仿C++下的那种ini配置文件读写吧,其他人写的都是调用非托管kernel32.dll.我也用过 但是感 ...

  4. android 模拟2048

    利用节日休息时间在ANDROID上进行学习并模拟2048游戏. 效果如下图: 制作思路: 1.画出2048游戏主界面,根据手机屏幕宽高度进行计算并画出每个方块的大小. @Override protec ...

  5. Rafy 框架 - 执行SQL或存储过程

    有时候,开发者不想通过实体来操作数据库,而是希望通过 SQL 语句或存储过程来直接访问数据库.Rafy 也提供了一组 API 来方便实现这类需求. IDbAccesser 接口 为了尽量屏蔽各数据库中 ...

  6. Basic Tutorials of Redis(1) - Install And Configure Redis

    Nowaday, Redis became more and more popular , many projects use it in the cache module and the store ...

  7. Spring下ActiveMQ实战

    MessageQueue是分布式的系统里经常要用到的组件,一般来说,当需要把消息跨网段.跨集群的分发出去,就可以用这个.一些典型的示例就是: 1.集群A中的消息需要发送给多个机器共享: 2.集群A中消 ...

  8. Json CPP 中文支持与入门示例

    在每一个Json Cpp自带*.cpp文件头加上: #include "stdafx.h" 将Json Cpp对自带的头文件的引用修改为单引号方式,例如json_reader.cp ...

  9. php实现设计模式之 策略模式

    策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化.是一种行为模式. 策略模式包含三种角色 1 抽象策略角色: 策略类,通常由一个接口或 ...

  10. 来玩Play框架06 用户验证

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 用户验证(User Authentification)复合的使用Play框架的数个 ...