System V IPC_msg消息队列

System V IPC(msg, sem, shm)

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






 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值