1. 程式人生 > >Linux關於程序間通訊共享記憶體

Linux關於程序間通訊共享記憶體

共享記憶體概念

共享記憶體允許兩個不相關的程序去訪問同一部分邏輯記憶體 如果需要在兩個執行中的程序之間傳輸資料,共享記憶體將是一種效率極高的解決方案

共享記憶體是由IPC為一個程序建立的一個特殊的地址範圍,它將出現在程序的地址空間中。 其他程序可以把同一段共享記憶體段“連線到”它們自己的地址空間裡去。 所有程序都可以訪問共享記憶體地址,就好像它們是有malloc分配的一樣 如果一個程序向這段共享記憶體寫了資料,所做的改動會立刻被有權訪問同一段共享記憶體的其他程序看到

關於共享記憶體的操作

以下程式碼建立一塊共享記憶體

#include<stdio.h> #include<sys/types.h> #include<sys/shm.h> #include<sys/ipc.h> #include<string.h>

int main() {     int shmid = shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);     printf("shmid = %d\n",shmid);         return 0; }

但實際我們要這樣建立,先刪除之前可能存在的記憶體,在建立一塊自己的記憶體

#include<stdio.h> #include<sys/types.h> #include<sys/shm.h> #include<sys/ipc.h> #include<string.h>

int main() {     int shmid = shmget((key_t)1234,0,0);     if(shmid > 0)     {         shmctl(shmid,IPC_RMID,0);         shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);         printf("shmid = %d\n",shmid);     }     return 0; }

下面演示為什麼要這樣做

#include<stdio.h> #include<sys/types.h> #include<sys/shm.h> #include<sys/ipc.h> #include<string.h>

int main() {  //   int shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);     int shmid = shmget((key_t)1234,0,0);     if(shmid > 0)     {         shmctl(shmid,IPC_RMID,0);         shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);     }     void *ptr = shmat(shmid,NULL,0);     memcpy(ptr,"helloworld",strlen("helloworld"));     printf("shmid = %d\n",shmid);     return 0; }

先註釋掉第一段程式碼是最開始實現的開闢共享記憶體,剩下的是第二種方法實現開闢共享記憶體,我們執行程式,不會出錯

當我們把第一段程式碼釋放掉,下面實現的第二種方法註釋起來

#include<stdio.h> #include<sys/types.h> #include<sys/shm.h> #include<sys/ipc.h> #include<string.h>

int main() {     int shmid = shmget((key_t)1234,4096,IPC_CREAT|0766);     //int shmid = shmget((key_t)1234,0,0);     //if(shmid > 0)     //{     //    shmctl(shmid,IPC_RMID,0);     //    shmid = shmget((key_t)1234,2048,IPC_CREAT|0766);     //}     void *ptr = shmat(shmid,NULL,0);     memcpy(ptr,"helloworld",strlen("helloworld"));     printf("shmid = %d\n",shmid);     return 0; }

出現以下結果:

我們來分析一下,仔細看紅色的那一段程式碼,我們把開闢的記憶體開闢成4096,當我們之前的記憶體沒有清掉,此時我們使用共享記憶體是一樣的,但是開闢出來更大的空間,此時使用shmat對映邏輯地址就會出現段錯誤。

所以當我們進行伺服器開發的時候,如果同組成員之前開闢了共享記憶體ID為1234,而我們後面也開闢了ID為1234的共享記憶體,但是我們不知道他開闢了多大,如果一旦開闢不一樣大,進行對映邏輯地址的時候就會出錯。避免這樣的事情發生,我們在開闢共享記憶體之前,對共享記憶體進行刪除,再進行建立,就會避免這樣的事情發生。