1. 程式人生 > >linux實現共享記憶體同步的四種方法

linux實現共享記憶體同步的四種方法

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

共享記憶體是一種最為高效的程序間通訊方式,程序可以直接讀寫記憶體,而不需要任何資料的拷貝。它是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等函式可以實現該程式(流程和前邊類似)。