成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux進程間通信——使用消息隊列

系統 Linux
Linux提供了一系列消息隊列的函數接口來讓我們方便地使用它來實現進程間的通信。它的用法與其他兩個System V PIC機制,即信號量和共享內存相似。

一、什么是消息隊列

消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。 每個數據塊都被認為含有一個類型,接收進程可以獨立地接收含有不同類型的數據結構。我們可以通過發送消息來避免命名管道的同步和阻塞問題。但是消息隊列與命名管道一樣,每個數據塊都有一個***長度的限制。

Linux用宏MSGMAX和MSGMNB來限制一條消息的***長度和一個隊列的***長度。

二、在Linux中使用消息隊列

Linux提供了一系列消息隊列的函數接口來讓我們方便地使用它來實現進程間的通信。它的用法與其他兩個System V PIC機制,即信號量和共享內存相似。

1、msgget函數

該函數用來創建和訪問一個消息隊列。它的原型為:

int msgget(key_t, key, int msgflg);

與其他的IPC機制一樣,程序必須提供一個鍵來命名某個特定的消息隊列。msgflg是一個權限標志,表示消息隊列的訪問權限,它與文件的訪問權限一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的消息隊列不存在時創建一個消息隊列,如果key所命名的消息隊列存在時,IPC_CREAT標志會被忽略,而只返回一個標識符。

它返回一個以key命名的消息隊列的標識符(非零整數),失敗時返回-1.

2、msgsnd函數

該函數用來把消息添加到消息隊列中。它的原型為:

int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);

msgid是由msgget函數返回的消息隊列標識符。

msg_ptr是一個指向準備發送消息的指針,但是消息的數據結構卻有一定的要求,指針msg_ptr所指向的消息結構一定要是以一個長整型成員變量開始的結構體,接收函數將用這個成員來確定消息的類型。所以消息結構要定義成這樣:

  1. struct my_message{   
  2.  
  3.     long int message_type;   
  4.  
  5.     /* The data you wish to transfer*/   
  6.  
  7. };   

msg_sz是msg_ptr指向的消息的長度,注意是消息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型消息類型成員變量的長度。

msgflg用于控制當前消息隊列滿或隊列消息到達系統范圍的限制時將要發生的事情。

如果調用成功,消息數據的一分副本將被放到消息隊列中,并返回0,失敗時返回-1.

3、msgrcv函數

該函數用來從一個消息隊列獲取消息,它的原型為

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);

msgid, msg_ptr, msg_st的作用也函數msgsnd函數的一樣。

msgtype可以實現一種簡單的接收優先級。如果msgtype為0,就獲取隊列中的***個消息。如果它的值大于零,將獲取具有相同消息類型的***個信息。如果它小于零,就獲取類型等于或小于msgtype的絕對值的***個消息。

msgflg用于控制當隊列中沒有相應類型的消息可以接收時將發生的事情。

調用成功時,該函數返回放到接收緩存區中的字節數,消息被復制到由msg_ptr指向的用戶分配的緩存區中,然后刪除消息隊列中的對應消息。失敗時返回-1.

4、msgctl函數

該函數用來控制消息隊列,它與共享內存的shmctl函數相似,它的原型為:

int msgctl(int msgid, int command, struct msgid_ds *buf);

command是將要采取的動作,它可以取3個值,

IPC_STAT:把msgid_ds結構中的數據設置為消息隊列的當前關聯值,即用消息隊列的當前關聯值覆蓋msgid_ds的值。

IPC_SET:如果進程有足夠的權限,就把消息列隊的當前關聯值設置為msgid_ds結構中給出的值

IPC_RMID:刪除消息隊列

buf是指向msgid_ds結構的指針,它指向消息隊列模式和訪問權限的結構。msgid_ds結構至少包括以下成員: 

  1. struct msgid_ds      
  2. {          
  3. uid_t shm_perm.uid;  
  4.         uid_t shm_perm.gid; 
  5.         mode_t shm_perm.mode; 
  6. };    

成功時返回0,失敗時返回-1.

三、使用消息隊列進行進程間通信

馬不停蹄,介紹完消息隊列的定義和可使用的接口之后,我們來看看它是怎么讓進程進行通信的。由于可以讓不相關的進程進行行通信,所以我們在這里將會編寫兩個程序,msgreceive和msgsned來表示接收和發送信息。根據正常的情況,我們允許兩個程序都可以創建消息,但只有接收者在接收完***一個消息之后,它才把它刪除。

接收信息的程序源文件為msgreceive.c的源代碼為:

  1. #include <unistd.h>   
  2.  
  3. #include <stdlib.h>   
  4.  
  5. #include <stdio.h>   
  6.  
  7. #include <string.h>   
  8.  
  9. #include <errno.h>   
  10.  
  11. #include <sys/msg.h>   
  12.  
  13.    
  14.  
  15. struct msg_st   
  16.  
  17. {   
  18.  
  19.     long int msg_type;   
  20.  
  21.     char text[BUFSIZ];   
  22.  
  23. };   
  24.  
  25.    
  26.  
  27. int main()   
  28.  
  29. {   
  30.  
  31.     int running = 1;   
  32.  
  33.     int msgid = -1;   
  34.  
  35.     struct msg_st data;   
  36.  
  37.     long int msgtype = 0; //注意1   
  38.  
  39.    
  40.  
  41.     //建立消息隊列   
  42.  
  43.     msgid = msgget((key_t)1234, 0666 | IPC_CREAT);   
  44.  
  45.     if(msgid == -1)   
  46.  
  47.     {   
  48.  
  49.         fprintf(stderr, "msgget failed with error: %d\n", errno);   
  50.  
  51.         exit(EXIT_FAILURE);   
  52.  
  53.     }   
  54.  
  55.     //從隊列中獲取消息,直到遇到end消息為止   
  56.  
  57.     while(running)   
  58.  
  59.     {   
  60.  
  61.         if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)   
  62.  
  63.         {   
  64.  
  65.             fprintf(stderr, "msgrcv failed with errno: %d\n", errno);   
  66.  
  67.             exit(EXIT_FAILURE);   
  68.  
  69.         }   
  70.  
  71.         printf("You wrote: %s\n",data.text);   
  72.  
  73.         //遇到end結束   
  74.  
  75.         if(strncmp(data.text, "end", 3) == 0)   
  76.  
  77.             running = 0;   
  78.  
  79.     }   
  80.  
  81.     //刪除消息隊列   
  82.  
  83.     if(msgctl(msgid, IPC_RMID, 0) == -1)   
  84.  
  85.     {   
  86.  
  87.         fprintf(stderr, "msgctl(IPC_RMID) failed\n");   
  88.  
  89.         exit(EXIT_FAILURE);   
  90.  
  91.     }   
  92.  
  93.     exit(EXIT_SUCCESS);   
  94.  
  95. }    

發送信息的程序的源文件msgsend.c的源代碼為:

  1. #include <unistd.h>   
  2.  
  3. #include <stdlib.h>   
  4.  
  5. #include <stdio.h>   
  6.  
  7. #include <string.h>   
  8.  
  9. #include <sys/msg.h>   
  10.  
  11. #include <errno.h>   
  12.  
  13.    
  14.  
  15. #define MAX_TEXT 512   
  16.  
  17. struct msg_st   
  18.  
  19. {   
  20.  
  21.     long int msg_type;   
  22.  
  23.     char text[MAX_TEXT];   
  24.  
  25. };   
  26.  
  27.    
  28.  
  29. int main()   
  30.  
  31. {   
  32.  
  33.     int running = 1;   
  34.  
  35.     struct msg_st data;   
  36.  
  37.     char buffer[BUFSIZ];   
  38.  
  39.     int msgid = -1;   
  40.  
  41.    
  42.  
  43.     //建立消息隊列   
  44.  
  45.     msgid = msgget((key_t)1234, 0666 | IPC_CREAT);   
  46.  
  47.     if(msgid == -1)   
  48.  
  49.     {   
  50.  
  51.         fprintf(stderr, "msgget failed with error: %d\n", errno);   
  52.  
  53.         exit(EXIT_FAILURE);   
  54.  
  55.     }   
  56.  
  57.    
  58.  
  59.     //向消息隊列中寫消息,直到寫入end   
  60.  
  61.     while(running)   
  62.  
  63.     {   
  64.  
  65.         //輸入數據   
  66.  
  67.         printf("Enter some text: ");   
  68.  
  69.         fgets(buffer, BUFSIZ, stdin);   
  70.  
  71.         data.msg_type = 1;    //注意2   
  72.  
  73.         strcpy(data.text, buffer);   
  74.  
  75.         //向隊列發送數據   
  76.  
  77.         if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)   
  78.  
  79.         {   
  80.  
  81.             fprintf(stderr, "msgsnd failed\n");   
  82.  
  83.             exit(EXIT_FAILURE);   
  84.  
  85.         }   
  86.  
  87.         //輸入end結束輸入   
  88.  
  89.         if(strncmp(buffer, "end", 3) == 0)   
  90.  
  91.             running = 0;   
  92.  
  93.         sleep(1);   
  94.  
  95.     }   
  96.  
  97.     exit(EXIT_SUCCESS);   
  98.  
  99. }    

運行結果如下: 

 

 

 

四、例子分析——消息類型

這里主要說明一下消息類型是怎么一回事,注意msgreceive.c文件main函數中定義的變量msgtype(注釋為注意1),它作為msgrcv函數的接收信息類型參數的值,其值為0,表示獲取隊列中***個可用的消息。再來看看msgsend.c文件中while循環中的語句data.msg_type = 1(注釋為注意2),它用來設置發送的信息的信息類型,即其發送的信息的類型為1。所以程序msgreceive能夠接收到程序msgsend發送的信息。

如果把注意1,即msgreceive.c文件main函數中的語句由long int msgtype = 0;改變為long int msgtype = 2;會發生什么情況,msgreceive將不能接收到程序msgsend發送的信息。因為在調用msgrcv函數時,如果msgtype(第四個參數)大于零,則將只獲取具有相同消息類型的***個消息,修改后獲取的消息類型為2,而msgsend發送的消息類型為1,所以不能被msgreceive程序接收。重新編譯msgreceive.c文件并再次執行,其結果如下: 

 

 

 

我們可以看到,msgreceive并沒有接收到信息和輸出,而且當msgsend輸入end結束后,msgreceive也沒有結束,通過jobs命令我們可以看到它還在后臺運行著。

五、消息隊列與命名管道的比較

消息隊列跟命名管道有不少的相同之處,通過與命名管道一樣,消息隊列進行通信的進程可以是不相關的進程,同時它們都是通過發送和接收的方式來傳遞數據的。在命名管道中,發送數據用write,接收數據用read,則在消息隊列中,發送數據用msgsnd,接收數據用msgrcv。而且它們對每個數據都有一個***長度的限制。

與命名管道相比,消息隊列的優勢在于,1、消息隊列也可以獨立于發送和接收進程而存在,從而消除了在同步命名管道的打開和關閉時可能產生的困難。2、同時通過發送消息還可以避免命名管道的同步和阻塞問題,不需要由進程自己來提供同步方法。3、接收程序可以通過消息類型有選擇地接收數據,而不是像命名管道中那樣,只能默認地接收。 

責任編輯:龐桂玉 來源: 嵌入式Linux中文站
相關推薦

2019-05-13 10:00:41

Linux進程間通信命令

2018-01-12 14:35:00

Linux進程共享內存

2010-01-05 10:00:48

Linux進程間通信

2013-03-28 13:14:45

AIDL進程間通信Android使用AI

2017-08-06 00:05:18

進程通信開發

2018-05-30 13:58:02

Linux進程通信

2019-05-08 11:10:05

Linux進程語言

2021-01-22 10:58:16

網絡安全進程間碼如

2021-03-11 06:01:41

Linux消息隊列

2020-11-18 09:06:04

Python

2020-11-04 07:17:42

Nodejs通信進程

2011-06-22 17:09:50

QT 進程 通信

2024-01-03 10:17:51

Linux通信

2019-06-04 09:00:00

Linux進程進程間通信

2019-11-08 14:47:49

TCPIP網絡

2016-11-28 14:11:24

ANDROID BIN通信架構

2024-05-16 08:10:17

RabbitMQ軟件通信機制

2011-06-24 14:01:34

Qt QCOP 協議

2025-04-27 03:22:00

2019-11-27 10:36:11

進程通信IPC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产乱码久久久久久蜜柚 | 国产成人精品免高潮在线观看 | 天天射影院 | 国产成人精品综合 | 欧美一二区| 国产激情毛片 | 一区二区国产精品 | 亚洲免费久久久 | 国产一区二区三区在线 | 久久免费精品视频 | 波多野结衣精品 | 欧美日韩在线观看一区二区三区 | 国产成人精品免费 | 国产成人免费 | 国产一二区视频 | 一区二区三区电影网 | 午夜视频一区 | 欧美激情在线观看一区二区三区 | 黄网站在线播放 | 91亚洲国产成人久久精品网站 | 中文字幕亚洲视频 | 久久久毛片 | 欧美日韩成人一区二区 | 欧美精品网站 | 少妇一级淫片免费播放 | 久久精品中文字幕 | 91小视频在线 | 亚洲第一天堂 | 精品欧美一区免费观看α√ | 欧美成人二区 | 中文字幕国产 | 久久久久中文字幕 | 香蕉婷婷 | 成人高潮片免费视频欧美 | 日韩国产欧美视频 | 欧美精品久久久久久久久老牛影院 | 欧美中文字幕在线 | 成人性视频免费网站 | 免费美女网站 | 久久久久国产精品一区二区 | 欧美一区二区 |