信号量主要用于进程间(不是线程)的互斥,通过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. 全自动迁移数据库的实现 (Fluent NHibernate, Entity Framework Core)

    在开发涉及到数据库的程序时,常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况,这时就需要进行数据库迁移. 实现数据库迁移有很多种办法,从手动管理各个版本的ddl脚本,到实现自己的mig ...

  2. 前端开发:setTimeout与setInterval 定时器与异步循环数组

    前端开发:setTimeout与setInterval 定时器与异步循环数组 前言: 开通博客园三个月以来,随笔记录了工作中遇到的大大小小的难题,也看过无数篇令人启发的文章,我觉得这样的环境是极好的, ...

  3. Visual Studio 2013 Ultimate因为CodeLens功能导致Microsoft.Alm.Shared.Remoting.RemoteContainer.dll高CPU占用率的折中解决方案

    1.为什么Microsoft.Alm.Shared.Remoting.RemoteContainer.dll的CPU占用率以及内存使用率会那么高? 在Visual Studio 2013 Ultima ...

  4. Navisworks 2014 Api 简单的使用

    初次接触Navisworks Api  .NET 的二次开发.主要是研究了一下.关于NavisWorks 结构树的加载. void LoadModel() { //清空当前的结构树信息 treeVie ...

  5. win2008R2 下解决关于mysql odbc无法正常工作问题

    1.安装 mysql-connector-odbc-5.1.1-win32 下载 2.确保IIS中“启用32位应用程序”为True 3.连接字符串: mysql_connstr="Drive ...

  6. jquery在线扫雷

    <扫雷>是一款大众类的益智小游戏,于1992年发行.游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷. 在线试玩 http://hovertree.com/te ...

  7. Socket简单使用

    客户端代码: import java.io.*; import java.net.*; public class DailyAdviceClient { public void go(){ try{ ...

  8. javaScript中的小细节-局部作用域中的var

    javaScript中var是很神奇的,在局部作用域中,var a = b = c = 1;是不一样的,a为使用var声明的变量,而b和c则是全局下的,此类变量被称为隐式全局变量:var a = 1; ...

  9. html5上传图片(二)一解决部分手机拍照上传图片转向问题

    本以为解决跨域上传后没有问题了,不成想被测试找出一个问题,那就是在手机上拍照上传后图片会旋转.很头痛,不过没有办法,问题还是需要解决的.在查阅了一系列资料后我找到了相应的解决方案,利用exif.js获 ...

  10. IOS 开发小技巧总结

    一.添加自定义字体 1.把字体文件拖到工程中. 2.plist 文件中添加字段:<Array>Fonts provided by application</Array> 把字体 ...