1. 程式人生 > >linux 實現共享內存同步

linux 實現共享內存同步

def 利用 reat 控制 six 初始 pri 程序 其中

本文主要對實現共享內存同步的四種方法進行了介紹。

共享內存是一種最為高效的進程間通信方式,進程可以直接讀寫內存,而不需要任何數據的拷貝。它是IPC對象的一種。

為了在多個進程間交換信息,內核專門留出了一塊內存區,可以由需要訪問的進程將其映射到自己的私有地址空間。進程就可以直接讀寫這一內存區而不需要進行數據的拷貝,從而大大提高的效率。

同步(synchronization)指的是多個任務(線程)按照約定的順序相互配合完成一件事情。由於多個進程共享一段內存,因此也需要依靠某種同步機制,如互斥鎖和信號量等 。

信號燈(semaphore),也叫信號量。它是不同進程間或一個給定進程內部不同線程間同步的機制。信號燈包括posix有名信號燈、 posix基於內存的信號燈(無名信號燈)和System V信號燈(IPC對象)

方法一、利用POSIX有名信號燈實現共享內存的同步

有名信號量既可用於線程間的同步,又可用於進程間的同步。

兩個進程,對同一個共享內存讀寫,可利用有名信號量來進行同步。一個進程寫,另一個進程讀,利用兩個有名信號量semr, semw。semr信號量控制能否讀,初始化為0。 semw信號量控制能否寫,初始為1。

讀共享內存的程序示例代碼如下

semr = sem_open("mysem_r", O_CREAT | O_RDWR , 0666, 0);
if (semr == SEM_FAILED)
{
printf("errno=%d\n", errno);
return -1;
}

semw = sem_open("mysem_w", O_CREAT | O_RDWR, 0666, 1);
if (semw == SEM_FAILED)
{
printf("errno=%d\n", errno);
return -1;
}

if ((shmid = shmget(key, MAXSIZE, 0666 | IPC_CREAT)) == -1)
{
perror("semget");
exit(-1);
}

if ((shmadd = (char *)shmat(shmid, NULL, 0)) == (char *)(-1))
{
perror("shmat");
exit(-1);
}

while (1)
{
em_wait(semr);
printf("%s\n", shmadd);
sem_post(semw);
}

寫共享內存的程序示例代碼如下

。。。。。。
//同讀的程序
while (1)
{
sem_wait(semw);
printf(">");
fgets(shmadd, MAXSIZE, stdin);
sem_post(semr);
}

方法二、利用POSIX無名信號燈實現共享內存的同步

POSIX無名信號量是基於內存的信號量,可以用於線程間同步也可以用於進程間同步。若實現進程間同步,需要在共享內存中來創建無名信號量。

因此,共享內存需要定義以下的結構體。

typedef struct
{
sem_t semr;
sem_t semw;
char buf[MAXSIZE];
}SHM;

讀、寫程序流程如下圖所示。

技術分享

技術分享

方法三、利用System V的信號燈實現共享內存的同步

System V的信號燈是一個或者多個信號燈的一個集合。其中的每一個都是單獨的計數信號燈。而Posix信號燈指的是單個計數信號燈

System V 信號燈由內核維護,主要函數semget,semop,semctl 。

一個進程寫,另一個進程讀,信號燈集中有兩個信號燈,下標0代表能否讀,初始化為0。 下標1代表能否寫,初始為1。

程序流程如下:

技術分享

寫的流程和前邊的類似。

方法四、利用信號實現共享內存的同步

信號是在軟件層次上對中斷機制的一種模擬,是一種異步通信方式。利用信號也可以實現共享內存的同步。

思路:

reader和writer通過信號通信必須獲取對方的進程號,可利用共享內存保存雙方的進程號。

reader和writer運行的順序不確定,可約定先運行的進程創建共享內存並初始化。

利用pause, kill, signal等函數可以實現該程序(流程和前邊類似)。

linux 實現共享內存同步