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

我们使用信号量,来解决进程或线程间共享资源引发的同步问题。

2.Linux中信号量的使用
Linux提供了一组信号量API,声明在头文件sys/sem.h中。
1)semget函数:新建信号量

int semget(key_t key,int num_sems,int sem_flags);

key:信号量键值,可以理解为信号量的唯一性标记。
num_sems:信号量的数目,一般为1
sem_flags:有两个值,IPC_CREATE和IPC_EXCL,
IPC_CREATE表示若信号量已存在,返回该信号量标识符。
IPC_EXCL表示若信号量已存在,返回错误。

返回值:相应的信号量标识符,失败返回-1

2)semop函数:修改信号量的值

int semop(int sem_id,struct sembuf *sem_opa,size_t num_sem_ops);

sem_id:信号量标识符
sem_opa:结构如下

struct sembuf{
short sem_num;//除非使用一组信号量,否则它为0
short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,
//一个是+1,即V(发送信号)操作。
short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,
//并在进程没有释放该信号量而终止时,操作系统释放信号量
};

3)semctl函数:用于信号量的初始化和删除

int semctl(int sem_id,int sem_num,int command,[union semun sem_union]);

command:有两个值SETVAL,IPC_RMID,分别表示初始化和删除信号量。
sem_union:可选参数,结构如下:

union semun{
int val;
struct semid_ds *buf;
unsigned short *arry;
};

一般用到的是val,表示要传给信号量的初始值。

3.Linux信号量使用示例
下例中,我们写了一个程序,程序中有一个char类型的字符,char message='x'
然后同时运行这个程序的两个实例。
第一个实例,带一个参数,将参数的第一个字符赋给message,比如为'0'
第二个实例,使用默认message值'x'
我们的目的是,使用信号量,循环执行这两个实例,
我们可以看到执行结果应该是'x0x0x0x0x0x0'

#include<stdio.h>
#include<stdlib.h>
#include<sys/sem.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int sem_id;
int set_semvalue()
{
union semun sem_union;
sem_union.val = ;
if(semctl(sem_id,,SETVAL,sem_union)==-)
return ;
return ;
}
int semaphore_p()
{
struct sembuf sem_b;
sem_b.sem_num = ;
sem_b.sem_op = -;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,)==-)
{
fprintf(stderr,"semaphore_p failed\n");
return ;
}
return ;
}
int semaphore_v()
{
struct sembuf sem_b;
sem_b.sem_num = ;
sem_b.sem_op = ;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,)==-)
{
fprintf(stderr,"semaphore_v failed\n");
return ;
}
return ;
}
void del_semvalue()
{
//删除信号量
union semun sem_union;
if(semctl(sem_id,,IPC_RMID,sem_union)==-)
fprintf(stderr,"Failed to delete semaphore\n");
}
int main(int argc,char *argv[])
{
char message = 'x';
//创建信号量
sem_id = semget((key_t),,|IPC_CREAT);
if(argc>)
{
//初始化信号量
if(!set_semvalue())
{
fprintf(stderr,"init failed\n");
exit(EXIT_FAILURE);
}
//参数的第一个字符赋给message
message = argv[][];
}
int i=;
for(i=;i<;i++)
{
//等待信号量
if(!semaphore_p())
exit(EXIT_FAILURE);
printf("%c",message);
fflush(stdout);
sleep();
//发送信号量
if(!semaphore_v())
exit(EXIT_FAILURE);
sleep();
}
printf("\n%d-finished\n",getpid());
if(argc>)
{
//退出前删除信号量
del_semvalue();
}
exit(EXIT_SUCCESS);
}

输出结果:

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

  1. Linux 信号量详解一

    信号量主要用于进程间(不是线程)的互斥,通过sem_p()函数加锁使用资源,sem_v函数解锁释放资源,在加锁期间,CPU从硬件级别关闭中断,防止pv操作被打断. semget函数 int semge ...

  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. C#语法问答式总结

    传入某个属性的set方法的隐含参数的名称是什么?value,它的类型和属性所声名的类型相同. 如何在C#中实现继承?在类名后加上一个冒号,再加上基类的名称. C#支持多重继承么?不支持.可以用接口来实 ...

  2. matlab求曲线长度

    曲线段在上的弧长为采用积分所求弧长s=∫√(1+y'²)dxmatlab求出各点的导数,然后按照上式积分 clear>> x=1:0.1:10;>> y=rand(1,leng ...

  3. ubuntu  输入时弹出剪切板候选项

    fcitx很坑的把这个功能的快捷键设置成了ctrl + ;结果我在用vim的时候怎么也 没法输入command 不知道是哪次更新引入的,简直是坑人! 我找了半天系统设置都没找到这个快捷键是在哪设置的. ...

  4. java语法学习问题总结

    No.1:EnumTest No.2:Addition 在此程序中,学习了将文本框调用出来,文本框输入的数据都是String类型,所以用于计算时需要先进行转型,然后计算. No.3:TestDoubl ...

  5. 作业5-需求分析(EX:南通大学成绩录入系统)

    产品利益相关者: 用户:南通大学各任课老师. 顾客:南通大学(教务处) 工程师:系统的开发,测试,维护,推广人员等 竞争性需求分析: N(需求) A(做法) B(好处) C(竞争) D(推广) 基础性 ...

  6. Android重写getResources规避用户调整系统字体大小影响Android屏幕适配

    Android屏幕适配一直是一个头疼的问题.除此之外还要考虑APP在实际应用场景中,用户千奇百怪的设置,最常见的用户设置行为就是设置手机的字体大小,比如把字体设置成超大或者超小,这对屏幕适配又带来额外 ...

  7. 怎么用jquery判断浏览器类型和版本号?

    用jquery判断浏览器类型:判断浏览器类型是IE浏览器还是火狐甚至是opera或者苹果浏览器safari,jquery 特效代码如下:判断浏览器类型和版本号如下: 怎么用jquery判断浏览器类型? ...

  8. 第二个Sprint冲刺第七天

    讨论地点:宿舍 讨论成员:邵家文.李新.朱浩龙.陈俊金 讨论:整理已完成的功能

  9. PHP 的snmp各个版本的Wrapper封装类

    原文来自:http://blog.chinaunix.net/uid-7654720-id-3211234.html class SNMP_Wrapper { protected $_host; pr ...

  10. Golang 交叉编译

    各平台的GOOS和GOARCH参考 OS ARCH OS version linux 386 / amd64 / arm >= Linux 2.6 darwin 386 / amd64 OS X ...