进程间通信(消息队列)

2019-07-12 14:50发布

         在嵌入式Linux应用开发中,Linux进程通信的方式有6种,分别是管道(pipe)及有名管道(named pipe)、信号(signal)、消息队列(msg)、共享内存(shm)、信号量、和套接字(socket),在这我就简单的描述一下进程通信中的信息队列(msg):         首先,消息队列的实现有重要的几步:                      1、创建或打开消息队列;                             int msgget(key_t key,int flag)                             ——key :代表返回新的或已有队列的队列ID,IPC_PRIVATE,可通过ftok生成                            ——返回值(int flag):消息队列ID(msqid)                       2、添加信息;                           int msgsnd(int msgqid,const  void *prt,size_t  size,int flag)                            ——其中prt指的是指向消息队列结构的指针,消息队列结构体:                                   struct  msgbuf                                      {                                          long  mtype;                                          char   mtext[1];                                       }                       3、读取信息;                            int  msgrcv(int  msgqid,struct  msgbuf *msgp,int  size,long  msgtype,int  flag)                            ——其中msgtype等于零:接收消息对列中的第一个消息                                                           大于零:接收消息队列中第一个类型为没事干type的消息                                                           小于零:接收消息队列中第一个类型值不小于msgtype绝对值且类型值又最小的消息                            ——在flag:如果flag=MSG_NOERROR,代表若返回的消息比size字节多,则消息就会截短到size字节,且不通知消息发送进程                                                  如果flag=IPC_NOWAIT,代表若消息并没有立即发送而调用进程会立即返回                                                 如果flag=0,代表msgsnd调用阻塞直到条件满足为止
                      4、控制消息队列。                         int msgctl(int msgqid,int  cmd,struct  msqid_ds *buf)                         ——其中如果cmd=IPC_STAT:代表读取消息队列的数据结构msgqid_ds,并将其存储在buf指定的地址中                                        如果cmd=IPC_SET:代表设置消息队列的数据结构msgqid_ds中的ipc_perm元素的值。这个值取自buf参数                                        如果IPC_RMID:从系统内核中移走消息队列                下面是一个简单的代码:                         #include
                        #include
                        #include
                        #include
                        #include
                        #include
                        #include
                        #define BUFSZ 512
                        struct message                           {
                                long msg_type;
                                 char msg_text[BUFSZ];
                          };
 
                         int main()
                         {
                                int qid;   //定义一个qip符号
                                key_t key;//定义一个key
                               int len;//类型是len
                               struct message msg;//消息队列的结构体
 
                                if((key=ftok(".",'a'))==-1){//通过ftok判断有没有返回新的或已有的队列的ID
                                perror("ftok");
                                  exit(1);
                              }
                                if((qid=msgget(key,IPC_CREAT|0666))==-1){//创建一个权限为读写的消息对列
                                 perror("msgget");
                                 exit(1);
                             }
                                printf("opened queue %d ",qid);
                                puts("Please enter the message to queue:");
                                if((fgets((&msg)->msg_text,BUFSZ,stdin))==NULL){
                                puts("no message");
                                exit(1);
                            }
                                msg.msg_type = getpid();
                                 len = strlen(msg.msg_text);
                                 if((msgsnd(qid,&msg,len,0))<0){//判断有没有添加消息
                                  perror("message posted");
                                  exit(1);
                            }
                                if(msgrcv(qid,&msg,BUFSZ,0,0)<0){//判断有没有消息读
                                perror("msgrcv");
                               exit(1);
                            }
                                printf("message is:%s ",(&msg)->msg_text);
                                if((msgctl(qid,IPC_RMID,NULL))<0){
                                 perror("msgctl");
                                 exit(1);
                              }
                                exit(0);
                               }