1、实验目的
(1)熟悉Linux的函数集;
(2)学习进程的消息通信
2、实验工具
PC机、Vmware station虚拟机软件、Ubuntu 16操作系统
3、实验步骤
<任务一>:
创建一个私有消息队列,一个进程自己发送消息和接收消息。将一个消息“hello,world”放入消息队列。再从消息队列进行接收,并打印出所接收的消息。
任务一程序:
结果:
显示错误:msgrcv:Argument list too long;
原因:报错Argument list too long错在使用msgsnd和msgrcv函数的时候,size_t msgsz 这个msgsz的大小双方不一致,msgsnd的长度大于了msgrcv的长度,所以就导致报错:Argument list too long
修改:
用ipcs指令查看发送来的数据消息的长度,
对代码进行修改,将MSG_SIZE的500换成1024,可以成功运行出结果。
任务一分析:
- 在一个代码中实现消息的接受和发送,创建结构体在结构体中定义一个长整型,一个数组,用于存放消息。接着创建进程,如果进程创建失败,输出“main’ msgget”,退出进程,重新创建,直到成功。进程创建成功时,输出the created message's id ='%d'.\n",queue_id;然后分派一个消息结构“hello world!”。将字符串复制到消息体中,发送消息;利用msgsnd函数读取消息,成功返回数据消息长度,失败返回负一,用加一标志字符串的结束。将消息占用的空间释放出来,输出提示词"message is placed on message's queue\n",准备接受消息;将接收到的消息输出;删除消息队列释放空间;结束进程。
- 函数里参数列表意思如下:
(1)smqid:消息队列的识别码.
(2)msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
(3)
- msgsz:消息的大小.
(4)msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息.
msgtyp大于0,则返回其类型为mtype的第一个消息.
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息.
(5)msgflg:用来指明核心程序在队列没有数据的情况下所应采取的行动.如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已 满,则msgsnd()将不会阻塞,而会立即返回-1,如果执行的是msgrcv(),则在消息队列呈空时,不做等待马上返回-1,并设定错误码为 ENOMSG.当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式.
(6)返回说明:
成功执行时,msgsnd()返回0,msgrcv()返回拷贝到mtext数组的实际字节数.失败两者都返回-1,errno被设为以下的某个值
<任务二>:
创建一个公共消息队列,实现客户进程和服务者进程之间进行通信。客户进程向服务者进程发送消息,请求服务。服务者进程接收消息,完成客户的服务请求后,再将服务结果以消息方式发送给客户。
服务者进程用关键字SVKEY和标志IPC_CREAT调用msgget()建立一个消息队列,得到其队列标识符msqid之后,用msqid调用msgrcv()接收类型为REQ的消息。
客户进程用关键字SVKEY调用msgget()得到消息队列标识符msqid,之后用msqid调用msgsnd()将自己的pid发送到消息队列(SVKEY)中,表示其所请求的服务。然后调用msgrcv()等待服务结果消息的到来。
服务者进程接收到请求服务的消息后进行服务工作,完成服务后向客户进程发回一条消息,消息的类型为客户的标识pid,消息正文是服务者进程自己的标识pid。
客户进程收到服务结果信息后,显示必要信息后,结束两者的通信过程。下面给出客户进程和服务者进程通信实例的源程序。
程序:
客户端:
服务器:
编译并且运行:
运行结果:
开启两个终端,一个充当客户端,一个充当服务器端
任务二分析:
客户端:创建结构体,用来存放消息,mtype 成员代表消息类型,从消息队列中读取消息的一个重要依据就是消息的类型;mtext 是消息的内容;首先预置一个缓冲区权限设置为任何人可读可写可执行。写入消息类型和内容;创建进程,如果进程创建成功,获取当前进程的标识,获取当前的消息队列的首地址;将客户进程的标识复制到消息缓存区;将消息发送到服务器。
服务器:创建结构体,用来存放消息,mtype 成员表示消息类型,mtext是消息的内容;权限设置为任何人可读可写可执行,获得客户进程的标识,同时将自己的标识发送给服务器;以便进行服务。首先分配这样一个缓冲区,然后将服务器的结果利用客户端的标识发送给客户端。服务器将结果读入缓冲区,输出结果,结束进程。
4、实验总结
在本次实验中我学到了如何在一个进程中创建新的消息队列然后将消息加入到队列中又从队列中拿出将结果输出。也学习了消息队列通过独立的方式对消息进行发送与接收。发送方充当客户端,接收方充当服务器;此时他们通过标识来识别对方的身份。在这个实验中我查询并学习了消息队列的一些特点:
- 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
- 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取, 也可以按消息的类型读取。消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列 ID)来标识。
在这次试验中我遇到了一些问题,代码在调试过程中一直报警告错误,加入的头文件没法利用;系统不存在这个头文件,然后通过查资料、问同学、百度之后发现在 root 用户下可以调试。