快捷搜索:

该id值通过ftok函数得到,一、消息队列的特点

来源:http://www.fab119.com 作者:关于我们 人气:135 发布时间:2020-01-05
摘要:消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。
①消息队列的创建与打开
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgget(key_t key,int msgflg);
返回值:
– 如果成功,返回消息队列标识符
– 如果失败,则返回-1
在以下两种情况下,该调用将创建一个新的消息队列:
– 如果没有消息队列与健值key相对应,并且msgflg中包含了IPC_CREAT标志位;
– key参数为IPC_PRIVATE;(其值为0)

所谓消息队列就是指一个消息链表。

Linux进程间通信:消息队列,linux进程通信队列

一、消息队列的特点

    1.消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识.
    2.消息队列允许一个或多个进程向它写入与读取消息.
    3.管道和命名管道都是通信数据都是先进先出的原则。
    4.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比FIFO更有优势。

    目前主要有两种类型的消息队列:POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用。系统V消息队列是随内核持续的,只有在内核重起或者人工删除时,该消息队列才会被删除。

二、相关函数

  1. 获得key值

    key_t ftok(char *pathname, int projid)

#include <sys/types.h>
#include <sys/ipc.h>
参数:
    pathname:文件名(含路径),通常设置为当前目录“.” 
    projid:项目ID,必须为非0整数(0-255). 

  1. 创建消息队列
        int msgget(key_t key, int msgflag)
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    功能:
        用于创建一个新的或打开一个已经存在的消息队列,此消息队列与key相对应。
    参数:
        key:函数ftok的返回值或IPC_PRIVATE。
        msgflag:
            IPC_CREAT:创建新的消息队列。
            IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
            IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。
    返回值:
        调用成功返回队列标识符,否则返回-1.

在以下两种情况下,将创建一个新的消息队列:
    1、如果没有与键值key相对应的消息队列,并且msgflag中包含了IPC_CREAT标志位。
    2、key参数为IPC_PRIVATE。 

  1. 消息队列属性控制
        int msgctl(int msqid,  int cmd,  struct msqid_ds *buf)
    功能:
     对消息队列进行各种控制操作,操作的动作由cmd控制。
    参数:
        msqid:消息队列ID,消息队列标识符,该值为msgget创建消息队列的返回值。
        cmd:
            IPC_STAT:将msqid相关的数据结构中各个元素的当前值存入到由buf指向的结构中.
            IPC_SET:将msqid相关的数据结构中的元素设置为由buf指向的结构中的对应值.
            IPC_RMID:删除由msqid指示的消息队列,将它从系统中删除并破坏相关数据结构.
    buf:消息队列缓冲区
        struct msqid_ds {
                  struct ipc_perm msg_perm;          /* Ownership and permissions*/
                  time_t        msg_stime;                /* Time of last msgsnd() */
                  time_t        msg_rtime;                  /* Time of last msgrcv() */
                  time_t        msg_ctime;                /* Time of last change */
                  unsigned long  __msg_cbytes;    /* Current number of bytes in  queue (non-standard) */
                  msgqnum_t      msg_qnum;          /* Current number of messages  in queue */
                  msglen_t      msg_qbytes;          /* Maximum number of bytesallowed in queue */
                  pid_t          msg_lspid;                  /* PID of last msgsnd() */
                  pid_t          msg_lrpid;                  /* PID of last msgrcv() */
                        };

    struct ipc_perm {
              key_t key;                        /* Key supplied to msgget() */
              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 */
                  };

4.发送信息到消息队列
    int msgsnd(int msqid,  struct msgbuf *msgp,  size_t msgsz,  int msgflag)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能:

    将新消息添加到队列尾端,即向消息队列中发送一条消息。
参数:
    msqid:已打开的消息队列id
    msgp:存放消息的结构体指针。
    msgflag:函数的控制属性。
    消息结构msgbuf为:
    struct msgbuf
    {
        long mtype;//消息类型
        char mtext[1];//消息正文,消息数据的首地址
    }
    msgsz:消息数据的长度。
    msgflag:
    IPC_NOWAIT: 指明在消息队列没有足够空间容纳要发送的消息时,msgsnd立即返回。
    0:msgsnd调用阻塞直到条件满足为止.(一般选这个)

  1. 从消息队列接收信息
        ssize_t msgrcv(int msqid,  struct msgbuf *msgp,  size_t msgsz,  long msgtype,  int msgflag)
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    功能:

    从队列中接收消息
参数:
    msqid:已打开的消息队列id
    msgp:存放消息的结构体指针。
    msgsz:消息的字节数,指定mtext的大小。
    msgtype:消息类型,消息类型 mtype的值。
    msgflag:函数的控制属性。
    msgflag:
        MSG_NOERROR:若返回的消息比nbytes字节多,则消息就会截短到nbytes字节,且不通知消息发送进程.
        IPC_NOWAIT:调用进程会立即返回.若没有收到消息则返回-1.
        0:msgrcv调用阻塞直到条件满足为止.
在成功地读取了一条消息以后,队列中的这条消息将被删除。

 

 

例如:简单的消息收发

#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

struct msg_buf
{
int mtype;
char data[255];

};

int main( int argc, char *argv[] )
{
key_t key;
int msgid;
int ret;
struct msg_buf msgbuf;

//get key
key = fork( ".", "a" );
printf( "key = [%x]n", key );

//create quee
msgid = msgget( key, IPC_CREATE|0666 );
if( msgid = -1 )
{
printf( "create err!n" );
return -1;

}
//以当前进程类型,非阻塞方式发送"test data"到消息队列
msgbuf.mtype = getpid();
stpcpy( msgbuf.data, "test data" );
ret = msgsnd( msgid; &msgbuf, sizeof( msgbuf.data), IPC_NOWAIT );
if( ret == -1 )
{
printf( "send err!n" );
return -1;
}

//以非阻塞方式接收数据
memset ( &msgbuf, 0x00, sizeof( msgbuf) );
ret = msgrcv( msgid, &msgbuf, sizeof( msgbuf.data), getpid(), IPC_NOWAIT );
if( ret == -1 )
{
printf( "rcv_err ret =[%d]!n", ret );
return -1;
}
printf( "receive msg = [%s]n!" , msgbuf.data );
return 0;

}

 

同一消息队列通信:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h> //要加这个头文件

struct msgbuf{
long mtype;
char mtext[100];
}; //存放消息类型和消息内容的结构体

int main()
{
key_t key;
int msgid;
struct msgbuf msg1,msg2; //msg1用来发送,msg2用来接收

key=ftok(".", 0xf0); //获得消息队列标识符
if( (msgid = msgget(key, IPC_CREAT|0666)) < 0 ) //创建一个消息队列
{
perror("msgget error");
exit(1);
}
msg1.mtype = 1; //消息类型为1,这个可以区别多个消息
memset(msg1.mtext, 0, 100); //将数组清0
strcpy(msg1.mtext, "hello"); //用strcpy给消息内容赋值
msgsnd(msgid, &msg1, strlen(msg1.mtext)+1, 0); //发送时最后加上一个‘’
printf("send %sn", msg1.mtext);

msgrcv(msgid, &msg2, 100, 1, 0); //接收1发过来的消息,存到msg2中
printf("receive %sn", msg2.mtext);

msgctl(msgid, IPC_RMID,NULL); //删除消息队列
return 0;
}

 

进程间消息队列通信:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <string.h>
#include <signal.h>

struct msgbuf{
int mtype;
char mtext[100];
};

int main()
{
key_t key;
pid_t pid;
int msgid;
struct msgbuf msg;

key=ftok(".", 0x01);
if ( (msgid = msgget(key, IPC_CREAT|0666)) <0 )
{
perror("msgget error");
exit(1);
}

//创建一个进程
if ( (pid = fork()) < 0 )
{
perror("fork error");
exit(1);
}
//子进程收信息
else if (pid==0)
{
while(1)
{
memset(msg.mtext,0,100);
msgrcv(msgid,&msg,100,2,0); //receive the msg from 2
printf("rbbb:%snaaa:",msg.mtext);
fflush(stdout);
}
exit(0);
}
//父进程发信息
else
{
while(1)
{
memset(msg.mtext,0,100);
printf("aaa:");
fgets(msg.mtext,100,stdin);
if (strncmp("bye",msg.mtext,3)==0)//如果前3个字符为bye,则退出
{
kill(pid,SIGSTOP);
exit(1);
}
msg.mtype=1;//send to 1
msg.mtext[strlen(msg.mtext)-1]='';
msgsnd(msgid,&msg,strlen(msg.mtext)+1,0);
}
}

return 0;
}

 

一、消息队列的特点 1.消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标...

linux消息队列函数

②向消息队列中发送消息

int msgget(key_t, int flag):创建和打开队列

 

原型:
int msgsnd(int msqid,struct msgbuf* msgp,int msgsz,int msgflg);

int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int flag):发送消息,msgid是消息队列的id,msgp是消息内容所在的缓冲区,msgsz是消息的大小,msgflg是标志。

 

参数含义:
–msqid参数是消息队列标识符,它是由系统调用msgget返回的;
–msgp参数是指向消息缓冲区的指针;
– 参数msgsz中包含的是消息的字节大小,但不包括消息类型的长度(4个字节);
– 参数msgflg可以设置为0(此时为忽略此参数),或者使用IPC_NOWAIT。

int msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int flag):接受消息,msgtyp是期望接收的消息类型。


返回值:
– 如果成功,返回值为0;
– 如果失败,返回值为-1

int msgctl(int msqid, int cmd, struct msqid_ds *buf):控制

linux消息队列函数

③从消息队列接收消息
函数形式:
intmsgrcv(intmsqid,structmsgbuf* msgp,int msgsz,long mtype,int msgflg);

  1. #include <sys/types.h>   
  2. #include <sys/ipc.h>   
  3. #include <sys/msg.h>   
  4. #include <stdio.h>   
  5. #include <stdlib.h>   
  6. #include <unistd.h>   
  7. #include <string.h>   
  8. #define BUFSZ 512   
  9. struct message{          //消息结构体   
  10.     long msg_type;  
  11.     char msg_text[BUFSZ];  
  12. };  
  13.   
  14. int main()  
  15. {  
  16.     int qid;  
  17.     key_t key;  
  18.     int len;  
  19.     struct message msg;  
  20.   
  21.     if((key=ftok(".",'a'))==-1)        //ftok获得一个key   
  22.     {  
  23.         perror("ftok");  
  24.         exit(1);  
  25.     }  
  26.     if((qid=msgget(key,IPC_CREAT|0666))==-1){    //创建一个消息队列   
  27.         perror("msgget");  
  28.         exit(1);  
  29.     }  
  30.     printf("opened queue %dn",qid);  
  31.     puts("Please enter the message to queue:");  
  32.     if((fgets(msg.msg_text,BUFSZ,stdin))==NULL)     // 从标准输入获取输入   
  33.     {  
  34.         puts("no message");  
  35.         exit(1);  
  36.     }  
  37.     msg.msg_type = getpid();       
  38.     len = strlen(msg.msg_text);  
  39.     if((msgsnd(qid,&msg,len,0))<0){                 //发送消息   
  40.         perror("message posted");  
  41.         exit(1);  
  42.     }  
  43.     if(msgrcv(qid,&msg,BUFSZ,0,0)<0){               //接收消息   
  44.         perror("msgrcv");  
  45.         exit(1);  
  46.     }  
  47.     printf("message is:%sn",(&msg)->msg_text);  
  48.     if((msgctl(qid,IPC_RMID,NULL))<0){              //删除消息   
  49.         perror("msgctl");  
  50.         exit(1);  
  51.     }  
  52.     exit(0);  
  53. }  

参数含义:
– 第一个参数用来指定将要读取消息的队列;
– 第二个参数代表要存储消息的消息缓冲区的地址;
– 第三个参数是消息缓冲区的长度,不包括mtype的长度,它可以按照如下的方法计算:
msgsz=sizeof(structmymsgbuf)-sizeof(long);
– 第四个参数是要从消息队列中读取的消息的类型。如果此参数的值为0,那么队列中最长时间的一条消息将返回,而不论其类型是什么

澳门新葡亰平台9411 1

头文件:

返回值:
– 如果成功,则返回复制到消息缓冲区的字节数。
– 如果失败,则返回-1。
④消息队列控制

#include <sys/types.h>

函数形式:
int msgctl(int msgqid,int cmd,struct msqid_ds* buf);

#include <sys/ipc.h>

返回值:
– 如果成功,返回值为0;
– 如果失败,返回值为-1
–cmd参数的取值:
– IPC_STAT   读取消息队列的数据结构msqid_ds,并将其存储在buf指定 的地址中。
– IPC_SET      设置消息队列的数据结构msqid_ds中的ipc_perm元素的值 。这个值取自buf参数。
–IPC_RMID 从系统内核中移走消息队列。

#include <sys/msg.h>

/*write.msg.c*/
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define BUFSIZ 512

  www.2cto.com  

struct message
{
    long msg_type;
    char msg_text[BUFSIZ];
};


int main(void)
{
    int qid;
    key_t key;
    int len;
    struct message msg;
    /*根据不同的路径和键值产生标准的key*/
    if((key=ftok(".",'a'))==-1)
    {
        perror("ftok");
         exit(1);
澳门新葡亰平台9411,    }
    /*创建消息队列*/
    if((qid=msgget(key,IPC_CREAT|0666))==-1)
    {
        perror("msgget");
        exit(1);
    }
    printf("opened queue %d n",qid);
    while(1)
    {
        /*写消息队列*/
        puts("Please enter the message to queue:");
        if((fgets((&msg)->msg_text,BUFSIZ,stdin))==NULL)
        {
            puts("no message");
            exit(1);
        }
        msg.msg_type=getpid();
        printf("message: %s  is sent!n",(&msg)->msg_text);
        len=strlen(msg.msg_text);
        /*添加消息队列*/
        if(msgsnd(qid,&msg,len,0)<0)
        {
            perror("message posted");
            exit(1);
        }
    }
    /*从系统内核中移走消息队列*/
    if((msgctl(qid,IPC_RMID,NULL))<0)
    {
        perror("msgctl");
        exit(1);
    }
    exit(0);
}
/*read_msg.c*/
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define BUFSIZ 512

1、系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

struct message
{
    long msg_type;
    char msg_text[BUFSIZ];
};

ftok原型如下:

int main(void)
{
    int qid;
    key_t key;
    int len;
    struct message msg;
    /*根据不同的路径和键值产生标准的key*/
    if((key=ftok(".",'a'))==-1)
    {
        perror("ftok");
         exit(1);
    }
    /*创建消息队列*/
    if((qid=msgget(key,IPC_CREAT|0666))==-1)
    {
        perror("msgget");
        exit(1);
    }
    printf("opened queue %d n",qid);
    while(1)
    {
        /*读取消息队列*/
        if(msgrcv(qid,&msg,BUFSIZ,0,0)<0)
        {
            perror("msgrcv");
            exit(1);
        }
        printf("message : %s   is received!n",(&msg)->msg_text);
    }
    /*从系统内核中移走消息队列*/
    if((msgctl(qid,IPC_RMID,NULL))<0)
    {
        perror("msgctl");
        exit(1);
    }
    exit(0);
}

key_t ftok( char * fname, int id )

fname就时你指定的文件名,id是子序号。

在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。

如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16 进制为0x26,则最后的key_t返回值为0x26010002。

查询文件索引节点号的方法是: ls -i

当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。

如果要确保key_t值不变,要目确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t 值,比如:

#define IPCKEY 0x111

char path[256];

    sprintf( path, "%s/etc/config.ini", (char*)getenv("HOME") );

    msgid=ftok( path, IPCKEY );[/code]

同一段程序,用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。

本文由澳门新葡亰平台9411发布于关于我们,转载请注明出处:该id值通过ftok函数得到,一、消息队列的特点

关键词:

最火资讯