进程间通信——消息队列

进程间通信——消息队列

  1. 什么是消息队列:消息队列是一种用于进程间通信的一种方式,可用于任意进程之间的通信,消息队列的实现原理就是存在内核中的链表,由消息队列标识符来进行操作;
  2. 消息队列的特点:用于任意进程间的通信,可以是双向的,传输的数据是有格式的;

  多进程网络交叉通信时选用消息队列为最佳;

  能实现 大规模数据的通信;

  1. 实现消息队列的API:

第一个: int msgid = msgget(key, 0664 | IPC_CREAT);

第二个:key_t key = ftok("./b", 'b');

       (文件路径,装在文件中的标识符、只识别低八位)

        返回值是由文件路径和文件标识符合成的key值,为整形

第三个: msgsnd(msgid, buf, sizeof(struct msgbuf), 0);

    (消息队列标识符,返送信息的结构体,结构体大小,标志位设置阻塞或非阻塞方式默认为0、非阻塞)

第四个:msgrcv(msgid, buf1, sizeof(struct msgbuf), 1, 0);

(消息队列标识符,接受信息的结构体,结构体大小,需要接受结构体的id,标志位设置阻塞或非阻塞方式默认为0、非阻塞)

msgget函数:获得消息队列的标识符

 Int msgget(key, mode);

返回值是一个消息队列的标识符,定义一个int msgid来接返回值,相当于文件中的fd;

第一个参数是消息队列的键值,用于判断消息队列是否已经被创建;

第二个参数是消息队列模式标识符,如果单独使用IPC_CREAT 标志,msgget()函数要么返回一个已经存在的消息队列对象的标识符,要么返回一个新建立的消息队列对象的标识符。如果将IPC_CREAT 和IPC_EXCL标志一起使用,msgget()将返回一个新建的消息对象的标识符,或者返回-1 如果消息队列对象已存在。IPC_EXCL 标志本身并没有太大的意义,但和IPC_CREAT 标志一起使用可以用来保证所得的消息队列对象是新创建的而不是打开的已有的对象。

  同时,权限控制符可以用 “ | ”或符号与模式标识符连接,作为第二个参数使用,用来修饰消息队列的权限:

举例

msgget(key,IPC_CREAT|0777)

创建一个权限为0777到消息队列

创建一个所有用户都可以读、写、执行的队列,因为读操作的数字代号是4,写是2,执行是1,7=4+2+1,四位数字分别代表特殊权限位,拥有者位,同组用户位,其余用户位

  1. 参考代码:msg.c 实现父子进程之间的消息的收发

 #include

 #include

 #include

 

 #include

 #include

 #include

 

 #include

 #include

 #include

 #include

 

 struct msgbuf

 {

     long id;

     char msg[1024];

 };

 

 int main()

 {

 

     int msgid;

     open("./b", O_CREAT | O_RDWR);

 

     key_t key = ftok("./b", 'b');

 

     msgid = msgget(key, 0664 | IPC_CREAT);

     if (msgid < 0)

     {

         perror("creat msg queue error !");

         exit(1);

     }

 

     pid_t pid;

 

     pid = fork();

     if (pid < 0)

     {

         perror("fork error !");

         exit(1);

     }

 

     else if (pid == 0)

     {

         struct msgbuf *buf1;

         buf1 = (struct msgbuf *)malloc(sizeof(struct msgbuf));

 

         while (1)

         {

 

             memset(buf1, 0, sizeof(struct msgbuf));

 

             msgrcv(msgid, buf1, sizeof(struct msgbuf), 1, 0);

            printf("recv :%s\n", buf1->msg);

        }

    }

    else if (pid > 0)

    {

        //sleep(1);

        struct msgbuf *buf ;

        //int i = 0;

 

        while (1)

        {

            buf = (struct msgbuf *)malloc(sizeof(struct msgbuf));

            if (buf == NULL)

            {

                printf("malloc error!");

                exit(1);

            }

            memset(buf, 0, sizeof(struct msgbuf));

            scanf("%s", buf->msg);

            buf->id = 1;

            msgsnd(msgid, buf, sizeof(struct msgbuf), 0);

        }

 

    }

 

 

    return 0;

}

 

你可能感兴趣的:(C/C++,liunx系统编程,liunx系统编程)