Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "进程通信 中科大软件学院. 消息队列 消息队列提供了一种由一个进程向另一个进程发送块数据 的方法。另外,每一个数据块被看作有一个类型,而接收 进程可以独立接收具有不同类型的数据块。 消息队列定义如下: #include int msgget(key_t key, int msgflg); int msgrcv(int."— Presentation transcript:

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

2 消息队列 消息队列提供了一种由一个进程向另一个进程发送块数据 的方法。另外,每一个数据块被看作有一个类型,而接收 进程可以独立接收具有不同类型的数据块。 消息队列定义如下: #include 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( key, IPC_CREAT | 0666 ) ; 第二位 : 当前用户的权限 :6=110( 二进制 ), 每一位分 别对应可读, 可写, 可执行,,6 说明当前用户可读可 写不可执行 第三位 :group 组用户,6 的意义同上 第四位 : 其它用户, 每一位的意义同上,0 表示不可读 不可写也不可执行

8 读写消息队列 系统为这个数据类型提供了两个接口( msgsnd 函数, msgrcv 函数),分别对应写消息 队列及读消息队列。将一个新的消息写入队列, 使用函数 msgsnd ,函数原型如下: #include 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 " ); 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 int msgctl( int msqid, int cmd, struct msqid_ds *buf ); 参数 msqid 为指定的要操作的队列, cmd 参数指定 所要进行的操作,其中有些操作需要 buf 参数。 cmd 参数的详细取值及操作如下:

15 cmd 操 作 IPC_ST AT 取队列的 msqid_ds 结构,将它存放在 buf 所指向的结构中 (需要 buf 参数) IPC_SE T 使用 buf 所指向结构中的值对当前队列的相关结构成员赋值, 其中包括: msg_perm.uid 、 msg_perm.gid 、 msg_perm.mode 以及 msg_perm.cuid 。该命令只能由具有 以下条件的进程执行:进程有效用户 ID 等于 msg_perm.cuid 或 msg_perm.uid 超级用户进程。其中只有 超级用户才可以增加队列的 msg_qbytes 的值 IPC_RM ID 删除队列,并清除队列中的所有消息。此操作会影响后续 进程对这个队列的相关操作。该命令只能由具有以下条件 的进程执行。进程有效用户 ID 等于 msg_perm.cuid 或 msg_perm.uid ,超级用户进程 msgctl ()函数

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

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


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

Similar presentations


Ads by Google