unix/linux进程间的通信------消息队列

本文详细介绍了Unix/Linux系统中使用消息队列进行进程间通信的方法,包括消息队列的结构、相关函数如msgget、msgsnd、msgrcv和msgctl的用法,以及一个简单的客户端-服务器端交互示例。
摘要由CSDN通过智能技术生成

        本文主要探讨unix/linux间的一种通信方式———消息队列。

消息队列的简介

        消息队列是一个链表,保存在内核中,通过消息队列的引用标识符来访问。只有重启内核(重启操作系统)或显示地删除一个消息队列时,该消息队列才会被删除。

消息对列相关函数   

        消息形式    

struct  msgbuf
{
    long  mtype;
    char  mcontext[n];
};

               参数

                        mtype:消息类型

                        mcontext:消息内容

        内核数据结构

Struct msqid_ds {
	struct           ipc_perm msg_perm;		/*所有权和权限*/
	time_t           msg_stime;		        /*上一次发送时间 */
	time_t           msg_rtime;		        /*最后接收时间*/
	time_t           msg_ctime;		        /*上次修改时间*/
	unsigned long 	 __msg_cbytes;	        /*当前输入的字节数队列*/
	msgqnum_t	     msg_qnum;	            /*当前消息数在队列中*/
	msglen_t	     msg_qbytes;		    /*最大字节数允许在队列*/
	pid_t            msg_lspid;		        /*上一次发送的PID  */
	pid_t            msg_lrpid;		        /*上一次接收的PID */
};
struct ipc_perm {
	key_t           __ key;		/*提供给键值*/
	uid_t           uid;		/*所有者的有效UID */
	gid_t           gid;		/* 所有者的有效GID */
	uid_t           cuid;		/*创建者的有效UID */
	gid_t           cgid;		/*创建者的有效GID */
	unsigned short mode;        /*权限*/
	unsigned short __seq;	    /*序列号*/
};

        消息队列键值

key_t ftok(const char *pathname, int proj_id);

                参数                   

                        pathname:存在且程序范围的文件

                        proj_id参数:整数,只有8个bit位有效,大于255,后8bit有效

               返回值

                        成功执行返回键值,失败返回-1

        消息队列创建        

int msgget(key_t key, int msgflg);

               参数

                        key:

                                键值,由ftok()函数创建,或自定义。

                                0(IPC_PRIVATE):会建立新的消息队列。

                        msflg:

                                 0:取消息队列标识符,若不存在则函数会报错
                                 IPC_CREAT:当msgflg&IPC_CREAT为真时,无key消息队列,则新建;如果存

                                 在,返回消息队列的标识符
                                 IPC_CREAT|IPC_EXCL:无key消息队列,则新建;如果存在,则报错

                返回值

                        成功执行返回消息队列标识符,失败返回-1

        消息队列发送

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

                参数

                        msqid:消息队列标识符

                        msgp:发送消息的内容

                        msgsz:消息内容的大小,不包含消息类型所占的4个字节

                        msgflg:

                                    0:队列满时,msgsnd将会阻塞,直到消息能写进消息队列
                                    IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回
                                    IPC_NOERROR:消息大于size字节,则消息截断,截断部分被丢弃,且不

                                     通知发送进程。

                 返回值

                        成功执行返回0,失败返回-1

        消息队列的接收

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

                 参数

                        msqid:消息队列标识符               

                        msgp:接收消息的内容

                        msgsz:接收消息内容的大小,不包含消息类型所占的4个字节

                        msgtype:
                                         0:接收第一个消息
                                        >0:接收类型等于msgtyp的第一个消息
                                        <0:接收类型等于或者小于msgtyp绝对值的第一个消息
                        msgflg:
                                        0: 阻塞式接收消息,没有该类型的消息msgrcv阻塞
                                        IPC_NOWAIT:如果没有返回条件的消息调用立即返回
                                        IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype

                                        的消息
                                        IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字

                                        节,则把该消息截断,截断部分将被丢弃 

                 返回值

                          成功执行返回消息大小,失败返回-1 

                消息队列的属性设置和获取       

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

                   参数

                            msqid:消息队列标识符

                            cmd:

                                        IPC_STAT:将与msqid关联的内核数据结构中的信息复制到buf所指向的

                                        msqid_ds结构中。调用方必须对消息队列具有读权限。(获取)

                                        IPC_SET:将buf所指向的msqid_ds结构的某些成员的值写入与之相关的内

                                        核数据结构消息队列。(设置)

                                        IPC_RMID:删除消息队列,(NULL)

                    返回值

                                成功返回0,失败返回-1

demo:       

                1.编写server端先接收消息,再发送消息tank you

                 2.编写client端先发送消息hello,再接收消息

                server:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct msgbuf 
{
        long mtype;
        char context[10];
};

void result()
{
        key_t key;
        int msqid;
        struct msgbuf to_client = {889,"thanks"};
        struct msgbuf from_client;
        key = ftok(".",127);
        if(key  == -1)
        {
                printf("create key fail\n");
                perror("why");
                exit(-1);
        }
        msqid = msgget(key,IPC_CREAT|0666);
        if(msqid == -1)
        {
                printf("create message queue fail\n");
                perror("why");
                exit(-1);

        }
        msgrcv(msqid,&from_client,sizeof(from_client.context),888,0);
        printf("from client type :%ld ,from client context: %s\n",from_client.mtype,from_client.context);
        msgsnd(msqid,&to_client,sizeof(to_client.context),0);
}

int main()
{
        result();
        return 0;
}

                client:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct msgbuf 
{
        long mtype;
        char context[10];
};

void result()
{
        key_t key;
        int msqid;
        struct msgbuf to_server = {888,"hello"};
        struct msgbuf from_server;
        key = ftok(".",127);
        if(key  == -1)
        {
                printf("create key fail\n");
                perror("why");
                exit(-1);
        }
        msqid = msgget(key,IPC_CREAT|0666);
        if(msqid == -1)
        {
                printf("create message queue fail\n");
                perror("why");
                exit(-1);

        }
        msgsnd(msqid,&to_server,sizeof(to_server.context),0);
        msgrcv(msqid,&from_server,sizeof(from_server.context),889,0);
        printf("from server type :%ld ,from server context: %s\n",from_server.mtype,from_server.context);
}

int main()
{
        result();
        return 0;
}

结果示例:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值