資源描述:
《技術(shù)積累--共享內(nèi)存使用常見陷阱與分析》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、LINUX共享內(nèi)存使用常見陷阱與分析所謂共享內(nèi)存就是使得多個(gè)進(jìn)程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。是針對(duì)其他通信機(jī)制運(yùn)行效率較低而設(shè)計(jì)的。往往與其它通信機(jī)制,如信號(hào)量結(jié)合使用,來達(dá)到進(jìn)程間的同步及互斥。其他進(jìn)程能把同一段共享內(nèi)存段“連接到”他們自己的地址空間里去。所有進(jìn)程都能訪問共享內(nèi)存中的地址。如果一個(gè)進(jìn)程向這段共享內(nèi)存寫了數(shù)據(jù),所做的改動(dòng)會(huì)即時(shí)被有訪問同一段共享內(nèi)存的其他進(jìn)程看到。共享內(nèi)存的使用大大降低了在大規(guī)模數(shù)據(jù)處理過程中內(nèi)存的消耗,但是共享內(nèi)存的使用中有很多的陷阱,一不注意就很容易
2、導(dǎo)致程序崩潰。l超過共享內(nèi)存的大小限制?在一個(gè)linux服務(wù)器上,共享內(nèi)存的總體大小是有限制的,這個(gè)大小通過SHMMAX參數(shù)來定義(以字節(jié)為單位),您可以通過執(zhí)行以下命令來確定SHMMAX的值:#cat/proc/sys/kernel/shmmax如果機(jī)器上創(chuàng)建的共享內(nèi)存的總共大小超出了這個(gè)限制,在程序中使用標(biāo)準(zhǔn)錯(cuò)誤perror可能會(huì)出現(xiàn)以下的信息:unabletoattachtosharedmemory解決方法:1、設(shè)置SHMMAXSHMMAX的默認(rèn)值是32MB。一般使用下列方法之一種將SHMMAX參數(shù)
3、設(shè)為2GB:通過直接更改/proc文件系統(tǒng),你不需重新啟動(dòng)機(jī)器就可以改變SHMMAX的默認(rèn)設(shè)置。我使用的方法是將以下命令放入/etc/rc.local啟動(dòng)文件中:#>echo"2147483648">/proc/sys/kernel/shmmax您還可以使用sysctl命令來更改SHMMAX的值:#sysctl-wkernel.shmmax=2147483648最后,通過將該內(nèi)核參數(shù)插入到/etc/sysctl.conf啟動(dòng)文件中,您可以使這種更改永久有效:#echo"kernel.shmmax=2147
4、483648">>/etc/sysctl.conf2、設(shè)置SHMMNI我們現(xiàn)在來看SHMMNI參數(shù)。這個(gè)內(nèi)核參數(shù)用于設(shè)置系統(tǒng)范圍內(nèi)共享內(nèi)存段的最大數(shù)量。該參數(shù)的默認(rèn)值是4096。這一數(shù)值已經(jīng)足夠,通常不需要更改。您可以通過執(zhí)行以下命令來確定SHMMNI的值:#cat/proc/sys/kernel/shmmni40963、設(shè)置SHMALL最后,我們來看SHMALL共享內(nèi)存內(nèi)核參數(shù)。該參數(shù)控制著系統(tǒng)一次可以使用的共享內(nèi)存總量(以頁為單位)。簡(jiǎn)言之,該參數(shù)的值始終應(yīng)該至少為:ceil(SHMMAX/PAGE_
5、SIZE)SHMALL的默認(rèn)大小為2097152,可以使用以下命令進(jìn)行查詢:#cat/proc/sys/kernel/shmall2097152SHMALL的默認(rèn)設(shè)置對(duì)于我們來說應(yīng)該足夠使用。注意:在i386平臺(tái)上RedHatLinux的頁面大小為4096字節(jié)。但是,您可以使用bigpages,它支持配置更大的內(nèi)存頁面尺寸。l多次進(jìn)行shmat會(huì)出現(xiàn)什么問題?當(dāng)首次創(chuàng)建共享內(nèi)存段時(shí),它并不能被任何進(jìn)程所訪問。為了使共享內(nèi)存區(qū)可以被訪問,則必須通過shmat函數(shù)將其附加(attach)到自己的進(jìn)程空間中,這
6、樣進(jìn)程就與共享內(nèi)存建立了連接。該函數(shù)聲明在linux/shm.h中:#include#includevoid*shmat(intshmid,constvoid*shmaddr,intshmflg);參數(shù)shmid是shmget()的返回值,是個(gè)標(biāo)識(shí)符;參數(shù)shmflg是存取權(quán)限標(biāo)志;如果為0,則不設(shè)置任何限制權(quán)限。在中定義了幾個(gè)權(quán)限:#defineSHM_RDONLY010000/*attachread-onlyelseread-wr
7、ite*/#defineSHM_RND020000/*roundattachaddresstoSHMLBA*/#defineSHM_REMAP040000/*take-overregiononattach*/如果指定SHM_RDONLY,那么共享內(nèi)存區(qū)只有讀取權(quán)限。參數(shù)shmaddr是共享內(nèi)存的附加點(diǎn),不同的取值有不同的含義:?如果為空,則由內(nèi)核選擇一個(gè)空閑的內(nèi)存區(qū);如果非空,返回地址取決于調(diào)用者是否給shmflg參數(shù)指定SHM_RND值,如果沒有指定,則共享內(nèi)存區(qū)附加到由shmaddr指定的地址;否則附
8、加地址為shmaddr向下舍入一個(gè)共享內(nèi)存低端邊界地址后的地址(SHMLBA,一個(gè)常址)。?通常將參數(shù)shmaddr設(shè)置為NULL。shmat()調(diào)用成功后返回一個(gè)指向共享內(nèi)存區(qū)的指針,使用該指針就可以訪問共享內(nèi)存區(qū)了,如果失敗則返回-1。其映射關(guān)系如下圖所示:圖1.1共享內(nèi)存映射圖其中,shmaddr表示的是物理內(nèi)存空間映射到進(jìn)程的虛擬內(nèi)存空間時(shí)候,虛擬內(nèi)存空間中該塊內(nèi)存的起始地址,在使用中,因?yàn)槲覀円话悴磺宄M(jìn)程中哪些地址