struct ipc_perm q_perm; time_t q_stime; // last msgsnd time time_t q_rtime; // last msgrcv _64__ unsigned long int __glibc_reserved1; #endif __time_t msg_rtime; /* time of last msgrcv 接收数据(读) 从消息队列接收数据使用msgrcv()函数,函数原型如下: #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h > int msgrcv(int msqid, const void *prt, size_t nbytes, long type, int flags); 运行成功返回0,失败返回-1。 = 1) { printf("Message:%s, Type:%ld\n", msg1.buf, msg1.mtype); res = msgrcv(msgid
接口 主要用到msgget、msgsnd、msgrcv和msgctl四个接口。其使用方式man手册说明的比较清晰了,这里简单描述一下函数形式及功能。 msgsnd、msgrcv #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); msgsnd与msgrcv主要用于消息队列的发送与接收。 如此msgrcv通过指定msgtype来筛选出需要的消息。
\0\0\0HJ\325r8\0\0\0"...}, 8192, 0, 0) = 10 write(1, "consumer:28204 recv {\"data\":0}\n", 31) = 31 msgrcv \0\0\0HJ\325r8\0\0\0"...}, 8192, 0, 0) = 10 write(1, "consumer:28204 recv {\"data\":1}\n", 31) = 31 msgrcv \0\0\0HJ\325r8\0\0\0"...}, 8192, 0, 0) = 10 write(1, "consumer:28204 recv {\"data\":2}\n", 31) = 31 msgrcv \0\0\0HJ\325r8\0\0\0"...}, 8192, 0, 0) = 10 write(1, "consumer:28204 recv {\"data\":3}\n", 31) = 31 msgrcv \0\0\0HJ\325r8\0\0\0"...}, 8192, 0, 0) = 10 write(1, "consumer:28204 recv {\"data\":4}\n", 31) = 31 msgrcv
msgqueB.c #include <stdio.h> #include <sys/msg.h> //key_t,ftok,msgget,msgrcv,msgctl,IPC_RMID 相关声明在这个头文件中有所包含 open queue %d\n",qid); do { memset(msg.msg_text,0,BUFSZ); //将msg.msg_text的内容清零 if(0 > msgrcv (qid,&msg,BUFSZ,0,0)) //从消息队列中获取信息并且存到msg中 { perror("msgrcv"); return res; } msgrcv 的原型定义在 sys/msg.h 中 /* Receive message from message queue. This function is a cancellation point and therefore not marked with __THROW. */ extern ssize_t msgrcv
Time of last msgsnd() */ time_t msg_rtime; /* Time of last msgrcv /* PID of last msgsnd() */ pid_t msg_lrpid; /* PID of last msgrcv 从消息队列接收信息 ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtype, int msgflag IPC_NOWAIT:调用进程会立即返回.若没有收到消息则返回-1. 0:msgrcv调用阻塞直到条件满足为止. 在成功地读取了一条消息以后,队列中的这条消息将被删除。 { while(1) { memset(msg.mtext, 0, 100); msgrcv
参考补充: Linux manual page ---- 消息的接收 msgrcv 函数原型:ssize_t msgrcv (int msqid, void *msgp, size_t msgsz, \n"); exit(1); } msg.msg_type = 0; ret = msgrcv(msgid, &msg, MSG_SIZE, 0, 0); if (ret == -1) { printf("msgrcv failed! \n"); exit(1); } while(1) { msg.msg_type = 0; ret = msgrcv(msgid, &msg, MSG_SIZE, 0, 0); if (ret == -1) { printf("msgrcv failed!
msgsnd 函数会阻塞,直到消息队列有空间可以发送消息 msgsnd(msgid, &msgbuf, sizeof(msgbuf.mtext), IPC_NOWAIT) (四)在消息队列中获取数据块 msgrcv 接收消息队列中消息类型为msgtyp的第一条消息,如果小于0,接收消息队列中消息类型小于等于msgtyp绝对值的最小类型的第一条消息 msgflg:该位置为0就是不设置 函数 msgflg 作用 示例 msgrcv IPC_NOWAIT 当消息队列中没有符合要求的消息时,如果设置了该标志,msgrcv 函数会立即返回 -1,errno 被设置为 ENOMSG;若未设置该标志,msgrcv 函数会阻塞,直到有符合要求的消息进入消息队列 msgrcv(msgid, &msgbuf, sizeof(msgbuf.mtext), msgtype, IPC_NOWAIT) msgrcv MSG_NOERROR 如果接收到的消息长度超过了指定的缓冲区大小 ,若设置了该标志,消息会被截断为缓冲区大小,多余部分会被丢弃,msgrcv 函数正常返回;若未设置该标志,msgrcv 函数会返回 -1,errno 被设置为 E2BIG msgrcv(msgid, &
mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ }; 消息类型必须大于0,因为对于msgrcv IPC_NOWAIT标志使的msgsnd调用非阻塞(nonblocking). 6.4 msgrcv #include <sys/msg.h> ssize_t msgrcv(int msgid,
一、msgsnd 和 msgrcv 函数 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> 功能: 功能:是从一个消息队列接收消息 原型 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); 参数 二、消息队列实现回射客户/服务器 在前面的系列文章中,我们都是使用socket 套接字来实现回射客户/服务器程序,现在尝试使用消息队列来实现,主要就是利用上面介绍的两个函数msgsnd,msgrcv 。 msgbuf msg; memset(&msg, 0, sizeof(msg)); int nrcv = 0; while (1) { if ((nrcv = msgrcv ERR_EXIT("msgsnd"); memset(msg.mtext + 4, 0, MSGMAX - 4); if ((nrcv = msgrcv
pid_t msg_lspid; // 最近一个执行`msgsnd`的进程PID pid_t msg_lrpid; // 最近一个执行`msgrcv PID time_t msg_stime; // 最近一次执行`msgsnd`的时间 time_t msg_rtime; // 最近一次执行`msgrcv 5.msgrcv函数 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid msgbuff; memset(msgbuff.mtext,0,sizeof(msgbuff.mtext)); size_t end=msgrcv _msgfd,&msgbuff,MTEXT_SIZE-1,mtype,0); if(-1==end){ std::cerr<<"msgrcv
msgrcv用于读消息队列。 消息队列遵循First In ,First Out规则。 下面是消息队列相关实现代码。 return; 50 } 51 } 52 int msgQueue::revMsg() 53 { 54 struct msgbuf buf; 55 int ret = msgrcv
time_t msg_stime; /* Time of last msgsnd(2) */ time_t msg_rtime; /* Time of last msgrcv pid_t msg_lspid; /* PID of last msgsnd(2) */ pid_t msg_lrpid; /* PID of last msgrcv msgrcv 是一个用于从 System V 消息队列 中接收消息的系统调用。 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp 128 }; int main() { int msgid = getMsg(); struct my_msgbuf msg; //开始接受信息 ssize_t n = msgrcv
msgrcv函数 3.ssize_t msgrcv(int msqid, void *ptr, size_t length, long type, int flag); 参数ptr: 指定接受消息存放的位置 strlen(msg.mtext), 0); } else if (pid == 0) { MSG msg; memset(&msg, 0, sizeof(msg)); msgrcv = -1); MSG msg; memset(&msg, 0, sizeof(msg)); msgrcv(id, &msg, 127, 200, 0); printf("msg.mtype
msg_stime; /* Time of last msgsnd(2) */ time_t msg_rtime; /* Time of last msgrcv msg_lspid; /* PID of last msgsnd(2) */ pid_t msg_lrpid; /* PID of last msgrcv struct msqid_ds *buf); int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgfl_g); ssize_t msgrcv void*)buf, len, IPC_NOWAIT);// 满了就会失败 if(ret < 0) ERR_EXIT("msgsnd"); return 0; } 4.4 msgrcv struct msgbuf *buf = (struct msgbuf*)malloc(sizeof(long) + MSGMAX); buf->mtype = type; int ret = msgrcv
__kernel_time_t msg_stime; /* last msgsnd time */ __kernel_time_t msg_rtime; /* last msgrcv msqid_ds 数据结构中给出的值(修改指定消息队列的属性) IPC_RMID 删除消息队列 buf:属性缓冲区 返回值 成功时返回 0,失败返回 -1 3. msgsnd NAME msgrcv be > 0 */ char mtext[1]; /* message data */ }; // 以一个 long int 长整数开始,接收者函数将利用这个长整型确定消息的类型 4. msgrcv NAME msgrcv, msgsnd - System V message queue operations SYNOPSIS #include <sys/types.h > #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp
如msgsnd喝msgrcv就是典型的例子,msgsnd/msgrcv以block方式发送/接收消息时,会因为进程收到了信号而中断。 此时msgsnd/msgrcv将返回-1,errno被设置为EINTR。且即使在插入信号时设置了SA_RESTART,也无效。 在man msgrcv中就有提到这点: msgsnd and msgrcv are never automatically restarted after being interrupted by a 有时我们需要捕获信号,但又考虑到第②种方法的局限性(设置 SA_RESTART属性对有的系统无效,如msgrcv),所以在编写代码时,一定要“人为重启被中断的系统调用”。
具体函数的用法可以用man手册查看(强力推荐) (1)ftok()生产key (2)使用msgget( ) 创建/获取消息队列,返回值是队列标识符 (3)使用msgsnd( ) 发送消息 使用msgrcv ; exit(1); } int res = msgrcv(msgid, &msg, sizeof(msg), 2, // 取消息类型为2的消息
2.3. msgrcv 用于从消息队列中接收消息。 函数原型: #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid, void 0666); if (msqid == -1) { perror("msgget"); exit(1); } // 接收消息 if (msgrcv (msqid, &msg, MSG_SIZE, 1, 0) == -1) { perror("msgrcv"); exit(1); } printf(" 使用msgrcv函数可以从消息队列中读取消息。该函数也需要四个参数:消息队列的ID、指向用于存储接收到的消息的缓冲区的指针、缓冲区的大小、消息的类型以及标志位。
当以下情况出现时消息队列才不会继续存在系统中: ①某个进程调用msgrcv或msgctl读取或删除消息队列 ②某个进程执行ipcrm(1)命令删除息队列 与管道相比,最后一个访问管道的进程结束时,管道就彻底被删除了 error: %d\n", errno); exit(EXIT_FAILURE); } //从队列中获取消息,直到遇到end消息为止 while(running) { if(msgrcv (msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno
msgrcv 函数分析: msqid 消息队列的标识符,指定要接收消息的目标队列 msgp 一个指向消息结构的指针,用于存储接收到的消息 该结构必须至少包含一个 long 类型的 mtype 如果消息的内容超过该大小,msgrcv 会截断消息。 常见的标志有: IPC_NOWAIT:如果没有符合条件的消息,msgrcv 会立即返回失败(并设置 errno 为 ENOMSG),而不是阻塞。 接收消息 struct mymsgbuf info; size_t sz = msgrcv(msqid, &info, sizeof(info), 1, 0); if(sz == -1){ std::cout << "msgrcv error" <<std::endl; } else std::cout << "msgrcv success: "