消息队列和信号量集合同样作为进程间通信的重要手段,是LInux编程必需理解的内容,但两者类似的操作和文件结构让很多人不能理解其中的原理。下面我来介绍下我的理解:
在使用消息队列和信号量集合前都必须使用的一个函数
Key_t ftok(char *pathname,char proj),
其功能是:根据文件名(包含路径)和项目名返回对应键值key,留作创建消息队列的参数(
这里可以理解为同一个文件可以有多个项目,每个项目的key值都不同
),学习这个函数时,就应该搞懂该函数的第二个参数项目名,这表明同样一个文件可以有不同的项目,当然对应的返回值key也就不一样了。
创建或打开消息队列函数
msgget(key_t key, int msgflg)
,这时传入key值即可返回对应的消息队列描述符。之后想在该消息队列中发送消息,使用
msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg)
,参数里的结构体
struct msgbuf
{
Long mtype; //
消息类型
>0
Char mtext[1]; //
消息队列的首地址
}
表明你的每个消息必须有一个消息类型,(
可以把一个消息类比成结构体,或者说python中的字典更为确切
),总而言之就是消息内容前有一个long型的类型表明消息名称。
而想要获取信号量也是类似的操作,首先通过
semget(key_ key ,int nsems, int semflg)
得到对应的信号量集合描述符,所以信号量集合和消息队列其实是一个重量级的东西。不过需要注意的是函数中的第二个参数表明在创建打开信号量集合时,必须确定信号量集合包含的信号量个数。这不同于创建消息队列。之后的操作函数
semop(int semid ,struct sembuf*sops,unsigned nsops)
中也有一个类似于消息队列中
struct msgbuf
的结构体
struct sembuf{
unsigned short sem_num;
信号量在信号量集合中的索引,第一个为
0
;
short sem_op;
信号量操作
-+1
,获取还是释放
short sem_flg;
操作标志,取值
IPC_NOWAIT
:对信号的操作不能满足时,
semop()
不会阻塞,并立即返回,同时设定错误信息。
IPC_UNDO:
程序结束时(无论正常或不正常)释放信号量,这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成资源永远锁定。
}
其中的
sem_num
其实和
struct msgbuf
中的type是一样的作用,用来表明操作那个信号量或消息。
最后画了一张图可以清晰的看出我所述的逻辑
,如下: