程序間通訊之共享記憶體初步

2021-07-25 14:46:40 字數 4503 閱讀 1832

共享記憶體

共享記憶體區是最快的ipc形式。一旦這樣的記憶體對映到共享它的程序的位址空間,這些程序間資料傳遞不再涉及到核心,換句話說是程序不再通過執行進入核心的系統呼叫來傳遞彼此的資料。

用管道或者訊息佇列傳遞資料

核心為每個ipc物件維護乙個資料結構

用共享記憶體傳遞資料

shmget函式

#include 

#include

#include

#include

#include

#include

#include

#include

#define err_exit(m) \

do \

while(0)

typedef

struct _t

teacher;

//沒有ipc_creat

int main01()

perror("shmget");

} return0;}

//使用ipc_creat

int main02()

perror("shmget");

} return0;}

//ipc_creat和ipc_excl在一起

int main03()

if(errno == eexist)//已經存在就報錯

err_exit("shmget");

} return

0;}

shmat函式原型

void *shmat(int shmid, const void *shmaddr, int shm***);引數

shmid: 共享記憶體標識

shmaddr:指定連線的位址

shm***:它的兩個可能取值是shm_rnd和shm_rdonly

返回值:成功返回乙個指標,指向共享記憶體第乙個節;失敗返回-1

shmaddr和shm***的組合關係對共享記憶體位址的影響

shmaddr和shm***的組合關係

共享記憶體最終位址

shmaddr為null,不管shm***

核心自動選擇乙個位址

shmaddr不為null且shm***無shm_rnd標記

則以shmaddr為連線位址。

shmaddr不為null且shm***設定了shm_rnd標記

shm***=shm_rdonly

表示連線操作用來唯讀共享記憶體

* 示例**

//shmat函式的使用

int main04()

if(errno == eexist)//已經存在就報錯

err_exit("shmget");

} //shmat讓共享記憶體可以被程序使用--在程序的位址空間就可以使用該塊記憶體--每個程序shmat以後得到的位址不一樣--屬於自己的共享記憶體位址

p = shmat(shm_id,null,0);//讓本程序鏈結到共享記憶體--得到乙個位址--共享記憶體的首位址--p

if(p ==(void*)-11)

memcpy(p,&t1,sizeof(t1));

printf("name : %s\tage:%d\n",((teacher*)p)->name,((teacher*)p)->age);

return

0;}

shmdt函式

注意:將共享記憶體段與當前程序脫離不等於刪除共享記憶體段

shmctl函式

//shmctl+shmdt刪除共享記憶體

int main05()

if(errno == eexist)//已經存在就報錯

err_exit("shmget");

} //shmat讓共享記憶體可以被程序使用--在程序的位址空間就可以使用該塊記憶體--每個程序shmat以後得到的位址不一樣--屬於自己的共享記憶體位址

p = shmat(shm_id,null,0);//讓本程序鏈結到共享記憶體--得到乙個位址--共享記憶體的首位址--p

if(p == (void*)-1)

memcpy(p,&t1,sizeof(t1));

printf("name : %s\tage:%d\n",((teacher*)p)->name,((teacher*)p)->age);

printf("please input your select:\n1-->don't delete\t2-->delete it force\n");

scanf("%d",&opt);

if(opt == 2)

else

if(opt == 1)

else

return

0;}

//如果共享記憶體被別的程式占用,連線數/引用計數不為0,則刪除共享記憶體不會立馬被刪除

//出現乙個現象---共享記憶體key值變成了0,引用計數減1,且此時的共享記憶體已經不能被其他重新shmat的程序讀取了

//只能被在刪除之前就已經shmat的程序讀取,重啟乙個程序重新shmat的時候由於key已經變為0,所以新開的程序是不能再繼續讀取共享記憶體的資料的

//只有當連線共享記憶體的所有程序都死掉linux核心才會刪除共享記憶體

//是否能直接刪除共享記憶體--關鍵是看在刪除以後有無程序鏈結到該塊記憶體--等同於shmctl+shmdt刪除之前有多少程序已經執行了shmat

//多程序中shmat和shmctl操作的時序關係不同--導致刪除共享記憶體是否能直接刪除

int main()

if(errno == eexist)//已經存在就報錯

err_exit("shmget");

} pid = fork();

if( pid == -1)

else

if(pid == 0)

printf("child p:%d\n",(int)p);

//子程序脫離並刪除共享記憶體--此時不一定直接刪除

//如果父程序在此之前已經shmat了--共享記憶體的key變為0--但因為父程序並沒有退出也沒有刪除共享記憶體--引用計數不為0--不刪除

//如果直到此時此刻,父程序還沒有shmat--沒有連線到共享記憶體--

//此時子程序可以直接刪除共享記憶體--因為再也沒有多餘的程序鏈到該塊記憶體

shmdt(p);

shmctl(shm_id,ipc_rmid,null);

//子程序結束

printf("child quit\n");

exit(0);

} wait(null);//如果wait放在這裡--程式會在父程序shmat的時候異常結束

//父程序會等待子程序刪除共享記憶體之後再shmat--

//此時共享記憶體已經被刪除,linux核心已經**該塊記憶體--

//意味著需要重新shmget一塊共享記憶體,再shmat才可以給父程序使用

//父程序在共享記憶體已經被刪除的情況下直接shmat是會core dump的

//shmat讓共享記憶體可以被程序使用--在程序的位址空間就可以使用該塊記憶體--屬於自己程序的使用者空間的記憶體位址

p = shmat(shm_id,null,0);//讓本程序鏈結到共享記憶體--得到乙個位址--共享記憶體的首位址--p

if(p == (void*)-1)

printf("parent p:%d\n",(int)p);

memcpy(p,&t1,sizeof(t1));

printf("name : %s\tage:%d\n",((teacher*)p)->name,((teacher*)p)->age);

sleep(5);

printf("please input your select:\n1-->read shm after child delete it\n2-->delete it force\n");

scanf("%d",&opt);

if(opt == 2)

else

if(opt == 1)

else

//如果wait放在這裡--程式正常執行

//父程序會在子程序刪除共享記憶體之前shmat--所以在子程序刪除共享記憶體之後還可以讀取

//wait(null);

return

0;}

程序間通訊之共享記憶體

此程式實現兩個普通程序間通過共享記憶體來進行通訊,共享記憶體能夠進行大資料量的通訊,這一點事訊息佇列無法比擬的。在這裡同時使用了訊號量來保證兩個程序間的讀寫同步。傳送端源 include include include include include include include include ...

程序間通訊之共享記憶體

1.概念 共享記憶體就是多個程序的位址空間對映到同乙個物理記憶體,多個程序都能看到這塊物理記憶體,共享記憶體可以提供給伺服器程序和客戶程序之間進行通訊,不需要進行資料的複製,所以速度最快。2.共享記憶體操作需要的函式 1 我們需要利用ftok函式生成key識別符號。key t ftok const ...

程序間通訊之共享記憶體

ipc物件這個概念需要理解,因為好多書或者料就直接說ipc就是共享記憶體 訊息佇列 訊號燈集,其實ipc是一種機制,這種機制提供了程序間通訊的通道,那麼為什麼加個system v呢,那是因為在system v 系統的四個版本中提出的程序通訊的ipc這種機制。所以叫做system v ipc。目前li...