msg: message
sem: semaphore
shm: share memory
消息队列 信号量 共享内存区
头文件 <sys/msg.h> <sys/sem.h> <sys/shm.h>
创建或是打开
IPC的函数 msgget semget shmget
控制IPC操作
的函数 msgctl semctl shmctl
IPC操作函数 msgsnd/msgrcv semop shmat/shmdt
System V IPC 函数汇总
system v 消息队列
对于系统中的每个消息队列,内核维护一个定义在<sys/msg.h>头文件中的信息结构
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue,unused */
struct msg *msg_last; /* last message in queue,unused */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
unsigned short msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
struct msqid_ds
{
struct ipc_perm msg_perm; //r,w权限
struct msg *msg_first; //指向队列中第一个消息
struct msg *msg_last; //指向队列中最后一个消息
msglen_t msg_cbytes; //当前队列中消息的总字节数
msgqnum_t msg_qnum; //当前队列中总消息数
msglen_t msg_qbytes; //队列中允许的最大字节数
pid_t msg_lspid; // pid of last msgsnd最后一个调用msgsnd的进程号
pid_t msg_lrpid; // pid of last msgrcv最后一个调用msgrcb的进程号
time_t msg_stime; // time of last msgsnd
time_t msg_rtime; // time of last msgrcv
time_t msg_ctime; // time of last msgctl
};
消息队列:
1. msgget返回是一个id号,它不是文件描述符。
所有用文件描述符来操作的系统函数,都不能用于消息队列
比如:read/write, select/poll 不能应用于消息队列
2. 消息队列是一种能被替换的旧的IPC方式,
应用程序中应尽量避免使用。
消息队列的操作:
1. 先向内核申请一个system v ipc的key
NAME
ftok - convert a pathname and a project identifier to a System V IPC
key
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
DESCRIPTION
The ftok() function uses the identity of the file named by the given
pathname (which must refer to an existing, accessible file) and the
least significant 8 bits of proj_id (which must be nonzero) to generate
a key_t type System V IPC key, suitable for use with msgget(2),
semget(2), or shmget(2).
The resulting value is the same for all pathnames that name the same
file, when the same value of proj_id is used. The value returned
should be different when the (simultaneously existing) files or the
project IDs differ.
RETURN VALUE
On success, the generated key_t value is returned. On failure -1 is
returned, with errno indicating the error as for the stat(2) system
call.
NAME
ftok - convert a pathname and a project identifier to a
System V IPC key
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
ftok把一个路径名和整数通过某种算法生成一个
唯一的system v ipc的key.
key_t ftok(const char *pathname, int proj_id);
pathname:一个路径名,(请写一个存在的文件名或目录名)
proj_id:一个整数
返回值:
成功返回一个system v ipc的key,
失败返回-1, errno被设置。
2. 调用msgget创建或打开消息队列
NAME
msgget - get a System V message queue identifier
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
DESCRIPTION
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 permission bits have the
same format and semantics as the permissions specified for the mode
argument of open(2). (The execute permissions are not used.)
If a new message queue is created, then its associated data structure
msqid_ds (see msgctl(2)) is initialized as follows:
msg_perm.cuid and msg_perm.uid are set to the effective user ID
of the calling process.
msg_perm.cgid and msg_perm.gid are set to the effective group ID
of the calling process.
The least significant 9 bits of msg_perm.mode are set to the
least significant 9 bits of msgflg.
msg_qnum, msg_lspid, msg_lrpid, msg_stime and msg_rtime are set
to 0.
msg_ctime is set to the current time.
msg_qbytes is set to the system limit MSGMNB.
If the message queue already exists the permissions are verified, and a
check is made to see if it is marked for destruction.
RETURN VALUE
If successful, the return value will be the message queue identifier (a
nonnegative integer), otherwise -1 with errno indicating the error.
NAME
msgget - get a System V message queue identifier
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
msgget用于创建或打开一个system v消息队列
int msgget(key_t key, int msgflg);
key: ftok生成的IPC key
msgflg: 标志位。 分两种情况
(1) 创建: IPC_CREAT | 权限位
如: IPC_CREAT | 0664
(2)打开: 0.
返回值:
成功返回一个打开了的system v消息队列的ID,
失败返回-1, errno被设置。
3. 收发消息
NAME
msgrcv, msgsnd - System V message queue operations
SYNOPSIS
#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);
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 caller-defined structure of the fol‐
lowing 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 speci‐
fied 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 receiv‐
ing process for message selection (see the description of msgrcv()
below).
msgsnd()
The msgsnd() system call appends a copy of the message pointed to by
msgp to the message queue whose identifier is specified by msqid.
If sufficient space is available in the queue, msgsnd() succeeds imme‐
diately. (The queue capacity is defined by the msg_qbytes field in the
associated data structure for the message queue. During queue creation
this field is initialized to MSGMNB bytes, but this limit can be modi‐
fied using msgctl(2).) If insufficient space is available in the
queue, then the default behavior of msgsnd() is to block until space
becomes available. If IPC_NOWAIT is specified in msgflg, then the call
instead fails with the error EAGAIN.
A blocked msgsnd() call may also fail if:
* the queue is removed, in which case the system call fails with errno
set to EIDRM; or
* a signal is caught, in which case the system call fails with errno
set to EINTR;see signal(7). (msgsnd() is never automatically
restarted after being interrupted by a signal handler, regardless of
the setting of the SA_RESTART flag when establishing a signal han‐
dler.)
Upon successful completion the message queue data structure is updated
as follows:
msg_lspid is set to the process ID of the calling process.
msg_qnum is incremented by 1.
msg_stime is set to the current time.
msgrcv()
The msgrcv() system call removes a message from the queue specified by
msqid and places it in the buffer pointed to by msgp.
The argument msgsz specifies the maximum size in bytes for the member
mtext of the structure pointed to by the msgp argument. If the message
text has length greater than msgsz, then the behavior depends on
whether MSG_NOERROR is specified in msgflg. If MSG_NOERROR is speci‐
fied, then the message text will be truncated (and the truncated part
will be lost); if MSG_NOERROR is not specified, then the message isn't
removed from the queue and the system call fails returning -1 with
errno set to E2BIG.
The argument msgtyp specifies the type of message requested as follows:
* If msgtyp is 0, then the first message in the queue is read.
* If msgtyp is greater than 0, then the first message in the queue of
type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in
which case the first message in the queue of type not equal to msgtyp
will be read.
* If msgtyp is less than 0, then the first message in the queue with
the lowest type less than or equal to the absolute value of msgtyp
will be read.
The msgflg argument is a bit mask constructed by ORing together zero or
more of the following flags:
IPC_NOWAIT
Return immediately if no message of the requested type is in the
queue. The system call fails with errno set to ENOMSG.
MSG_EXCEPT
Used with msgtyp greater than 0 to read the first message in the
queue with message type that differs from msgtyp.
MSG_NOERROR
To truncate the message text if longer than msgsz bytes.
If no message of the requested type is available and IPC_NOWAIT isn't
specified in msgflg, the calling process is blocked until one of the
following conditions occurs:
* A message of the desired type is placed in the queue.
* The message queue is removed from the system. In this case the sys‐
tem call fails with errno set to EIDRM.
* The calling process catches a signal. In this case the system call
fails with errno set to EINTR. (msgrcv() is never automatically
restarted after being interrupted by a signal handler, regardless of
the setting of the SA_RESTART flag when establishing a signal han‐
dler.)
Upon successful completion the message queue data structure is updated
as follows:
msg_lrpid is set to the process ID of the calling process.
msg_qnum is decremented by 1.
msg_rtime is set to the current time.
RETURN VALUE
On failure both functions return -1 with errno indicating the error,
otherwise msgsnd() returns 0 and msgrcv() returns the number of bytes
actually copied into the mtext array.
NAME
msgrcv, msgsnd - System V message queue operations
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
msgsnd用来发送一个信息到指定的消息队列上去。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msqid: 由msgget返回的标识消息队列的标识符。
msgp: 指针。指向要发送信息的结构体的指针,
该结构体应具有如下形式(这个结构体需要用户
自己定义。)
struct msgbuf
{
long mtype; //消息类型。 > 0
char mtext[0]; //消息内容,可大可小
}
msgsz:消息内容的长度。上述结构体中数组mtext的大小。
msgflg: 发送标志:
(1) 0 阻塞模式(默认)
(2) IPC_NOWAIT 非阻塞模式
例子:
struct msgbuf *p = malloc(sizeof(struct msgbuf) + 1024);
此处用到柔性数组的概念,结构体msgbuf中,并不定义mtext的数组长度,或者大小不定,而实际malloc中分配在p所指向的结构体msgbuf空间后面连续的1024个byte内存空间都可以由mtext指向。非常灵活使用。
返回值:
成功返回0
失败返回-1, errno被设置
msgrcv用来在指定消息队列上读取下一个指定类型的消息。
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtype, int msgflg);
msqid:消息队列id, 表示从哪个消息队列上读取消息
msgp:一个指针。用来保存消息的结构体。(该结构体需要自已定义)
msgsz:表示msgp指向的结构体最大能保存的字节数
msgtype:想要读取的消息类型。 0表示任意类型的消息
msgflg:读取标志
(1) 0 阻塞方式
(2) IPC_NOWAIT 非阻塞方式
返回值:
若成功则为读入到缓冲区中数据的字节数,
若出错则返回-1, errno被设置
4. 消息队列控制
NAME
msgctl - System V message control operations
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
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. Appro‐
priate privilege (Linux: the CAP_IPC_RESOURCE capability) is
required to raise the msg_qbytes value beyond the system parame‐
ter 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.
IPC_INFO (Linux-specific)
Returns 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)
Returns 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 cur‐
rently 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)
Returns 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 operation returns the identifier of the queue whose
index was given in msqid.
On error, -1 is returned with errno indicating the error.
msgctl
NAME
msgctl - System V message control operations
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
msgctl用来实现system v 消息队列的控制操作
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid:消息队列id,表示要控制的消息队列
cmd: 命令号。常用有有下面三个:
IPC_RMID : 删除消息队列
IPC_SET: 设置消息队列的属性
IPC_STAT:返回消息队列的属性
buf:是一个struct msqid_ds的结构体指针。
根据不同的命令含义不一样。
IPC_RMID, 可以为空。
IPC_SET:把buf指向的结构体设置到消息队列的属性中去
IPC_STAT:把消息队列的属性消息返回到buf指向的结构体中去。
返回值:
成功返回0
失败返回-1, errno被设置。
Demo:
msgsnd.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#define PATH_NAME "/home/klein"
#define PROJ_ID 158
//key_t ftok(const char *pathname, int proj_id);
// int msgget(key_t key, int msgflg);
struct msgbuf{
long mtype;
char mtext[0];
};
int main(int argc,char** argv){
key_t key = ftok(PATH_NAME,PROJ_ID);
if(key == -1){
perror("ftok error");
return -1;
}
int msg_qid = msgget(key,IPC_CREAT | 0666);
if(msg_qid == -1){
perror("msgget error");
return -1;
}
/* 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);*/
struct msgbuf *p = (struct msgbuf*)malloc(sizeof(*p)+100);
p->mtype = 100;
strcpy(p->mtext,"hello,this is a msg.");
msgsnd(msg_qid,p,100,0);//0 indicate block
return 0;
}
msgrcv.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#define PATH_NAME "/home/klein"
#define PROJ_ID 158
//key_t ftok(const char *pathname, int proj_id);
// int msgget(key_t key, int msgflg);
struct msgbuf{
long mtype;
char mtext[0];
};
int main(int argc,char** argv){
key_t key = ftok(PATH_NAME,PROJ_ID);
if(key == -1){
perror("ftok error");
return -1;
}
int msg_qid = msgget(key,IPC_CREAT | 0666);
if(msg_qid == -1){
perror("msgget error");
return -1;
}
/* 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);*/
struct msgbuf *p = (struct msgbuf*)malloc(sizeof(*p)+100);
//p->mtype = 100;
//strcpy(p->mtext,"hello,this is a msg.");
//msgsnd(msg_qid,p,100,0);//0 indicate block
ssize_t s = msgrcv(msg_qid,p,100,0,0);
if(s == -1){
perror("msgrcv error");
return -1;
}
printf("%s\n",p->mtext);
return 0;
}