❶ linux兩個進程間共享內存通信都需要調用shmget函數么
兩個進程都需要調用shmget函數,是根據key值來實現訪問同一個共享內存的。
函數原型:int shmget(key_t key, size_t size, int shmflg)
由於是兩個進程訪問,最好是做兩手准備:
1,先創建,若創建成功,可以直接使用。
2,若創建失敗--此時,很可能另一個進程已經創建成功了,就不能再創建了。此時,就改為只是獲取。
示例代碼如下:
int mid = shmget(key, size, IPC_CREAT | 0660);
if(mid < 0){
mid = shmget(key, 0, 0);
}
❷ LINUX下系統編程,多進程間數據共享,即共享變數
共享內存相關的API怎麼使用不難:
1. 首先調用shmget分配一個新的共享內存,這里你可以指定其大小,如果你要分配一個整形,那你可以將size參數設置成4,如果你要共享一個結構體那就將size參數設置成你的結構體大小,操作系統不關心你要共享什麼,它只關心你要分配多少個位元組的區間。而且實際上操作系統會將你要求的大小按照內存頁面的大小進行對齊,也就是說它可能實際上給你分配若干個頁面的物理存儲空間,只要這個空間能夠容納你所指定的大小就ok了。它的第三個參數是關於一些訪問許可權設置的,要講起來太長,建議自己搜索一下,或者用man查查幫助。總之,調用完shmget以後系統會給你創建一段共享內存,然後返回給你一個shmid,也就是這個共享內存的標識,你可以理解為給它取了個名字。
2. 接著調用shmat將這段共享內存映射到你的進程的虛擬地址空間上。這個函數的第一個參數就是你之前調用shmget創建的共享內存的名字shmid;第二個參數是個指針,指向你的進程虛存空間中的某個地址,你可以通過傳入一個確定的地址強行要求操作系統將共享內存映射到你指定的虛存地址上(可能會失敗,如果你指定的虛擬地址空間已經映射了別的物理存儲空間),也可以通過傳入0地址讓系統給你選擇一個合適的地址(它會通過返回值把地址返回給你)。第三個參數則允許你指定一些特殊的標志位,還是那句話,太復雜自己搜索一下看看,一般應用不需要用到。
至於例子嘛你可以看看下面這個鏈接:
http://ke..com/view/3025906.htm
另外,你要知道只用共享內存是不互斥的,你必須結合信號量一起使用才能防止互斥問題的出現。如果你共享的只是一個整形變數可能問題不大,因為對頁面對齊的整形變數的讀寫都是原子操作,但如果你共享的是個復雜的結構體就得小心了。
❸ linux 進程間通信的幾種方式
1管道(Pipe)及有名管道(named pipe):管道可用於具有親緣關系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關系進程間的通信;
2信號(Signal):信號是比較復雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還可以發送信號給進程本身;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD為了實現可靠信號機制,又能夠統一對外介面,用sigaction函數重新實現了signal函數);
3報文(Message)隊列(消息隊列):消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠許可權的進程可以向隊列中添加消息,被賦予讀許可權的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式位元組流以及緩沖區大小受限等缺點。
4共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
5信號量(semaphore):主要作為進程間以及同一進程不同線程之間的同步手段。
6套介面(Socket):更為一般的進程間通信機制,可用於不同機器之間的進程間通信。起初是由Unix系統的BSD分支開發出來的,但現在一般可以移植到其它類Unix系統上:Linux和System V的變種都支持套接字。
❹ linux共享內存和mmap的區別
共享內存的創建
根據理論:
1. 共享內存允許兩個或多個進程共享一給定的存儲區,因為數據不需要來回復制,所以是最快的一種進程間通信機制。共享內存可以通過mmap()映射普通文件(特殊情況下還可以採用匿名映射)機制實現,也可以通過系統V共享內存機制實現。應用介面和原理很簡單,內部機制復雜。為了實現更安全通信,往往還與信號燈等同步機制共同使用。
mmap的機制如:就是在磁碟上建立一個文件,每個進程存儲器裡面,單獨開辟一個空間來進行映射。如果多進程的話,那麼不會對實際的物理存儲器(主存)消耗太大。
shm的機制:每個進程的共享內存都直接映射到實際物理存儲器裡面。
結論:
1、mmap保存到實際硬碟,實際存儲並沒有反映到主存上。優點:儲存量可以很大(多於主存)(這里一個問題,需要高手解答,會不會太多拷貝到主存裡面???);缺點:進程間讀取和寫入速度要比主存的要慢。
2、shm保存到物理存儲器(主存),實際的儲存量直接反映到主存上。優點,進程間訪問速度(讀寫)比磁碟要快;缺點,儲存量不能非常大(多於主存)
使用上看:如果分配的存儲量不大,那麼使用shm;如果存儲量大,那麼使用shm。
參看網路:http://ke..com/view/1499209.htm
mmap就是一個文件操作
看這些網路的描述:
mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以向訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。 成功執行時,mmap()返回被映射區的指針,munmap()返回0。失敗時,mmap()返回MAP_FAILED[其值為(void *)-1],munmap返回-1。errno被設為以下的某個值 EACCES:訪問出錯EAGAIN:文件已被鎖定,或者太多的內存已被鎖定EBADF:fd不是有效的文件描述詞EINVAL:一個或者多個參數無效 ENFILE:已達到系統對打開文件的限制ENODEV:指定文件所在的文件系統不支持內存映射ENOMEM:內存不足,或者進程已超出最大內存映射數量 EPERM:權能不足,操作不允許ETXTBSY:已寫的方式打開文件,同時指定MAP_DENYWRITE標志SIGSEGV:試著向只讀區寫入 SIGBUS:試著訪問不屬於進程的內存區參數fd為即將映射到進程空間的文件描述字,
一般由open()返回,同時,fd可以指定為-1,此時須指定 flags參數中的MAP_ANON,表明進行的是匿名映射(不涉及具體的文件名,避免了文件的創建及打開,很顯然只能用於具有親緣關系的進程間通信)
相關文章參考:
mmap函數是unix/linux下的系統調用,來看《Unix Netword programming》卷二12.2節有詳細介紹。
mmap系統調用並不是完全為了用於共享內存而設計的。它本身提供了不同於一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。而Posix或系統V的共享內存IPC則純粹用於共享目的,當然mmap()實現共享內存也是其主要應用之一。
mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以像訪問普通內存一樣對文件進行訪問,不必再 調用read(),write()等操作。mmap並不分配空間, 只是將文件映射到調用進程的地址空間里, 然後你就可以用memcpy等操作寫文件, 而不用write()了.寫完後用msync()同步一下, 你所寫的內容就保存到文件里了. 不過這種方式沒辦法增加文件的長度, 因為要映射的長度在調用mmap()的時候就決定了.
簡單說就是把一個文件的內容在內存裡面做一個映像,內存比磁碟快些。
基本上它是把一個檔案對應到你的virtual memory 中的一段,並傳回一個指針。
重寫總結:
1、mmap實際就是操作「文件」。
2、映射文件,除了主存的考慮外。shm的內存共享,效率應該比mmap效率要高(mmap通過io和文件操作,或「需要寫完後用msync()同步一下」);當然mmap映射操作文件,比直接操作文件要快些;由於多了一步msync應該可以說比shm要慢了吧???
3、另一方面,mmap的優點是,操作比shm簡單(沒有調用比shm函數復雜),我想這也是許多人喜歡用的原因,包括nginx。
缺點,還得通過實際程序測試,確定!!!
修正理解(這也真是的,這個網站沒辦法附加;只能重寫了):
今天又細心研究了一下,發現網路這么一段說明:
2、系統調用mmap()用於共享內存的兩種方式:
(1)使用普通文件提供的內存映射:適用於任何進程之間;此時,需要打開或創建一個文件,然後再調用mmap();典型調用代碼如下:
fd=open(name, flag, mode);
if(fd<0)
...
ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0); 通過mmap()實現共享內存的通信方式有許多特點和要注意的地方,我們將在範例中進行具體說明。
(2)使用特殊文件提供匿名內存映射:適用於具有親緣關系的進程之間;由於父子進程特殊的親緣關系,在父進程中先調用mmap(),然後調用fork()。那麼在調用fork()之後,子進程繼承父進程匿名映射後的地址空間,同樣也繼承mmap()返回的地址,這樣,父子進程就可以通過映射區域進行通信了。注意,這里不是一般的繼承關系。一般來說,子進程單獨維護從父進程繼承下來的一些變數。而mmap()返回的地址,卻由父子進程共同維護。
看了一下windows「內存映射文件」:http://ke..com/view/394293.htm
內存映射文件與虛擬內存有些類似,通過內存映射文件可以保留一個地址空間的區域,同時將物理存儲器提交給此區域,只是內存文件映射的物理存儲器來自一個已經存在於磁碟上的文件,而非系統的頁文件,而且在對該文件進行操作之前必須首先對文件進行映射,就如同將整個文件從磁碟載入到內存。由此可以看出,使用內存映射文件處理存儲於磁碟上的文件時,將不必再對文件執行I/O操作,這意味著在對文件進行處理時將不必再為文件申請並分配緩存,所有的文件緩存操作均由系統直接管理,由於取消了將文件數據載入到內存、數據從內存到文件的回寫以及釋放內存塊等步驟,使得內存映射文件在處理大數據量的文件時能起到相當重要的作用。另外,實際工程中的系統往往需要在多個進程之間共享數據,如果數據量小,處理方法是靈活多變的,如果共享數據容量巨大,那麼就需要藉助於內存映射文件來進行。實際上,內存映射文件正是解決本地多個進程間數據共享的最有效方法。
這里再總結一次:
1、mmap有兩種方式,一種是映射內存,它把普通文件映射為實際物理內存頁,訪問它就和訪問物理內存一樣(這也就和shm的功能一樣了)(同時不用刷新到文件)
2、mmap可以映射文件,不確定會不會像windows「內存映射文件」一樣的功能,如果是,那麼他就能映射好幾G甚至好幾百G的內存數據,對大數據處理將提供強大功能了???
3、shm只做內存映射,和mmap第一個功能一樣!只不過不是普通文件而已,但都是物理內存。
❺ linux共享內存存在於進程空間的什麼位置
共享內存方式:從物理內存裡面拿出來一部分作為多個進程共享。 共享內存是進程間共享數據的一種最快的方法,一個進程向共享內存區域寫入數據,共享這個內存的所有進程都可以立即看到其中內容。 共享內存實現步驟: 一、創建共享內存,使用shmget函數。 二、映射共享內存,將這段創建的共享內存映射到具體的進程空間去,使用shmat函數。 創建共享內存shmget: intshmget(key_t key, size_t size, int shmflg) 功能:得到一個共享內存標識符或創建一個共享內存對象並返回共享內存標識符。 key: 0(IPC_PRIVATE)會建立共享內存對象 size:大於0的整數,新建共享內存的大小,以位元組為單位。只獲取共享內存時,指定為0. shmflg: 0表示取共享內存標識符,如不存在則函數會報錯; IPC_CREAT,如果內核中不存在鍵值與key相等的共享內存時,則創建一個共享內存;如果存在這樣的共享內存則返回共享內存的標識符; IPC_CREATIPC_EXCL: 如果內核中不存在鍵值與key相等的共享內存,則新建一個消息隊列;如果存在這樣的共享內存則報錯; 函數返回值:成功則返回內存的標識符;出錯則返回-1,錯誤原因存在於error中 映射共享內存到調用進程的地址空間shmat: void*shmat(int shmid, const void *shmaddr, int shmflg) msqid:共享內存標識符 shmaddr:指定共享內存出現在進程內存地址的什麼位置,直接指定為NULL讓內核自己決定一個合適的地址位置。 shmflg: SHM_RDONLY 只讀模式,其他為讀寫模式 函數返回值:成功則返回附加好的共享內存地址;出錯返回-1,錯誤原因存在於error中 斷開共享內存連接shmdt: intshmdt(const void *shmaddr) 功能:傳入shmaddr,連接共享的內存起始地址;斷開成功則返回0,出錯則返回-1,錯誤原因存在於error中。 父子進程間通訊實例: #include #include #include #include #include #include int main(int argc, char **argv){ if(argc< 2){ //需要輸入共享的數據 printf("pleaseinput the shared data.n"); exit(-1); } intshmid; shmid= shmget(0,1024,IPC_CREAT); if(shmid== -1){ // 申請共享內存失敗 printf("createshare memory failed.n"); exit(-1); } if(fork()){ // 父進程之中 char*p_shmaddr; p_shmaddr= shmat(shmid, NULL, 0); // 映射到父進程之中的一個地址 memset(p_shmaddr,0, 1024); // 初始化共享內存 strcpy(p_shmaddr,argv[1]); // 拷貝共享數據到共享內存 wait(NULL); //等待子進程結束 exit(0); } else{ sleep(2); //等待父進程寫入數據 char*c_shmaddr; c_shmaddr= shmat(shmid,NULL,0); // 映射到子進程之中一個地址,具體由kernel 指配 printf("theshare data is: %sn", c_shmaddr); //子進程輸出共享的數據 exit(0); } }
❻ Linux進程間通信
linux下進程間通信的幾種主要手段簡介:
一般文件的I/O函數都可以用於管道,如close、read、write等等。
實例1:用於shell
管道可用於輸入輸出重定向,它將一個命令的輸出直接定向到另一個命令的輸入。比如,當在某個shell程序(Bourne shell或C shell等)鍵入who│wc -l後,相應shell程序將創建who以及wc兩個進程和這兩個進程間的管道。
實例二:用於具有親緣關系的進程間通信
管道的主要局限性正體現在它的特點上:
有名管道的創建
小結:
管道常用於兩個方面:(1)在shell中時常會用到管道(作為輸入輸入的重定向),在這種應用方式下,管道的創建對於用戶來說是透明的;(2)用於具有親緣關系的進程間通信,用戶自己創建管道,並完成讀寫操作。
FIFO可以說是管道的推廣,克服了管道無名字的限制,使得無親緣關系的進程同樣可以採用先進先出的通信機制進行通信。
管道和FIFO的數據是位元組流,應用程序之間必須事先確定特定的傳輸"協議",採用傳播具有特定意義的消息。
要靈活應用管道及FIFO,理解它們的讀寫規則是關鍵。
信號生命周期
信號是進程間通信機制中唯一的非同步通信機制,可以看作是非同步通知,通知接收信號的進程有哪些事情發生了。信號機制經過POSIX實時擴展後,功能更加強大,除了基本通知功能外,還可以傳遞附加信息。
可以從兩個不同的分類角度對信號進行分類:(1)可靠性方面:可靠信號與不可靠信號;(2)與時間的關繫上:實時信號與非實時信號。
(1) 可靠信號與不可靠信號
不可靠信號 :Linux下的不可靠信號問題主要指的是信號可能丟失。
可靠信號 :信號值位於SIGRTMIN和SIGRTMAX之間的信號都是可靠信號,可靠信號克服了信號可能丟失的問題。Linux在支持新版本的信號安裝函數sigation()以及信號發送函數sigqueue()的同時,仍然支持早期的signal()信號安裝函數,支持信號發送函數kill()。
對於目前linux的兩個信號安裝函數:signal()及sigaction()來說,它們都不能把SIGRTMIN以前的信號變成可靠信號(都不支持排隊,仍有可能丟失,仍然是不可靠信號),而且對SIGRTMIN以後的信號都支持排隊。這兩個函數的最大區別在於,經過sigaction安裝的信號都能傳遞信息給信號處理函數(對所有信號這一點都成立),而經過signal安裝的信號卻不能向信號處理函數傳遞信息。對於信號發送函數來說也是一樣的。
(2) 實時信號與非實時信號
前32種信號已經有了預定義值,每個信號有了確定的用途及含義,並且每種信號都有各自的預設動作。如按鍵盤的CTRL ^C時,會產生SIGINT信號,對該信號的默認反應就是進程終止。後32個信號表示實時信號,等同於前面闡述的可靠信號。這保證了發送的多個實時信號都被接收。實時信號是POSIX標準的一部分,可用於應用進程。非實時信號都不支持排隊,都是不可靠信號;實時信號都支持排隊,都是可靠信號。
發送信號的主要函數有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。
調用成功返回 0;否則,返回 -1。
sigqueue()是比較新的發送信號系統調用,主要是針對實時信號提出的(當然也支持前32種),支持信號帶有參數,與函數sigaction()配合使用。
sigqueue的第一個參數是指定接收信號的進程ID,第二個參數確定即將發送的信號,第三個參數是一個聯合數據結構union sigval,指定了信號傳遞的參數,即通常所說的4位元組值。
sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號。sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號。
inux主要有兩個函數實現信號的安裝: signal() 、 sigaction() 。其中signal()在可靠信號系統調用的基礎上實現, 是庫函數。它只有兩個參數,不支持信號傳遞信息,主要是用於前32種非實時信號的安裝;而sigaction()是較新的函數(由兩個系統調用實現:sys_signal以及sys_rt_sigaction),有三個參數,支持信號傳遞信息,主要用來與 sigqueue() 系統調用配合使用,當然,sigaction()同樣支持非實時信號的安裝。sigaction()優於signal()主要體現在支持信號帶有參數。
消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優先順序。對消息隊列有寫許可權的進程可以向中按照一定的規則添加新消息;對消息隊列有讀許可權的進程則可以從消息隊列中讀走消息。消息隊列是隨內核持續的
消息隊列的內核持續性要求每個消息隊列都在系統范圍內對應唯一的鍵值,所以,要獲得一個消息隊列的描述字,只需提供該消息隊列的鍵值即可;
消息隊列與管道以及有名管道相比,具有更大的靈活性,首先,它提供有格式位元組流,有利於減少開發人員的工作量;其次,消息具有類型,在實際應用中,可作為優先順序使用。這兩點是管道以及有名管道所不能比的。同樣,消息隊列可以在幾個進程間復用,而不管這幾個進程是否具有親緣關系,這一點與有名管道很相似;但消息隊列是隨內核持續的,與有名管道(隨進程持續)相比,生命力更強,應用空間更大。
信號燈與其他進程間通信方式不大相同,它主要提供對進程間共享資源訪問控制機制。相當於內存中的標志,進程可以根據它判定是否能夠訪問某些共享資源,同時,進程也可以修改該標志。除了用於訪問控制外,還可用於進程同步。信號燈有以下兩種類型:
int semop(int semid, struct sembuf *sops, unsigned nsops); semid是信號燈集ID,sops指向數組的每一個sembuf結構都刻畫一個在特定信號燈上的操作。
int semctl(int semid,int semnum,int cmd,union semun arg)
該系統調用實現對信號燈的各種控制操作,參數semid指定信號燈集,參數cmd指定具體的操作類型;參數semnum指定對哪個信號燈操作,只對幾個特殊的cmd操作有意義;arg用於設置或返回信號燈信息。
進程間需要共享的數據被放在一個叫做IPC共享內存區域的地方,所有需要訪問該共享區域的進程都要把該共享區域映射到本進程的地址空間中去。系統V共享內存通過shmget獲得或創建一個IPC共享內存區域,並返回相應的標識符。內核在保證shmget獲得或創建一個共享內存區,初始化該共享內存區相應的shmid_kernel結構注同時,還將在特殊文件系統shm中,創建並打開一個同名文件,並在內存中建立起該文件的相應dentry及inode結構,新打開的文件不屬於任何一個進程(任何進程都可以訪問該共享內存區)。所有這一切都是系統調用shmget完成的。
shmget()用來獲得共享內存區域的ID,如果不存在指定的共享區域就創建相應的區域。shmat()把共享內存區域映射到調用進程的地址空間中去,這樣,進程就可以方便地對共享區域進行訪問操作。shmdt()調用用來解除進程對共享內存區域的映射。shmctl實現對共享內存區域的控制操作。這里我們不對這些系統調用作具體的介紹,讀者可參考相應的手冊頁面,後面的範例中將給出它們的調用方法。
註:shmget的內部實現包含了許多重要的系統V共享內存機制;shmat在把共享內存區域映射到進程空間時,並不真正改變進程的頁表。當進程第一次訪問內存映射區域訪問時,會因為沒有物理頁表的分配而導致一個缺頁異常,然後內核再根據相應的存儲管理機制為共享內存映射區域分配相應的頁表。
❼ 共享內存原理
Linux的2.2.x內核支持多種共享內存方式,如mmap()系統調用,Posix共享內存,以及系統V共享內存。
共享內存可以說是最有用的進程間通信方式,也是最快的IPC形式。兩個不同進程A、B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。進程A可以即時看到進程B對共享內存中數據的更新,反之亦然。由於多個進程共享同一塊內存區域,必然需要某種同步機制,互斥鎖和信號量都可以。
系統V共享內存原理
進程間需要共享的數據被放在一個叫做IPC共享內存區域的地方,所有需要訪問該共享區域的進程都要把該共享區域映射到本進程的地址空間中去。系統V共享內存通過shmget獲得或創建一個IPC共享內存區域,並返回相應的標識符。內核在保證shmget獲得或創建一個共享內存區,初始化該共享內存區相應的shmid_kernel結構注同時,還將在特殊文件系統shm中,創建並打開一個同名文件,並在內存中建立起該文件的相應dentry及inode結構,新打開的文件不屬於任何一個進程(任何進程都可以訪問該共享內存區)。所有這一切都是系統調用shmget完成的。
Linux 有一個系統調用叫 mmap(),這個 mmap() 可以把一個文件映射到進程的地址空間(進程使用的虛擬內存),這樣進程就可以通過讀寫這個進程地址空間來讀寫這個文件。
你可能會覺得奇怪,我明明寫的是內存啊,怎麼會變成寫文件了呢?他們之間是怎麼轉化的呢?
沒錯,你寫的確實是內存,但是你寫的這個內存不是普通的內存,你寫在這個內存上的內容,過段時間後會被內核寫到這個文件上面。而寫文件,其實最後都會變成寫數據到設備里(硬碟、Nand Flash 等)。
mmap的優點主要在為用戶程序隨機的訪問,操作,文件提供了一個方便的操作方法;其次就是為不同進程共享大批量數據提供高效的手段;另外就是對特大文件(無法一次性讀入內存)的處理提供了一種有效的方法。
內核里存在著一個特殊的文件系統,這個文件系統的存儲介質不是別的,正是 RAM。
在 shmget() 調用之後,系統會為你在這個文件系統上創建一個文件,但是這個時候僅僅是創建了這個文件。
然後你就應該調用 shmat() 了,調用 shmat() 之後,內核會使用 mmap 把這個文件映射到你的進程地址空間,這個時候你就能直接讀寫映射後的地址了。
過段時間,內核把你寫的 內容寫到了文件裡面,但是,這個文件的存儲介質是內存,所以他會怎麼做?看明白了吧?
答案:他會寫入內存呀
我們先來看看如果不使用內存映射文件的處理流程是怎樣的,首先我們得先讀出磁碟文件的內容到內存中,然後修改,最後回寫到磁碟上。第一步讀磁碟文件是要經過一次系統調用的,它首先將文件內容從磁碟拷貝到內核空間的一個緩沖區,然後再將這些數據拷貝到用戶空間,實際上是兩次數據拷貝。第三步回寫也一樣也要經過兩次數據拷貝。
所以我們基本上會有四次數據的拷貝了,因為大文件數據量很大,幾十GB甚至更大,所以拷貝的開銷是非常大的。
而內存映射文件是操作系統的提供的一種機制,可以減少這種不必要的數據拷貝,從而提高效率。它由mmap()將文件直接映射到用戶空間,mmap()並沒有進行數據拷貝,真正的數據拷貝是在缺頁中斷處理時進行的,由於mmap()將文件直接映射到用戶空間,所以中斷處理函數根據這個映射關系,直接將文件從硬碟拷貝到用戶空間,所以只進行了一次數據拷貝 ,比read進行兩次數據拷貝要好上一倍,因此,內存映射的效率要比read/write效率高。
一般來說,read write操作可以滿足大多數文件操作的要求,但是對於某些特殊應用領域所需要的幾十GB甚至更大的存儲,這種通常的文件處理方法進行處理顯然是行不通的。
mmap將一個文件或者其它對象映射進內存。文件被映射到多個頁上,如果文件的大小不是所有頁的大小之和,最後一個頁不被使用的空間將會清零。munmap執行相反的操作,刪除特定地址區域的對象映射。
當使用mmap映射文件到進程後,就可以直接操作這段虛擬地址進行文件的讀寫等操作,不必再調用read,write等系統調用.但需注意,直接對該段內存寫時不會寫入超過當前文件大小的內容.
參考地址:
❽ linux進程間通信 socket 共享內存 哪個快
進程間通訊進程間通信就是不同進程之間傳播或交換信息,進程的用戶空間是互相獨立的,進程之間可以利用系統空間交換信息。 管道(pipe)管道是一種半雙工的通信方式,數據只能單向流動。如果要進行雙工通信,需要建立兩個管道。 管道只能在具有親緣關系的進程間使用,例如父子進程或兄弟進程。 有名管道(named pipe) 有名管道也是雙半工的通信方式,但它允許無親緣關系的進程間使用。 信號量(semophore) 信號量常用來作為一種鎖機制來使用,它是一個記數器,用來控制多進程對共享資源的訪問,防止多個進程同時訪問一個共享資源。信號量主要用作為進程間或同一進程間不同線程之間的同步手段。 信號(sinal) 信號是一種比較復雜的通信方式,用於通知接收進程某些事件已經發生,要注意信號處理中調用的函數是否為信號安全。 消息隊列(message queue) 消息隊列是由消息的鏈表組成,存放在內核中並由消息隊列標識符標識。 共享內存(shared memory) 共享內存就是映射一段被其他進程所訪問的內存,這段共享內存由一個進程創建,可由多個進程訪問。共享內存是最快的IPC方式,它是針對其他進程間通信方式的低運行效率而專門設計的。它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步和通信。 套接字(socket) 套接字也是進程間通信的一種方式,與其他方式不同的是,它可以用在不同主機間的進程通信(也是它的主要用途)。 幾種方式的缺點 管道: 速度慢,容量有限,只能用於親緣關系進程間通信。 有名管道: 同管道,不過允許無親緣關系進程間通信。 消息隊列: 容量受系統限制,隊列中會遺留數據,讀時要考慮到這些未讀完的數據。 信號量: 主要用於同步,無法傳遞復雜的數據信息。
❾ linux下通過shmget創建的共享內存,是屬於用戶空間還是內核空間
屬於用戶空間. shmat後返回的地址空間屬於用戶空間, 不同進程可以將同一物理內存區域映射到各自的用戶空間中。該空間可以隨意讀寫。note: 一個小屁進程,在用戶態時,是沒有許可權操作內核空間的。
虛擬地址空間=用戶空間+內核空間。
❿ linux系統的進程間通信有哪幾種方式
一、方式
1、管道(Pipe)及有名管道( mkpipe):
管道可用於具有親緣關系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關系進程間的通信;
2、信號(Signal):
信號是比較復雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還可以發送信號給進程本身。
linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction。
實際上,該函數是基於BSD的,BSD為了實現可靠信號機制,又能夠統一對外介面,用sigaction函數重新實現了signal函數。
3、消息隊列(Message):
消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠許可權的進程可以向隊列中添加消息,被賦予讀許可權的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式位元組流以及緩沖區大小受限等缺點。
4、共享內存:
使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
5、信號量(semaphore):
主要作為進程間以及同一進程不同線程之間的同步手段。
6、套介面(Socket):
更為一般的進程間通信機制,可用於不同機器之間的進程間通信。起初是由Unix系統的BSD分支開發出來的,但現在一般可以移植到其它類Unix系統上:Linux和System V的變種都支持套接字。
二、概念
進程間通信概念:
IPC—-InterProcess Communication
每個進程各自有不同的用戶地址空間,任何一個進程的全局變數在另一個進程中都看不到所以進程之間要交換數據必須通過內核。
在內核中開辟一塊緩沖區,進程1把數據從用戶空間拷到內核緩沖區,進程2再從內核緩沖區把數據讀走,內核提供的這種機制稱為進程間通信。
(10)linux進程間共享內存擴展閱讀
1)無名管道:
管道是半雙工的,數據只能向一個方向流動;需要雙方通信時,需要建立起兩個管道;只能用於父子進程或者兄弟進程之間(具有親緣關系的進程)。
管道對於管道兩端的進程而言,就是一個文件,但它不是普通的文件,它不屬於某種文件系統,構成兩進程間通信的一個媒介。
數據的讀出和寫入:一個進程向管道中寫的內容被管道另一端的進程讀出。寫入的內容每次都添加在管道緩沖區的末尾,並且每次都是從緩沖區的頭部讀出數據。
2)有名管道:
不同於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即使與FIFO的創建進程不存在親緣關系的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程以及FIFO的創建進程之間)。
因此,通過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數據,對它們的寫則把數據添加到末尾。它們不支持諸如lseek()等文件定位操作。