行业知识
Linux信号【systemV】
���录
前言
正文:
1消息队列
1.1什么是消息队列?
1.2消息队列的数据结构
1.3消息队列的相关接口
1.3.1创建
1.3.2释放
1.3.3发送
1.3.4接收
1.4消息队列补充
2.信号量
2.1什么是信号量
2.2互斥相关概念
2.3信号量的数据结构
2.4信号量相关接口
2.4.1创建
2.4.2释放
2.4.3操作
2.5信号量补充
3.深入理解 System V通信方式
总结:
前言
在 System V 通信标准中,还有一种通信方式:消息队列,以及一种实现互斥的工具:信号量;随着时代的发展,这些陈旧的标准都已经较少使用了,但作为 IPC 中的经典知识,我们可以对其做一个简单了解,扩展 IPC 的知识栈,尤其是 信号量,可以通过它,为以后多线程学习中 POSIX 信号量的学习做铺垫
正文:
1消息队列
1.1什么是消息队列?
消息队列(Message Queuing)是一种比较特殊的通信方式,它不同于管道与共享内存那样借助一块空间进行数据读写,而是 在系统中创建了一个队列,这个队列的节点就是数据块,包含类型和信息
- 假设现在进程 A、B 想要通过消息队列进行通信,首先创建一个消息队列
- 然后进程 A 将自己想要发送给进程 B 的信息打包成数据块(其中包括发送方的信息),将数据块添加至消息队列队尾处
- 进程 B 同样也可以向消息队列中添加数据块,同时也会从消息队列中捕获其他进程的数据块,解析后进行读取,这样就完成了通信
遍历消息队列时,存数据块 还是 取数据块 取决于 数据块中的类型 type
注意: 消息队列跟共享内存一样,是由操作系统创建的,其生命周期不随进程,因此在使用结束后需要删除
下面有关于消息队列详解的文章
- 《什么是消息队列》
- 《消息队列详解》
1.2消息队列的数据结构
同属于 System V 标准,消息队列也有属于自己的数据结构
注:msg 表示 消息队列
struct msqid_ds{struct ipc_perm msg_perm;/* Ownership and permissions */time_t msg_stime;/* Time of last msgsnd(2) */time_t msg_rtime;/* Time of last msgrcv(2) */time_t msg_ctime;/* Time of last change */unsigned long __msg_cbytes; /* Current number of bytes in queue (nonstandard) */msgqnum_t msg_qnum;/* Current number of messages in queue */msglen_t msg_qbytes;/* Maximum number of bytes allowed in queue */pid_t msg_lspid;/* PID of last msgsnd(2) */pid_t msg_lrpid;/* PID of last msgrcv(2) */};和 共享内存 一样,其中 struct ipc_perm 中存储了 消息队列的基本信息,具体包含内容如下:
struct ipc_perm{key_t __key; /* Key supplied to msgget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions */unsigned short __seq; /* Sequence number */};可以通过 man msgctl 查看函数使用手册,其中就包含了 消息队列 的数据结构信息
1.3消息队列的相关接口
论标准的重要性,消息队列的大小接口风格与共享内存一致,都是出自 System V 标准
1.3.1创建
使用 msgget 函数创建 消息队列
#include #include #include int msgget(key_t key, int msgflg);
关于 msgget 函数
与 共享内存 的 shmget 可以说是十分相似了,关于 ftok 函数计算 key 值,这里就不再阐述,可以在这篇文章中学习 《Linux进程间通信【共享内存】》
简单使用函数 msgget 创建 消息队列,并使用 ipcs -q 指令查看资源情况
#include #include #include #include using namespace std;int main(){ //创建消息队列 int n = msgget(ftok("./", 668), IPC_CREAT | IPC_EXCL | 0666); if(n == -1) { cerr 0 */ char mtext[1]; /* message data */};1.4消息队列补充
System V 版的 消息队列 使用起来比较麻烦,并且过于陈旧,现在已经较少使用了,所以我们不必对其进行深究,知道个大概就行了,如果实际中真遇到了,再查文档也不迟
2.信号量
2.1什么是信号量
信号量(semaphore)一种特殊的工具,主要用于实现 同步和互斥
信号量 又称 信号灯,是各大高校《操作系统》课程中老师提及的高频知识点,往往伴随着 P、V 操作出现,但大多数老师都只是提及了基本概念,并未对 信号量 的本质及使用场景作出详细讲解
在正式学习 信号量 相关知识前,需要先简单了解下 互斥相关四个概念,为后续 多线程中信号量的学习作铺垫(重点)
2.2互斥相关概念
1、并发 是指系统中同时存在多个独立的活动单元
- 比如在多线程中,多个执行流可以同时执行代码,可能访问同一份共享资源
2、互斥 是指同一时刻只允许一个活动单元使用共享资源
- 即在任何一个时刻,都只允许一个执行流进行共享资源的访问(可以通过加锁实现)
3、临界资源 与 临界区,多执行流环境中的共享资源就是 临界资源,涉及 临界资源 操作的代码区间即 临界区
- 在多线程环境中,全局变量就是 临界资源,对全局变量的修改、访问代码属于 临界区
4、原子性:只允许存在 成功 和 失败 两种状态
- 比如对变量的修改,要么修改成功,要么修改失败,不会存在修改一半被切走的状态
所以 互斥 是为了解决 临界资源 在多执行流环境中的并发访问问题,需要借助 互斥锁 或 信号量 等工具实现 原子操作,实现 互斥
关于互斥锁(mutex) 的相关知识在 多线程 中介绍,现在先来学习 信号量,搞清楚它是如何实现 互斥 的
2.3信号量的数据结构
下面来看看 信号量 的数据结构,通过 man semctl 进行查看
sem 表示 信号量
struct semid_ds{ struct ipc_perm sem_perm; /* Ownership and permissions */ time_t sem_otime; /* Last semop time */ time_t sem_ctime; /* Last change time */ unsigned long sem_nsems; /* No. of semaphores in set */};System V 家族基本规矩,struct ipc_perm 中存储了 信号量的基本信息,具体包含内容如下:
struct ipc_perm{ key_t __key; /* Key supplied to semget(2) */ uid_t uid; /* Effective UID of owner */ gid_t gid; /* Effective GID of owner */ uid_t cuid; /* Effective UID of creator */ gid_t cgid; /* Effective GID of creator */ unsigned short mode; /* Permissions */ unsigned short __seq; /* Sequence number */};显然,无论是 共享内存、消息队列、信号量,它们的 ipc_perm 结构体中的内容都是一模一样的,结构上的统一可以带来管理上的便利,具体原因可以接着往下看
2.4信号量相关接口
2.4.1创建
信号量的申请比较特殊,一次可以申请多个信息量,官方称此为 信号量集,所使用函数为 semget
#include #include #include int semget(key_t key, int nsems, int semflg);
关于 semget 函数
除了参数2,其他基本与另外俩兄弟一模一样,实际传递时,一般传 1,表示只创建一个 信号量
使用函数创建 信号量集,并通过指令 ipcs -s 查看创建的 信号量集 信息
#include #include #include #include using namespace std;int main(){ //创建一个信号量 int n = semget(ftok("./", 668), 1, IPC_CREAT | IPC_EXCL | 0666); if(n == -1) { cerr
- 比如对变量的修改,要么修改成功,要么修改失败,不会存在修改一半被切走的状态
- 在多线程环境中,全局变量就是 临界资源,对全局变量的修改、访问代码属于 临界区
- 即在任何一个时刻,都只允许一个执行流进行共享资源的访问(可以通过加锁实现)
- 比如在多线程中,多个执行流可以同时执行代码,可能访问同一份共享资源
上一篇:服务器代理ip费用怎么算?
下一篇:怎么检查主机电源是否通电