Linux learning
- 1、引言
- 2、创建一个消息队列
- 3、发送和接受消息
- 3.1、发送消息
- 3.1、接收消息
- 4、删除一个消息队列
- 5、例程
1、引言
消息队列(message queue)也是进程之间通信的一种方式,相比于共享内存的通信方式,消息队列也有类型的运行机制,也是在多个进程之间开辟一个内存区域,让不同进程可以访问。由于消息队列其实是通过拷贝数据的方式来储存数据的,所以效率上比共享内存低,但优点在于消息队列可以通过函数来对内存中的数据进行排序等操作。
查看系统中是否存在消息队列,可以在终端中输入一下命令。
ipcs -q
2、创建一个消息队列
创建一个消息队列用到的函数是msgget(),其函数原型如下:
int msgget(key_t key, int msgflg);
可以在shell中输入”man 2 msgget“查看其更详细的信息。
- key:键值,可以由自己指定,也可以用ftok()函数生成,相当于给这个消息队列取一个独一无二的名字,以便于其他进程访问。
- msgflg:指定消息队列的权限。
- return:成功则返回消息队列的标识符,失败则返回-1。
3、发送和接受消息
3.1、发送消息
发送消息用的是msgsnd()函数,其原型如下:
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
- msgid:消息队列的id,其实就是msgget()函数的返回值。
- msg_ptr:存储消息的内存指针。这里要求必须是一个格式如下的结构体。
typedef struct
{
long mtype;
char mtext[8]; //数组的小大可以自己指定
}Msg_buf;
- msg_sz:上述结构体中mtext的长度。
- msgflg:指定在达到系统为消息队列限定的界限时应采取的操作。 Linux的官方说明书中有这样一段话。
If insufficient space is available in the queue, then the default behavior of msgsnd() is to block until space becomes available. If IPC_NOWAIT is specified in msgflg, then the call instead fails with the error EAGAIN.
即意味着,默认情况下,如果消息队列达到上限的时候,默认的操作是让该函数进入阻塞。而如果msgflg被设定为IPC_NOWAIT,则如果达到上限,那么直接抛出报错信息。
- return:成功则返回0,失败则返回-1。
3.1、接收消息
读取消息用到的函数是msgrcv(),其原型如下。
int msgrcv(int msgid, void *msg_ptr, size_t msgsz, long int msgtype, int msgflg);
- msqid:消息队列标识符,也是msgget的返回值。
- msg_ptr:指向用户自定义的缓冲区,也是指向一个结构与上文所诉一样的结构体。(但注意它和发送消息函数所用的结构体并不共享同一块内存)
- msgsz:也是指结构体中的mtext的长度。
- msgtype:指定请求的消息类型:
- msgtyp=0:收到的第一条消息,任意类型。
- msgtyp>0:收到的第一条msgtyp类型的消息。
- msgtyp<0:收到的第一条最低类型(小于或等于msgtyp的绝对值)的消息。
- msgflg:有两个选项可以选,IPC_NOWAIT和IPC_NOERROR。前者指示函数,没有消息则无需等待,返回ENOMSG的报错即可。后者指示函数,当个消息大小超过msgsz时,舍弃超出的部分。
- return:成功返回0,失败返回-1。
4、删除一个消息队列
删除一个消息队列用到了msgctl()函数,从msgctl英语全称应是message control也可以窥视到,该函数应当不仅仅只有函数消息队列一个功能。事实上,它可以对消息队列的基本属性进行控制、修改。其函数原型如下:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
- msqid:消息队列标识符,也是msgget的返回值。
- cmd:控制和修改消息队列。
- IPC_RMID:删除消息队列,立即生效。
- IPC_SET:设置消息队列的属性。
- IPC_STAT:读取消息队列的属性。
- IPC_INFO:读取消息队列的基本情况。
- buf:结构很复杂,作为初学者,我暂时不像深入学习。一般我用的时候直接设置为0即可。