1 / 17

进程通信

进程通信. 中科大软件学院. 消息队列. 消息队列提供了一种 由一个进程向另一个进程发送块数据的方法 。另外,每一个数据块被看作有一个类型,而接收进程可以独立接收具有不同类型的数据块。 消息队列定义如下: #include <sys/msg.h> int msgget (key_t key, int msgflg); int msgrcv (int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);

liluye
Download Presentation

进程通信

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 进程通信 中科大软件学院

  2. 消息队列 • 消息队列提供了一种由一个进程向另一个进程发送块数据的方法。另外,每一个数据块被看作有一个类型,而接收进程可以独立接收具有不同类型的数据块。 • 消息队列定义如下: • #include <sys/msg.h> • int msgget(key_t key, int msgflg); • int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg); • int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg); • int msgctl(int msqid, int cmd, struct msqid_ds *buf);

  3. msgget()函数 创建或访问一个消息队列,系统调用msgget()中的第一个参数是关键字值(通常是由ftok()返回的)。这时,打开和存取操作是和参数msgflg中的内容相关的。

  4. msgget()函数 • 实例: • if((key=ftok(".",'a'))==-1){ • perror("ftok"); • exit(1);} •     qid=msgget( key, IPC_CREAT | 0666 );       /*创建一个消息队列*/ •     if ( qid < 0 ) {   /* 创建一个消息队列失败 */ •         perror ( "msgget" ); •         exit (1) ; •     } •   printf ("created queue id : %d \n", qid );  /* 输出消息队列的ID */

  5. msgget()函数 • key_t ftok( char * fname, int id ) • fname为指定的文件名 • id为子序号 • 实例: • if((key=ftok(".",'a'))==-1){ • perror("ftok"); • exit(1); • }

  6. msgget()函数

  7. msgget()函数 • msgget( key, IPC_CREAT | 0666 ); • 第二位:当前用户的权限:6=110(二进制),每一位分别对应可读,可写,可执行,,6说明当前用户可读可写不可执行 • 第三位:group组用户,6的意义同上 • 第四位:其它用户,每一位的意义同上,0表示不可读不可写也不可执行

  8. 读写消息队列 • 系统为这个数据类型提供了两个接口(msgsnd函数,msgrcv函数),分别对应写消息队列及读消息队列。将一个新的消息写入队列,使用函数msgsnd,函数原型如下: • #include <sys/msg.h> • int msgsnd ( int msqid, const void *prt, size_t nbytes, int flags); • int msgrcv ( int msqid, struct msgbuf *ptr, size_t nbytes, long type , int flag);

  9. 读写消息队列 • 每个消息都类似如下的数据结构: • struct msgbuf • { • long mtype; • char mtext[1]; • }; • struct msgbuf { long mtype; char mtext[1]; }; • mtype成员代表消息类型,从消息队列中读取消息的一个重要依据就是消息的类型;mtext是消息内容,当然长度不一定为1。因此,对于发送消息来说,首先预置一个msgbuf缓冲区并写入消息类型和内容,调用相应的发送函数即可;对读取消息来说,首先分配这样一个msgbuf缓冲区,然后把消息读入该缓冲区即可。 • 以下为一读取消息队列实例:

  10. 发送方: • struct msg{ /*声明消息结构体*/ • long msg_types; /*消息类型成员*/ • char msg_buf[511]; /*消息*/ • }; • int main( void ) { • int qid; • int pid; • int len; • struct msg pmsg; /*一个消息的结构体变量*/ • pmsg.msg_types = getpid(); /*消息类型为当前进程的ID*/ • sprintf (pmsg.msg_buf,"hello!this is :%d\n\0", getpid() ); /*初始化消息*/ • len = strlen ( pmsg.msg_buf ); /*取得消息长度*/ • if ( (qid=msgget(IPC_PRIVATE, IPC_CREAT | 0666)) < 0 ) { /*创建一个消 • 息队列*/ • perror ( "msgget" ); • exit (1) ; • } • if ( (msgsnd(qid, &pmsg, len, 0 )) < 0 ){ /*向消息队列中发送消息*/ • perror ( "msgsn" ); • exit ( 1 ); • } • printf ("successfully send a message to the queue: %d \n", qid); • exit ( 0 ) ; • }

  11. 接收方: • struct msg{ /*声明消息结构体*/ • long msg_types; /*消息类型成员*/ • char msg_buf[511]; /*消息*/ • }; • int main( int argc, char * argv[] ) { • int qid; • int len; • struct msg pmsg; • if ( argc != 2 ){ /**/ • perror ( "USAGE: read_msg <queue ID>" ); • exit ( 1 ); • } • qid = atoi ( argv[1] ); /*从命令行中获得消息队列的ID*/

  12. /*从指定队列读取消息 */ • len = msgrcv ( qid, &pmsg, BUFSZ, 0, 0 ); • if ( len > 0 ){ • pmsg.msg_buf[len] = '\0'; /*为消息添加结束符*/ • printf ("reading queue id :%05ld\n", qid ); /*输出队列ID*/ • /*该消息类型就是发送消息的进程ID*/ • printf ("message type : %05ld\n", pmsg.msg_types ); • printf ("message length : %d bytes\n", len ); /*消息长度*/ • printf ("mesage text: %s\n", pmsg.msg_buf); /*消息内容*/ • } • else if ( len == 0 ) • printf ("have no message from queue %d\n", qid ); • else { • perror ( "msgrcv"); • exit (1); • } • system("ipcs -q") ; • exit ( 0 ) ; • }

  13. 读写消息队列

  14. msgctl()函数 • 函数msgctl可以在队列上做多种操作,函数原型如下: • #include <sys/msg.h> • int msgctl( int msqid, int cmd , struct msqid_ds *buf ); • 参数msqid为指定的要操作的队列,cmd参数指定所要进行的操作,其中有些操作需要buf参数。cmd参数的详细取值及操作如下:

  15. msgctl()函数

  16. msgctl()函数 • 删除消息队列: • int main ( int argc ,char *argv[] ) • { •     int qid ;    •     if ( argc != 2 ){ /* 命令行参数出错 */ •         puts ( "USAGE: del_msgq.c <queue ID >" ); •         exit ( 1 ); •     } •     qid = atoi ( argv[1] ); /* 通过命令行参数得到组ID */ •     system( "ipcs -q"); •     if ( ( msgctl( qid, IPC_RMID, NULL ) ) < 0 ){ /* 删除指定的消息队列 */ •         perror ("msgctl"); •         exit (1 ); •     } •     exit( 0 ); • }

  17. 实验内容 • 用消息队列实现的简单聊天程序 • 实验报告提交内容: • 1、程序流程图 • 2、程序代码 • 3、运行结果 • 接收作业邮箱:chenbo2008@ustc.edu.cn

More Related