进程通信之消息通信

消息通信 message

消息是进程间通信的一种重要方式,通常由客户端和服务器端组成。服务器以特定的键值创建一个消息队列,根据约定的消息格式填充要发送的消息和数据类型,把他插入消息队列。而在客户端,根据已知的键值和指定地点类型编码,接收对应的数据。和共享内存的方式相比,不用自己维护消息队列,可以集中精力关注数据传输,但不足的是,对于需要共享或者传输比较复杂数据结构的应用,它就显得不太灵活。

消息通信重要的函数组包括:

int
msgget(key_t key, int msgflg);

The
msgget()  system  call returns the System V message queue identifier
associated with the value of the key argument.  A

new message
queue is created if key has the value IPC_PRIVATE or key isn‘t
IPC_PRIVATE, no message queue with the given key

key exists,
and IPC_CREAT is specified in msgflg.

If  msgflg
specifies both IPC_CREAT and IPC_EXCL and a message queue already
exists for key, then msgget() fails with errno

set to
EEXIST.  (This is analogous to the effect of the combination O_CREAT
| O_EXCL for open(2).)

Upon
creation, the least significant bits of the argument msgflg define
the permissions of the message queue.   These  per‐

mission  bits
have the same format and semantics as the permissions specified for
the mode argument of open(2).  (The exe‐

cute
permissions are not used.)

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);

DESCRIPTION

The  msgsnd()
and msgrcv() system calls are used, respectively, to send messages
to, and receive messages from, a System V

message
queue.  The calling process must have write permission on the message
queue in order to send a  message,  and  read

permission to
receive a message.

The msgp
argument is a pointer to a caller-defined structure of the following
general form:

struct
msgbuf {

long
mtype;       /* message type, must be > 0 */

char
mtext[1];    /* message data */

};

The  mtext
field is an array (or other structure) whose size is specified by
msgsz, a nonnegative integer value.  Messages

of zero
length (i.e., no mtext field) are permitted.  The mtype field must
have a strictly positive  integer  value.   This

value can be
used by the receiving process for message selection (see the
description of msgrcv() below).

int
msgctl(int msqid, int cmd, struct msqid_ds *buf);

DESCRIPTION

msgctl()
performs the control operation specified by cmd on the System V
message queue with identifier msqid.

The msqid_ds
data structure is defined in <sys/msg.h> as follows:

struct
msqid_ds {

struct
ipc_perm msg_perm;     /* Ownership and permissions */

time_t
       msg_stime;    /* Time of last msgsnd(2) */

time_t
       msg_rtime;    /* Time of last msgrcv(2) */

time_t
       msg_ctime;    /* Time of last change */

unsigned
long   __msg_cbytes; /* Current number of bytes in

queue
(nonstandard) */

msgqnum_t
     msg_qnum;     /* Current number of messages

in
queue */

msglen_t
      msg_qbytes;   /* Maximum number of bytes

allowed
in queue */

pid_t  
       msg_lspid;    /* PID of last msgsnd(2) */

pid_t  
       msg_lrpid;    /* PID of last msgrcv(2) */

};

The ipc_perm
structure is defined as follows (the highlighted fields are settable
using IPC_SET):

struct
ipc_perm {

key_t  
      __key;       /* Key supplied to msgget(2) */

uid_t  
      uid;         /* Effective UID of owner */

gid_t  
      gid;         /* Effective GID of owner */

uid_t  
      cuid;        /* Effective UID of creator */

gid_t  
      cgid;        /* Effective GID of creator */

unsigned
short mode;        /* Permissions */

unsigned
short __seq;       /* Sequence number */

};

Valid values
for cmd are:

IPC_STAT

Copy
information from the kernel data structure associated with msqid into
the msqid_ds structure pointed to by buf.

The
caller must have read permission on the message queue.

IPC_SET

Write
the values of some members of the msqid_ds structure pointed to by
buf to the kernel data structure associated

with
this  message  queue, updating also its msg_ctime member.  The
following members of the structure are updated:

msg_qbytes,
msg_perm.uid, msg_perm.gid, and (the least significant 9 bits of)
msg_perm.mode.  The effective  UID  of

the
calling  process  must  match  the owner (msg_perm.uid) or creator
(msg_perm.cuid) of the message queue, or the

caller
must be privileged.  Appropriate privilege (Linux: the
CAP_SYS_RESOURCE capability) is required to raise  the

msg_qbytes
value beyond the system parameter MSGMNB.

IPC_RMID

Immediately
remove  the  message queue, awakening all waiting reader and writer
processes (with an error return and

errno
set to EIDRM).  The calling process must have appropriate privileges
or its effective user ID must  be  either

that of
the creator or owner of the message queue.  The third argument to
msgctl() is ignored in this case.

IPC_INFO
(Linux-specific)

Return
information  about system-wide message queue limits and parameters in
the structure pointed to by buf.  This

structure
is of type msginfo (thus, a cast is required), defined in <sys/msg.h>
if  the  _GNU_SOURCE  feature  test

macro is
defined:

struct
msginfo {

int
msgpool; /* Size in kibibytes of buffer pool

used
to hold message data;

unused
within kernel */

int
msgmap;  /* Maximum number of entries in message

map;
unused within kernel */

int
msgmax;  /* Maximum number of bytes that can be

written
in a single message */

int
msgmnb;  /* Maximum number of bytes that can be

written
to queue; used to initialize

msg_qbytes
during queue creation

(msgget(2))
*/

int
msgmni;  /* Maximum number of message queues */

int
msgssz;  /* Message segment size;

unused
within kernel */

int
msgtql;  /* Maximum number of messages on all queues

in
system; unused within kernel */

unsigned
short int msgseg;

/*
Maximum number of segments;

unused
within kernel */

};

The
msgmni, msgmax, and msgmnb settings can be changed via /proc files of
the same name; see proc(5) for details.

MSG_INFO
(Linux-specific)

Return
a  msginfo  structure  containing the same information as for
IPC_INFO, except that the following fields are

returned
with information about system resources consumed by message queues:
the msgpool field returns the number of

message
queues  that  currently  exist  on the system; the msgmap field
returns the total number of messages in all

queues
on the system; and the msgtql field returns the total number of bytes
in all messages in all  queues  on  the

system.

MSG_STAT
(Linux-specific)

Return
a msqid_ds structure as for IPC_STAT.  However, the msqid argument is
not a queue identifier, but instead an

index
into the kernel‘s internal array that maintains information about all
message queues on the system.

RETURN
VALUE

On success,
IPC_STAT, IPC_SET, and IPC_RMID return 0.  A successful IPC_INFO or
MSG_INFO operation returns the index of the

highest used
entry in the kernel‘s internal array recording information about all
message queues.  (This information can be

used with
repeated MSG_STAT operations to obtain information about all queues
on the system.)  A successful MSG_STAT opera‐

tion returns
the identifier of the queue whose index was given in msqid.

On error, -1
is returned with errno indicating the error.

依赖的头文件包括:

#include
<sys/types.h>

#include
<sys/ipc.h>

#include
<sys/msg.h>

下面以具体可用的一个基于消息通信的服务端和客户端的代码为例:

服务端:test_msg_svc.c

#include<stdio.h>

#include<assert.h>

#include<inttypes.h>

#include
<string.h>

#include
<stdlib.h>

#include
<errno.h>

#include
<unistd.h>

#include
<sys/types.h>

#include
<sys/ipc.h>

#include
<sys/stat.h>

#include
<sys/msg.h>

#define
MSG_FILE "test_msg_clnt"

#define
BUFFER 255

#define
PERM S_IRUSR|S_IWUSR

struct
msgtype {

long
mtype;

char
buffer[BUFFER+1];

};

int
main()

{

struct
msgtype msg;

key_t
key;

int
msgid;

if((key=ftok(MSG_FILE,‘a‘))==-1)

{

{

fprintf(stderr,"Creat
Key Error:%s\a\n",strerror(errno));

exit(1);

}

if((msgid=msgget(key,PERM|IPC_CREAT|IPC_EXCL))==-1)

//if((msgid=msgget(key,PERM|IPC_EXCL))==-1)

{

fprintf(stderr,"Creat
Message Error:%s\a\n",strerror(errno));

exit(1);

}

while(1)

{

msgrcv(msgid,&msg,sizeof(struct
msgtype),1,0);

fprintf(stderr,"Server
Receive:%s\n",msg.buffer);

msg.mtype=2;

msgsnd(msgid,&msg,sizeof(struct
msgtype),0);

memcpy(msg.buffer,
"Hello", strlen("Hello") + 1);

msg.mtype=2;

msgsnd(msgid,&msg,sizeof(struct
msgtype),0);

}

exit(0);

}

客户端: test_msg_clnt.c:

#include<stdio.h>

#include<assert.h>

#include<inttypes.h>

#include
<string.h>

#include
<stdlib.h>

#include
<errno.h>

#include
<unistd.h>

#include
<sys/types.h>

#include
<sys/ipc.h>

#include
<sys/stat.h>

#include
<sys/msg.h>

#define
MSG_FILE "test_msg_clnt"

#define
BUFFER 255

#define
PERM S_IRUSR|S_IWUSR

struct
msgtype {

long
mtype;

char
buffer[BUFFER+1];

};

int
main(int argc,char **argv)

{

struct
msgtype msg;

key_t
key;

int
msgid;

if(argc!=2)

{

fprintf(stderr,"Usage:%s
string\n\a",argv[0]);

exit(1);

}

if((key=ftok(MSG_FILE,‘a‘))==-1)

{

fprintf(stderr,"Creat
Key Error:%s\a\n",strerror(errno));

exit(1);

}

if((msgid=msgget(key,PERM))==-1)

{

fprintf(stderr,"Creat
Message Error:%s\a\n",strerror(errno));

exit(1);

}

msg.mtype=1;

strncpy(msg.buffer,argv[1],BUFFER);

msgsnd(msgid,&msg,sizeof(struct
msgtype),0);

memset(&msg,‘\0‘,sizeof(struct
msgtype));

msgrcv(msgid,&msg,sizeof(struct
msgtype),2,0);

fprintf(stdout,"Client
receive:%s\n",msg.buffer);

msgrcv(msgid,&msg,sizeof(struct
msgtype),2,0);

fprintf(stdout,"Client
receive:%s\n",msg.buffer);

exit(0);

}

编译运行及其结果:

[[email protected]
testcases]$ gcc -o test_msg_svc test_msg_svc.c

[[email protected]
testcases]$ gcc -o test_msg_clnt test_msg_clnt.c

[[email protected]
testcases]$ ./test_msg_svc

Server
Receive:HaHi

Server
Receive:GdLuCK

[[email protected]
testcases]$ ./test_msg_clnt HaHi

Client
receive:HaHi

Client
receive:Hello

[[email protected]
testcases]$ ./test_msg_clnt GdLuCK

Client
receive:GdLuCK

Client
receive:Hello

时间: 2024-10-13 07:57:58

进程通信之消息通信的相关文章

【进程编程】——msg进程间的消息队列通信

           [进程编程]--msg进程间的消息队列通信 消息队列就像一个链表,先进先出,就像排队打饭,先到先买!键值 用来获取消息队列的描述字,我感觉就像是一个定位标识符! 函数一     key_t ftok(char *pathname,char proj)返回的是一个键值------>创建队列之前一定要获取这个键值!proj:项目名,不为零即可 打开.创建函数二     int msgget(key_t key,int msgflg) //看见没,这里是要求键值的. key:键值

msgrcv,msgsnd进程通信,消息的发送和接收

//进程通信,消息的发送和接收 //client.c #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <err

Linux程序设计学习笔记----System V进程通信之消息队列

一个或多个进程可向消息队列写入消息,而一个或多个进程可从消息队列中读取消息,这种进程间通讯机制通常使用在客户/服务器模型中,客户向服务器发送请求消息,服务器读取消息并执行相应请求.在许多微内核结构的操作系统中,内核和各组件之间的基本通讯方式就是消息队列.例如,在 MINIX 操作系统中,内核.I/O 任务.服务器进程和用户进程之间就是通过消息队列实现通讯的. Linux中的消息可以被描述成在内核地址空间的一个内部链表,每一个消息队列由一个IPC的标识号唯一的标识.Linux 为系统中所有的消息队

使用内存映射开发高性能进程间消息通信组件

一.背景 项目开发中免不了各模块或系统之间进行消息通信,目前热门的消息中间件有Redis.RabbitMQ.Kafka.RocketMQ等等. 以上几种组件中Redis在消息队列方面表现还可以,但是如果涉及发布订阅功能,就不行了,最近项目就使用了redis的发布订阅, 每秒只能发出几千条,虽然目前绰绰有余,但是瓶颈可以预期. 其余的几种都是比较重量级的消息中间件,什么跨平台.分布式.集群.支持N种协议等等,很高大全, 我们可能就只使用了其中1.2个功能.严格来说,项目中集成这几种MQ的工作量是不

ZeroMQ——一个轻量级的消息通信组件

ZeroMQ是一个轻量级的消息通信组件,尽管名字中包含了"MQ",严格上来讲ZeroMQ并不是"消息队列/消息中间件".ZeroMQ是一个传输层API库, 更关注消息的传输.与消息队列相比,ZeroMQ有以下一些特点: 点对点无中间节点 传统的消息队列都需要一个消息服务器来存储转发消息.而ZeroMQ则放弃了这个模式,把侧重点放在了点对点的消息传输上,并且(试图)做到极致.以为消息服务器最终还是转化为服务器对其他节点的点对点消息传输上.ZeroMQ能缓存消息,但是是

信号,信号量,锁,条件变量,消息通信,共享内存,RPC (一)

在实际项目当中,经常需要把一个功能分成多个子模块实现.那么,这些子模块之间该如何关联起来呢?静态地看,模块可以看作一组完成相同功能的函数:而动态地看,模块可以是一个独立的进程.线程或者一个中断服务或者信号服务例程.根据不同的具体业务实现,它们之间可能是静态调用.动态互斥.同步.唤醒等关系.静态的调用很好实现,上层的函数调用底层的函数即可.那么,动态互斥.同步.唤醒等关系,又该如何实现呢?这就设计到我们将要讨论的信号.进程间消息通信.共享内存.线程互斥同步条件变量.RPC等手段.下面就按照Linu

进程通信,线程通信,同步方式

一.进程间通信 进程间的通信,它的数据空间的独立性决定了它的通信相对比较复杂,需要通过操作系统.以前进程间的通信只能是单机版的,现在操作系统都继承了基于套接字(socket)的进程间的通信机制.这样进程间的通信就不局限于单台计算机了,实现了网络通信.进程的通信机制主要有:管道.有名管道.消息队列.信号量.共享空间.信号.套接字. 1.信号 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号

进程的同步与通信,进程与线程同步的区别,进程与线程通信的区别【转】

本文转载自:http://www.cnblogs.com/youngforever/p/3250270.html 这两天看进程的同步与通信,看了几本书上的介绍,也从网上搜了很多资料,越看越迷惑,被这几个问题搞得很纠结. 进程同步与互斥的区别? 进程的同步方式有哪些? 进程的通信方式有哪些? 进程同步与通信的区别是什么? 线程的同步/通信与进程的同步/通信有区别吗? 在好多教材上(包括国内与国外的)也没有明确这些概念,现在对每个问题还没有准确的答案,下面将自己的理解记下来,以后再补充. 参考资料:

ZeroMQ——一个轻量级的消息通信组件 C#

ZeroMQ——一个轻量级的消息通信组件 ZeroMQ是一个轻量级的消息通信组件,尽管名字中包含了"MQ",严格上来讲ZeroMQ并不是"消息队列/消息中间件".ZeroMQ是一个传输层API库, 更关注消息的传输.与消息队列相比,ZeroMQ有以下一些特点: 点对点无中间节点 传统的消息队列都需要一个消息服务器来存储转发消息.而ZeroMQ则放弃了这个模式,把侧重点放在了点对点的消息传输上,并且(试图)做到极致.以为消息服务器最终还是转化为服务器对其他节点的点对点