進程間ipC通信的三大主題,消息隊列,信號量,共享內存,我們接下來說一說共享內存,共享內存可以提供給服務器進程和客戶進程之間進行通信,不需要進行數(shù)據(jù)的復制,所以速度最快,只需要讓兩個進程通過頁表映射到同一塊物理內存即可,這樣,這塊物理內存是兩個進程都能看到的,這樣當一個進程進行寫操作,另外的一個進程也就可以做讀操作。所以問題關鍵也就是給出一個特定的存儲區(qū)。通常情況下,我們需要確保一個進程在寫的時候,另外一個進程不能去讀,所以我們可以使用信號量進行共享內存訪問。


首先我們利用ftok函數(shù)生成key標識。
key_t ftok(const char *pathname, int PRoj_id);然后我們使用shmget函數(shù),這個函數(shù)可以進行創(chuàng)建共享內存。
int shmget(key_t key, size_t size, int shmflg);在這你要看好,這個size是需要進行申請的共享內存的大小,需要注意的是,操作系統(tǒng)為你提供的時候是按照頁來提供的,因為是按照頁提供的,所以size為4k的整數(shù)倍,然后shmflg和信號量以及消息隊列的類似,如果要創(chuàng)建新的共享內存,那么就是使用IPC_CREATE,IPC_EXCL。如果是已存在的,那么只需要使用IPC_CREATE或者傳0。
創(chuàng)建好共享的內存以后,這個時候我們就應該考慮的是讓進程去掛接共享內存。
void *shmat(int shmid, const void *shmaddr, int shmflg);掛接共享內存,shmflg一般表示什么方式進行掛接,一般都是取0,shmid是掛接的進程號。這個函數(shù)返回的是一個地址,我們可以想一下使用malloc的時候如何使用的,這個和那個類似。
當一個進程不需要共享內存的時候,這個時候就需要去關聯(lián),
int shmdt(const void *shmaddr);這個參數(shù)就是我們掛接以后返回的地址。
我們可以使用函數(shù)銷毀共享內存,
int shmctl(int shmid, int cmd, struct shmid_ds *buf);上面的這個函數(shù)用來控制共享內存的操作,我們可以用它來刪除共享內存,當cmd取IPC_RMID的時候就可以刪除共享內存,另外我們也可以使用命令來進行操作ipcrm -m xxx 這樣也可以進行銷毀共享內存。
共享內存并沒有提供互斥和同步機制,所以一般都是我們自己來做這個,可以使用信號量保證互斥,共享內存一般來提供對大塊內存區(qū)域的訪問,因為共享內存不想IPC另外兩個一樣需要拷貝和搬遷,所以共享內存是最快的,所以使用也比較多。
對于一個共享內存,實現(xiàn)也應用了引用計數(shù)的原理,當進程脫離了共享內存區(qū)之后,計數(shù)器會減一,只有當計數(shù)器變?yōu)?的時候,就是沒有任何進程來使用這個共享內存區(qū),這個時候共享內存才會被刪除,當一個進程終止的時候,它所附加的共享內存區(qū)都會自動脫離。
下面的例子是服務器進程進行創(chuàng)建共享共享內存,然后掛接,客戶進程是得到關聯(lián)共享內存,然后客戶進程一秒發(fā)一個a,這個時候服務器進程接受到,打印,從而實現(xiàn)共享內存。
comm.h
#ifndef __COMM_H_#define __COMM_H_#include<stdio.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#define PATHNAME "."#define PROJID 0x6666#define SIZE 4096*1int Comm_Shm(int flags);int Create_Shm();int Get_Shm();int Destory_Shm(int shmid);char *At_Shm(int shmid);int Dt_Shm(char *mem_addr);#endif //!__COMM_H_comm.c
#include"comm.h"int Comm_Shm(int flags){ key_t shmkey=ftok(PATHNAME,PROJID); if(shmkey<0) { perror("ftok"); return -1; } printf("sda"); int shmid=shmget(shmkey,SIZE,flags); if(shmget<0) { perror("shmget"); return -2; } printf("create"); return shmid;}int Create_Shm(){ return Comm_Shm(IPC_CREAT|IPC_EXCL|0666);}int Get_Shm(){ return Comm_Shm(0);}int Destory_Shm(int shmid){ int ret=shmctl(shmid,IPC_RMID,NULL); if(ret<0) { perror("shmctl"); return -1; } return 0;}char* At_Shm(int shmid){ char *shm=(char *)shmat(shmid,NULL,0); return shm;}int Dt_Shm(char *mem_addr){ int ret =shmdt(mem_addr); return 0;}client.c
#include"comm.h"int main(){ int shmid=Get_Shm(); char *add=At_Shm(shmid); printf("physic address:%s",add); int i=0; while(1) { sleep(1); add[i++] = 'a'; i %= (SIZE-1); add[i]='/0'; } Dt_Shm(add); return 0;}server.c
#include"comm.h"int main(){ int shmid=Create_Shm(); sleep(5); char *add=At_Shm(shmid); while(1) { sleep(1); printf("%s/n",add); } sleep(5); Dt_Shm(add); Destory_Shm(shmid); return 0;}新聞熱點
疑難解答