常見進程間的幾種通信方式以及使用注意點

常見進程間的幾種通信方式以及使用注意點

通常情況下進程間的通信方式主要有以下幾點:

此處只是介紹相關工作過程及概念,具體代碼,網上一抓一大片,可以自己看。

1、管道:

管道通常分類兩種,一種有名管道,一種無名管道無名管道:主要用於父子進程間的通信方式,主要的數據方式是一般是通過一個二維數組來進行通信,比如int pipefd[2],pipefd[0]主要是用來讀數據,pipefd[1]主要是用來寫數據。有名管道:也叫命名管道,這個主要是應用於非父子進程之間的一種數據通信方式,通常管道的使用過程總共分爲三步:第一,創建管道,需要指定管道文件,第二步,打開管道文件,通常會有兩種常見方式,以阻塞的方式打開或者非阻塞的方式開,第三步,就是管道的寫,也會兩種常見方式,以阻塞的方式寫或者非阻塞的方式寫,其中阻塞的讀寫指的是在讀或者寫的時候必須有一個個進程在寫或者讀操作。管道主要是進程間數據同步的一種方式,比如一個寫數據,另一個讀數據。

2、信號量

信號量也是常見的進程直接的一種數據共享方式,信號量的操作通常也是分爲了三步,第一步創建信號量semget,這裏面主要是需要確定key,第二步是初始化信號量semctl其中需要注意的就是第二個參數,一般使用0,表示這個一個唯一的信號量,第二個參數semun,一般採用默認值,這個聯合結構體一般會在sem.h頭文件中進行定義,可以直接使用即可,有關信號量的操作主要是第三步,就是信號量的操作了semop,這個裏面主要是使用了

struct sembuf
{ 
    short sem_num;
    short sem_op;
    short sem_flg;
}

第一個參數,表示信號量編號,除非你使用一組信號量,一般使用0;第二個參數是信號量值的改變操作即P(+1)和V(-1)操作,第三個參數一般是SEM_UNDO,使得系統跟蹤當前這個信號量使用情況,如果在當前進程結束情況下,這個信號量沒有進行釋放,則由系統自動釋放該進程持有的這個信號量。信號量主要是進程間對於臨界區代碼權限訪問控制的一種方式,確保了唯一訪問以及操作性。

3、消息隊列

消息隊列在使用上與管道有很多相似的地方,但是比管道使用起來方便了很多,減少了管道的打開和關閉的操作,但是消息隊列仍然沒有解決在使用管道時遇見的管道滿時的阻塞問題,消息隊列與管道不同之處在於它獨立於發送和接受進程,管道的阻塞模式則需要依賴於進程的發送和接收。消息隊列使用的方式一般也是分爲三步:

  • 第一步:創建消息隊列msgget
  • 第二步:發送消息,即把消息添加到消息隊列中去使用msgsnd(int msgid,const void *msg_pstr, size_t msg_sz, int msgflg)函數,主要參數需要注意的是第二個參數msg_pstr指針,這個消息指針的第一個參數必須是以一個長整型的成員變量開始,最後一個msgflg標示,主要是控制在消息隊列滿或者消息隊列達到系統範圍的限制時將要發生的事情,如果是IPC_NOWAIT,則函數立即返回,不發送消息,且返回值爲-1,如果該標誌位被清除,則發送進程將掛起,等待消息隊列騰出空間。
  • 第三步:就是消息接受函數msgrcv(int msgid, void *msg_pstr, size_t msg_sz, long int msgtype, int msgflg) ,msg_pstr跟上面的一樣,主要是msgtype標示接受消息的優先級,如果爲0標示接受隊列中第一個可用的消息,如果大於零,獲取具有相同消息類型的第一個消息,msgflg用於控制隊列中沒有相應類型消息時候的操作,如果是IPC_NOWAIT則函數立即返回並且返回-1,如果IPC_NOWAIT被清除,則進程會掛起一直等待一小相應的類型消息出現爲止。

4、共享內存

共享內存是在進程這幾個通信方式中速度以及效率最高的一種方式,使用操作一般也分爲三部分,第一步:創建共享內存,主要是設置共享內存的key以及大小,第二步綁定共享內存到指定內存地址,一般默認使用系統自己選擇的地址,第三步:有兩種操作方式1、shmdt將共享內存從當前進程剝離掉,但是未刪除它,2、shmctl可以刪除共享內存,直接物理刪除該內存段。

進程間數據同步方式一般使用的都是共享內存,主要原因就是因爲高效,但是共享內存在使用的時候有一個問題就是它無法確保數據的唯一性,沒有提供數據同步的機制,通常情況下結合信號量或者互斥鎖來進行數據的同步,比如使用互斥鎖的時候,數據內容的定義如下:

struct sm_msg  
{  
    int flag;  
    pthread_mutex_t    sm_mutex;  
    char buf[SM_BUF_SIZE];  
}; 

在使用之前需要先解釋一下互斥鎖的使用情況。

經常使用的互斥鎖是線程內的互斥鎖,比如這種使用方式
初始化鎖: int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
加鎖:int pthread_mutex_lock(pthread_mutex *mutex);
解鎖:int pthread_mutex_unlock(pthread_mutex *mutex);
銷燬鎖: int pthread_mutex_destroy(pthread_mutex *mutex);
對於mutexattr參數默認都會使用NULL,表示使用互斥鎖的默認屬性,表示爲快速互斥鎖,單互斥鎖還有一種是進程互斥鎖。

簡單在此介紹下進程互斥鎖的使用

pthread_mutex_attr_t *mutexattr;
初始化互斥鎖pthread_mutexattr_init(&mattr),
屬性的缺省值爲 PTHREAD_PROCESS_PRIVATE。 該值表示可以在進程內使用經過初始化的互斥鎖。mattr 範圍可能的值爲

  • PTHREAD_PROCESS_PRIVATE
  • PTHREAD_PROCESS_SHARED。

PTHREAD_PROCESS_PRIVATE 是缺省值。PTHREAD_PROCESS_PRIVATE表示由同一進程所創建的線程才能使用,要在多個進程中的線程之間共享互斥鎖,可以在共享內存中創建互斥鎖,並將pshared屬性設置爲 PTHREAD_PROCESS_SHARED,
通常使用pthread_mutexattr_setpshared來設置屬性
pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared);

大致介紹完線程互斥鎖,接下來說下如何使用該互斥鎖;

使用的過程大致跟線程互斥鎖使用方式一致,需要注意的是在調用pthread_mutex_init()的時候,需要使用pthread_mutex_init(sm_msg->sm_mutex, mutexatrr)的方式來初始化互斥鎖,這樣就可確保在進程中的數據的互斥性。

還有一種共享內存的同步方式就是使用信號量,具體使用過程如下介紹:

key_t semkey;
key_t shmkey;
//創建共享內存
shmid=shmget(shmkey,1024,0666|IPC_CREAT);
//創建信號量
semid=semget(semkey,1,0666|IPC_CREAT);
union semun{
int val;
struct semid_ds *buf;
unsignedshort*array;
}sem_u;
sem_u.val=1;/*設置變量值*/
semctl(semid,0,SETVAL,sem_u);//初始化信號量,設置第0個信號量
對於信號量P操作
共享內存操作
對於信號量V操作

以上就是有關進程間通信的常見的四種方式的概括,當然還有套接字的使用,下次再補充

多線程操作總結:http://blog.csdn.net/bingshiwuyu/article/details/78768515

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章