共享內存
共享內存是被多個進程共享的一部分物理內存。共享內存是進程間共享數據的一種最快的方法,一個進程向共享內存區域寫入了數據,共享這個內存區域的所有進程就可以立刻看到其中的內容。原理圖如下:
共享內存的實現分爲兩個步驟:
一、 創建共享內存,使用shmget函數。
二、 映射共享內存,將這段創建的共享內存映射到具體的進程空間去,使用shmat函數。
創建共享內存
int shmget(key_t key ,int size,int shmflg)
key標識共享內存的鍵值:0/IPC_PRIVATE。當key的取值爲IPC_PRIVATE,則函數shmget將創建一塊新的共享內存;如果key的取值爲0,而參數中又設置了IPC_PRIVATE這個標誌,則同樣會創建一塊新的共享內存。
返回值:如果成功,返回共享內存表示符,如果失敗,返回-1。
映射共享內存
int shmat(int shmid,char *shmaddr,int flag)
參數:
shmid:shmget函數返回的共享存儲標識符
flag:決定以什麼樣的方式來確定映射的地址(通常爲0)
返回值:
如果成功,則返回共享內存映射到進程中的地址;如果失敗,則返回-1。
共享內存解除映射
當一個進程不再需要共享內存時,需要把它從進程地址空間中多裏。
int shmdt(char *shmaddr)
貢獻內存實例如下:
實驗要求:創建兩個進程,在A進程中創建一個共享內存,並向其寫入數據,通過B進程從共享內存中讀取數據。
chm_com.h函數
- #define TEXT_SZ 2048
- struct shared_use_st
- {
- int written_by_you;
- char some_text[TEXT_SZ];
- };
讀取進程:
- /**********************************************************
- *實驗要求: 創建兩個進程,通過共享內存進行通訊。
- *功能描述: 本程序申請和分配共享內存,然後輪訓並讀取共享中的數據,直至
- * 讀到“end”。
- *日 期: 2010-9-17
- *作 者: 國嵌
- **********************************************************/
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include "shm_com.h"
- /*
- * 程序入口
- * */
- int main(void)
- {
- int running=1;
- void *shared_memory=(void *)0;
- struct shared_use_st *shared_stuff;
- int shmid;
- /*創建共享內存*/
- shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
- if(shmid==-1)
- {
- fprintf(stderr,"shmget failed\n");
- exit(EXIT_FAILURE);
- }
- /*映射共享內存*/
- shared_memory=shmat(shmid,(void *)0,0);
- if(shared_memory==(void *)-1)
- {
- fprintf(stderr,"shmat failed\n");
- exit(EXIT_FAILURE);
- }
- printf("Memory attached at %X\n",(int)shared_memory);
- /*讓結構體指針指向這塊共享內存*/
- shared_stuff=(struct shared_use_st *)shared_memory;
- /*控制讀寫順序*/
- shared_stuff->written_by_you=0;
- /*循環的從共享內存中讀數據,直到讀到“end”爲止*/
- while(running)
- {
- if(shared_stuff->written_by_you)
- {
- printf("You wrote:%s",shared_stuff->some_text);
- sleep(1); //讀進程睡一秒,同時會導致寫進程睡一秒,這樣做到讀了之後再寫
- shared_stuff->written_by_you=0;
- if(strncmp(shared_stuff->some_text,"end",3)==0)
- {
- running=0; //結束循環
- }
- }
- }
- /*刪除共享內存*/
- if(shmdt(shared_memory)==-1)
- {
- fprintf(stderr,"shmdt failed\n");
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- }
寫入進程:
- /**********************************************************
- *實驗要求: 創建兩個進程,通過共享內存進行通訊。
- *功能描述: 本程序申請了上一段程序相同的共享內存塊,然後循環向共享中
- * 寫數據,直至寫入“end”。
- *日 期: 2010-9-17
- *作 者: 國嵌
- **********************************************************/
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include "shm_com.h"
- /*
- * 程序入口
- * */
- int main(void)
- {
- int running=1;
- void *shared_memory=(void *)0;
- struct shared_use_st *shared_stuff;
- char buffer[BUFSIZ];
- int shmid;
- /*創建共享內存*/
- shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
- if(shmid==-1)
- {
- fprintf(stderr,"shmget failed\n");
- exit(EXIT_FAILURE);
- }
- /*映射共享內存*/
- shared_memory=shmat(shmid,(void *)0,0);
- if(shared_memory==(void *)-1)
- {
- fprintf(stderr,"shmat failed\n");
- exit(EXIT_FAILURE);
- }
- printf("Memory attached at %X\n",(int)shared_memory);
- /*讓結構體指針指向這塊共享內存*/
- shared_stuff=(struct shared_use_st *)shared_memory;
- /*循環的向共享內存中寫數據,直到寫入的爲“end”爲止*/
- while(running)
- {
- while(shared_stuff->written_by_you==1)
- {
- sleep(1);//等到讀進程讀完之後再寫
- printf("waiting for client...\n");
- }
- printf("Ener some text:");
- fgets(buffer,BUFSIZ,stdin);
- strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
- shared_stuff->written_by_you=1;
- if(strncmp(buffer,"end",3)==0)
- {
- running=0; //結束循環
- }
- }
- /*刪除共享內存*/
- if(shmdt(shared_memory)==-1)
- {
- fprintf(stderr,"shmdt failed\n");
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- }
3 . 在一個終端中運行shm1,在另一個終端中運行shm2.當shm1運行起來之後,由於共享內存中沒有數據可讀,會處於等待狀態
[root@localhost 2-4-4]# ./shm1
Memory attached at B7F9A000
/***阻塞***/
再向shm2運行的終端輸入字符串
[root@localhost 2-4-4]# ./shm2
Memory attached at B7FD8000
Enter some text:Impossible is nothing
waiting for client。。。
waiting for client。。。
Enter some text:Anything is possible
waiting for client。。。
Ener some text:end
[root@localhost 2-4-4]#
shm1能夠逐個從共享內存中巴他們讀出來,知道雙方暈倒字符串"end"後,兩個程序都退出。
[root@localhost 2-4-4]# ./shm1
Memory attached at B7F9A000
You write:Impossible is nothing
You write:Anything is possible
You write:end
[root@localhost 2-4-4]#
以上運行過程中,紅色表示在終端1中運行的結果,藍色表示在終端2裏面運行的結果。