所谓信号量,其实就是一个数字。内核给这个数字赋予一定的含义,让它等于不同的值时所表示的意义不同。这样就可以用它来标示某种资源是否正被使用。信号的分类其实挺多的,主要还是二值和计数器。这里讨论二值

现在有个文件,有两个进程要同时访问它。进程A 要往里面写入 "Math class is cancel",进程B 要往里面写入“English test”。正常情况下这两个信息会被完整的写入文件中。但是如果进程A写到"Math class" 就暂停,接着B进程就开始写“English test”,最后进程A继续写剩下的“is cancel ”,那文件最后的结果就是“Math class English test is cancel”。结果显然错的离谱。究其错误的原因其实很简单,两个进程在同时公用一个资源但是又没有一种机制来控制访问的先后顺序。因为Linux 是一个多任务的系统,这中资源被多个任务同时访问的情况是非常普遍的。我们需要一种机制来控制资源能够被有序的访问。信号量就是一种实现。

信号量互斥的实现机制简单描述如下:

让两个进程在真正写入数据之前先测试信号量sig。当进程A要写入文件时,它先测试信号量sig,如果信号量sig 等于1,表示这个文件没有其他进程再使用,那么它就将这个信号量减1 让它等于0,接着直接写数据到这个文件。但是当进程B测试信号量sig 时发现它等于0 ,表示有进程在使用它,那么内核就让进程B挂起,当信号量的值被置为1时它才能继续执行写入操作。、

描述完信号量的机制就可以讨论Linux内核对于信号量的实现。

事实上linux内核关于信号量的接口还是很简洁的。就三个函数:

int semget(key_t key, int num_sems, int sem_flags);
int semop(int semid, struct sembuf *sops, size_t ops_num);

int semctl(int semid, int semnum, int command, ...);

semget函数

这个函数的功能是 创建/打开一个信号量集合,所谓集合其实就相当于数组。一个进程可能与多种资源相关联,可以用多个信号量来控制这些资源的访问。可见Linux 内核提供的信号量集合的概念是合理的。下面讨论它的参数和返回值:

返回值很简单,就是一个整型数----信号量标识符,标识符是内核为每个打开了的信号量集合而分配的,访问某个信号量集合就得靠它了(类比文件编程里的文件描述符)。key参数:键值。内核为所有的信号量集合维护了不同的键值,不管信号量集合是否被打开,这个键值都存在。键值其实就相当于文件名,但是键值是个整数,它可以自由指定,只是自由指定容易使得不同的信号量拥有相同的键值。因此内核提供了一个函数来分配键值:key_t ftok(const char *pathname, int proj_num);这个函数合成键值的机制简单描述下:

根据文件名pathname在内核中表示的数字以及proj_num共同合成一个键值key 并返回给调用者。num_sems参数:表明这个信号量集合的信号量个数。sem_flags参数:打开的标志,可以取值IPC_CREAT。当函数调用中有这个参数,并且键值指定的信号量集合不存在,那么这个函数就创建一个key 表示的信号量集合。

semop 函数

semop 函数用来信号量集合。事实上信号量集合的操作很简单,无非就是将信号量加一或者减一,来分别表示释放或者获取信号量。返回值除了表示操作的成败,没有什么意义。semid 参数:打开的信号量集合的标识符,从semget 返回。ops_num 参数:表示这个操作函数操作多少个信号量,因为信号量集合可能有多个信号量。 ops执行的结构体定义如下:

struct  sembuf

{

unsigned short   sem_num;//表明这个信号量在信号量集合中是哪一个

short       sem_op;     //表明操作类型    整数表明+1, 负数表明-1。事实上获取信号量和释放                                                    信号量就是在这里区别

short        sem_flg;

}

semctl 函数

semctl函数是在信号量上执行的多种操作。semid参数:表明要操作的信号量集合的标识符。semnum参数:表明要操作的信号量个数。command参数:表明要执行的命令。当我们要给信号量赋初值时可以令command == SETVAL,然后在省略参数给出要赋的值。

函数说明完了,下面给出一个简单的实例测试一下信号量互斥编程:

进程A:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>int main()
{int fd = 0;key_t key;int semid;struct sembuf sops;//创建并打开信号量key = ftok("/home",1);semid = semget(key,1,IPC_CREAT);semctl(semid,0,SETVAL,1);/* 0.打开公示栏*/fd = open("./board.txt",O_RDWR|O_APPEND);//获取信号量sops.sem_num = 0;sops.sem_op = -1;semop(semid,&sops,1);/* 1. 写入“数学课” */write(fd,"Math class",11);    /* 2. 暂停 */sleep(10);/* 3. 写入“取消”*/write(fd,"is cancel",10);//释放信号量sops.sem_num = 0;sops.sem_op = 1;semop(semid,&sops,1);    /* 4. 关闭公示栏 */close(fd);return 0;
}

View Code

进程B:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>int main()
{int fd = 0;key_t key;int semid;struct sembuf sops;   /* 0.打开公示栏 */fd = open("./board.txt",O_RDWR|O_APPEND);//打开信号量key = ftok("/home",1);semid = semget(key,1,IPC_CREAT);//获取信号量sops.sem_num = 0;sops.sem_op = -1;semop(semid,&sops,1);/* 1. 写入“英语课” */write(fd,"Enclish exam",13);//释放信号量sops.sem_num = 0;sops.sem_op = 1;semop(semid,&sops,1);      /* 2. 关闭公示栏 */close(fd);return 0;
}

View Code

转载于:https://www.cnblogs.com/linzizhang/p/4544794.html

Linux 信号量互斥编程相关推荐

  1. linux申请信号量,linux 信号量

    https://www.jianshu.com/p/6e72ff770244 无名信号量 只适合用于一个进程的不同线程 #include #include #include #include #inc ...

  2. linux 信号量锁 内核,Linux内核信号量互斥锁应用

    主要介绍了Linux 内核关于信号量,互斥锁等的应用 内核同步机制-信号量/互斥锁/读-写信号量 sema ,mutex ,rwsem 信号量 通用信号量 用户类进程之间使用信号量(semaphore ...

  3. 信号量 互斥量 条件变量

    原文:https://blog.csdn.net/qq_32646795/article/details/78221005 本文打算写一些和锁有关的东西,谈一谈我对锁的原理和实现的理解,主要包含以下方 ...

  4. 【linux草鞋应用编程系列】_3_ 进程间通信

    一.进程间通信        linux下面提供了多种进程间通信的方法, 管道.信号.信号量.消息队列.共享内存.套接字等.下面我们分别 介绍管道.信号量.消息队列.共享内存.        信号和套 ...

  5. Linux下C编程实战

    2019独角兽企业重金招聘Python工程师标准>>> Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于 ...

  6. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:     1 创建线程和结束线程:     2 读取和设置线程属性:     3 线程同步方式:POSIX信号量,互斥锁和条 ...

  7. linux c语言编程(转)

    linux操作系统下 c语言编程入门 整理编写:007xiong 原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设 ...

  8. ①Linux简明系统编程(嵌入式公众号的课)---总课时12h

    10.09 注意:这个是Linux高级编程的简明教程,是Linux应用程序的开发,而不是底层程序的开发. 内容是关于操作系统和网络编程的吗? Linux简明系统编程 〇.课程思维导图 〇.会用到的头文 ...

  9. linux下C编程详解

    linux操作系统下 c语言编程入门 整理编写:007xiong原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设计 ...

  10. 从入门到精通ARM(4412)-Linux内核驱动编程【下】-李志勇-专题视频课程

    从入门到精通ARM(4412)-Linux内核驱动编程[下]-247人已学习 课程介绍         嵌入式绝对是当前IT领域最炙手可热的话题了.其主要应用领域涵盖与人类相关的各行各业: * 消费电 ...

最新文章

  1. 解析并符号 读取dll_Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
  2. Exchange服务器系列课程之七--维护邮件服务器(二)
  3. Linux-profile、bashrc、bash_profile之间的区别和联系
  4. label自适应高度
  5. 洛谷1020导弹拦截
  6. Linux+nfs配置开机启动,linux NFS配置:NFS开机自动启用及其原理
  7. Repeater 得到checkbox值
  8. html调用python_HTML网页调用本地Python程序
  9. 查看文件md5_了解 | Mongodb 文件存储之 GridFs
  10. 如何在云中发掘僵尸网络?
  11. 防冲撞协议原理实验报告
  12. KK 的99 条额外的建议[翻译]#yyds干货盘点#
  13. linux opessl下载_linux安装openssl
  14. 文件包含漏洞及漏洞利用
  15. ffmpeg保存rtsp视频流为mp4文件
  16. Task运行过程分析2
  17. FlexRay 简介
  18. 基于Antd Input组件自定义Input的成功状态
  19. 硬盘分区出错提示磁盘结构损坏且无法读取怎么修复??
  20. cpu内存占用率都不高,电脑卡的问题

热门文章

  1. 享元模式在 Java Integer 中的应用
  2. Kafka负载均衡策略
  3. redis数据类型之hash入门
  4. 注册表添加 右键功能
  5. Zephyr在编译时将二进制文件转化成c语言数组
  6. vim怎么把一个写的代码文件另存到任意文件夹里?
  7. 解决Ubuntun 12.04编译 WARNING: 'automake1.12' is missing on your system
  8. 怎样增加Dave 英语学习小组
  9. 关于 Android Service 的介绍都在这了
  10. 为什要学习烹饪?学习烹饪迫在眉睫