各位看官们,大家好,上一回中咱们说的是使用共享内存进行进程间通信的例子,这一回咱们说的例子是:使用消息队列进行进程间通信。闲话休提,言归正转。让我们一起talk C栗子吧!
消息队列是SystemV IPC结构这种抽象概念的一种具体对象,这点和共享内存一样。消息队列提供了一个队列供不同的进程使用,进程之间可以通过该队列传递数据,进而实现进程间的通信。
在介绍消息队列的使用方法之前,我们先介绍几个函数,这些函数都是用来操作消息队列的。
msgget函数
int msgget(key_t key,int msgflag)
该函数用来创建一个新的消息队列或者获取已经存在的消息队列。
- 第一个参数是键值,通过它来操作IPC在内核中的结构,也就是消息队列在内核中的结构;(前面章回中介绍过)
- 第二个参数是消息队列的权限标记,该权限和文件权限一样;
- 该函数运行成功时返回消息队列标识符,否则返回-1;我们可以通过该标识符使用消息队列;
msgsnd函数
int msgsnd(int msg_id, const void *msg_ptr,size_t msg_sz,int msgflg)
该函数用来把消息添加到消息队列中,这样进程就可以从消息队列中获取消息了;
在使用该函数的时候,我们需要自己定义一个消息的类型,并且计算出该类型的内存空间。消息的类型可以依据程序需要来定义,常见的是定义一个结构体类型。不过类型中的第一个成员必须是一个long int类型的成员,该成员用来确定消息的类型。
- 第一个参数是消息队列的标识符,通过msgget函数可以获得;
- 第二个参数是一个指针,该指针指向准备添加到消息队列中消息;
- 第三个参数是一个int类型的值,表示准备添加到消息队列中消息的大小;
- 第四个参数是一个位标记,该标记用来控制消息队列已满或者达到系统限制时的动作。
- 该函数运行成功时返回0,否则返回-1;
在使用该函数的时候,第四个参数通常为IPC_NOWAIT,表示消息队列已满后函数不发消息到消息队列中,并且立刻返回-1.如果没有设置该标记,那么消息队列已满后先把以送消息的进程挂起,直到消息到消息队列中有空间了,它再发送消息到消息队列中。
msgrcv函数
int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg)
该函数用来从消息队列中获取消息或者说接收消息;
- 第一个参数是消息队列的标识符,通过msgget函数可以获得;
- 第二个参数是一个指针,该指针指向准备从消息队列中获取的消息;
- 第三个参数是一个int类型的值,表示获取消息的大小;
- 第四个参数是一个long int类型的值,表示接收消息的优先级;
- 第五个参数是一个位标记,该标记用来控制消息队列中没有消息供接收时的动作。
- 该函数运行成功时返回接收到消息的字节数,否则返回-1;
在使用该函数数,第五个参数的值和msgsnd函数中第四个参数的值一样,而且函数的动作也类似,只不过从发送消息转换为接收消息。该函数的第四个参数通常为0,表示按照消息的发送顺序接收消息;
如果它的值为n(n>0),表示接收类型值为n的这一类消息;
如果它的值为-n(n>0),表示接收类型值为等于或者小于n的这一类消息;
这里说的类型值就是我们定义消息类型中的第一个成员。
msgctl函数
int msgctl(int msg_id, int cmd,struct msgid_ds *buf)
该函数用来对消息队列进行相关操作,常用的操作是删除消息队列;
- 第一个参数是消息队列的标识符,通过msgget函数可以获得;
- 第二个参数是一个命令,表示对消息队列的操作,只有三个命令供使用:IPC_STAT,IPC_SET和IPC_RMID;
- 第三个参数是一个结构体指针,该结构体中有消息队列的权限和所有者等信息;
- 该函数运行成功时返回0,否则返回-1;
我们通常使用该函数删除消息队列,这时候需要给第二个参数赋值为IPC_RMID,表示删除消息队列,第三参数可以为空指针。第二个参数的另外两个命令:IPC_STAT表示把第三个参数中的内容和消息队列关联起来;IPC_SET表示把第三个参数中的内容设置为消息队列的值。第三个参数的类型,我们在前面章回中提起过,它和SystemV IPC的结构类似,除了必须有的成员外,它还有自己特有的成员。
该函数的用法和咱们在前面章回中介绍过的shmctl函数用法类似,大家可以进行对比。
我从源代码中找到了第三个参数的类型,详细的定义如下:(位于linux-4.0.3/include/linux/msg.h文件中)
struct msg_queue {
struct kern_ipc_perm q_perm;
time_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */
unsigned long q_cbytes; /* current number of bytes on queue */
unsigned long q_qnum; /* number of messages in queue */
unsigned long q_qbytes; /* max number of bytes on queue */
pid_t q_lspid; /* pid of last msgsnd */
pid_t q_lrpid; /* last receive pid */
struct list_head q_messages;
struct list_head q_receivers;
struct list_head q_senders;
};
各位看官,关于使用消息队列进行进程间通信的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。