建设银行官方网站是什么关键词搜索工具
1.system V消息队列
两个进程,进程A在OS中申请一块空间以队列形式,然后写入信息,这时进程B访问了这个队列,就可以看到写入的信息了,就说一个通信了,写入的信息以结构体形式,然后在队列中存储着,这个队列就叫消息队列,进程还可以创建多个消息队列,这样进需要对消息队列进行管理了,用链表形式把一个一个的消息队列串在一起,就可以进行维护了。然后俩个进程怎么保证看到的进程是否是同一个消息队列,是以key值来确定是否是同一个消息队列。
消息队列的调用接口
1.msgget创建或访问消息队列
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);
key:通过ftok函数生成的唯一键值
msgflg:标志位,常用的有IPC_CREAT(创建队列),IPC_EXCL(若队列已经存在则报错),和权限位
示例:
key_t key = ftok("/tmp", 'a'); // 生成一个唯一的键值
int msgid = msgget(key, IPC_CREAT | 0666); // 创建或访问消息队列
2.发生消息msgsnd
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg);
mssgid:通过msgget获取队列的消息队列标识符
msgp:指向消息缓冲区的指针
msgsz:消息的大小(注意不是结构体的大小,仅表示正文的大小)
msgflg:标志位,常用的有IPC_NOWAIT(非阻塞)
示例
struct msg_buffer {long msg_type;char msg_text[100];
};struct msg_buffer message;
message.msg_type = 1; // 消息类型
strcpy(message.msg_text, "Hello, Message Queue!");msgsnd(msgid, &message, sizeof(message), 0); // 发送消息
3.接受消息msgrcv
#include <sys/ipc.h>
#include <sys/msg.h>ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgid:消息队列标识符
msgp:指向消息缓冲区的指针
msgsz:缓冲区的大小
msgtyp:要接受的消息类型
msgflg:标志位,常用的有IPC_NOWAIT
示例
struct msg_buffer message;
msgrcv(msgid, &message, sizeof(message), 1, 0); // 接收消息类型为1的消息
4.控制消息队列msgctl
对消息队列进行控制操作,如获取状态,设置属性或删除队列
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msgid, int cmd, struct msqid_ds *buf);
msgid:消息队列标识符
cmd:操作命令,常用的有IPC_STAT(获取队列状态),IPC_SET(设置队列属性)和IPC_RMID(删除队列)
buf:指向msqid_ds结构的指针,用于存储或修改队列的属性
示例
struct msqid_ds mqs;
msgctl(msgid, IPC_STAT, &mqs); // 获取消息队列的状态
msgctl(msgid, IPC_SET, &mqs); // 设置消息队列的属性
msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
msgid_ds 结构体代码
消息队列的生命周期
消息队列的生命周期不会随进程的结束而关掉,需要手动执行关闭消息队列释放资源。
2.并发编程
多个执行流(进程),能看到同一份公共资源:公共资源
被保护的资源就叫临界资源
被保护的方式:互斥和同步(互斥是任何时刻只允许一个执行流访问资源,同步是多个执行流访问临界资源时,具有一定的顺序性)
系统中某些资源一次只允许一个进程使用,这样的资源为临界资源或者互斥资源
在进程中,涉及到互斥资源的程序段叫临界区,我们写的代码=访问临界资源的代码(临界区)+不访问临界资源的代码(非临界区)
所谓的对共享资源进行保护,本质是对访问共享资源的代码进行保护。
例子
我们要去银行存钱,就需要进到里面的小屋子里面,首先就要把们打开,再能进去存,存完后再出来,门有锁,所以这个过程是不会被被干扰的,只有当你把钱存进去后,把门打开,别人才能进去,这就是原子性,保证任务完成不被干扰。
3.信号量
信号量:是一个计数器
只用方面:保护临界区
本质方面:信号量本质是对资源的预订机制
操作方面:申请资源,计数器--,P操作;释放资源,计数器++,V操作
例子
去电影买票,不是坐到这个位置,这个位置就是你的,而是买了票,票上面的号码就表示着对于号码的位置是你的,在电影开始到播放结束之间,这个位置都是你的,不管你去不去看电影,买票就是对资源的预定机制。sem表示有16个位置,那么又有人要看就只能阻塞等待,直到下一个电影开始了。
特殊情况
有svip的影院,只能一个人看,信号量是1,这样就是互斥的现象了,你看完了,才到下一个人,一次使用一整块资源。
信号量是计数器,描述的是临界资源中,资源数量的多少,就像一个电影院能出售多少个位置一样,所有的进程,访问临界资源中的一小块,就必须先申请信号量,看电影就必须要买票一样,进程访问资源前,先申请信号量,本质是:是对资源的预订机制。预定的资源,即便不使用,其它进程也不能使用这块资源。
信号量调用接口
POSIX信号量接口
1.sem_init初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
-
sem
:指向信号量的指针。 -
pshared
:指定信号量是否在进程间共享(非零值表示共享)。 -
value
:信号量的初始值。 -
返回值:成功返回0,失败返回-1。
2.sem_wait等待信号量
int sem_wait(sem_t *sem);
-
sem
:指向信号量的指针。 -
功能:如果信号量值大于0,则减1并返回;否则阻塞,直到信号量值大于0
3.sem_post释放信号量
int sem_post(sem_t *sem);
-
sem
:指向信号量的指针。 -
功能:将信号量值加1,并唤醒等待该信号量的线程。
4.sem_destory销毁信号量
int sem_destroy(sem_t *sem);
-
sem
:指向信号量的指针。 -
功能:释放信号量占用的资源。
system V信号量接口
1.semget创建或获取信号量
int semget(key_t key, int nsems, int semflg);
-
key
:通过ftok
生成的唯一键值。 -
nsems
:信号量集中的信号量数量。 -
semflg
:标志位,常用的有IPC_CREAT
(创建信号量集)和权限位(如0666
)。
2.semop对信号量进行操作(P,V操作)
int semop(int semid, struct sembuf *sops, size_t nsops);
-
semid
:信号量集的标识符。 -
sops
:指向sembuf
结构数组的指针,定义了要执行的操作。 -
nsops
:sops
数组的大小。
3.semctl对信号量进行控制操作
int semctl(int semid, int semnum, int cmd, ...);
-
semid
:信号量集的标识符。 -
semnum
:信号量的编号。 -
cmd
:操作命令,常用的有IPC_RMID
(删除信号量集)、IPC_SET
(设置信号量属性)和IPC_STAT
(获取信号量状态)。
信号量集合 是由多个信号量组成的一个数组。每个信号量都是一个计数器,用于控制对共享资源的访问。
在 System V信号量 中,信号量集合允许一次申请多个信号量,并且这些信号量可以一起被管理。
信号量结构体代码
总结
共享内存,消息队列和信号量都用key来区分唯一,OS中,共享内存,消息队列和信号量被当成同一种资源。
结构图
ipc_id_ary里有一个柔性数组,里面存储的是不同通信的形式,msg_queue,shnid_kernel和sem_arry的首元素都是perm指向一个结构体,开头都是一样的,则就可以用数组管理起来了,以多态的形式,头一样其余的不同,就像继承一样,把共同的继承下来了,又有不一样的东西存在。
shmid之所以是一个整数,因为是下标来访问数组元素的,对于的就是共享内存,消息队列和信号量三种之一的通信方式。