思考共享內存的整個概念後,出現了一個問題:進程VS線程:兩個進程可以共享相同的共享內存嗎?可以兩個線程?
可以兩個進程共享相同的共享內存段嗎?兩個線程可以共享相同的共享內存嗎?
經過仔細考慮之後,我幾乎肯定地看到兩個進程可以共享相同的共享內存段,其中第一個是父親,第二個是兒子,使用fork()
創建,但兩個線程呢?
由於
思考共享內存的整個概念後,出現了一個問題:進程VS線程:兩個進程可以共享相同的共享內存嗎?可以兩個線程?
可以兩個進程共享相同的共享內存段嗎?兩個線程可以共享相同的共享內存嗎?
經過仔細考慮之後,我幾乎肯定地看到兩個進程可以共享相同的共享內存段,其中第一個是父親,第二個是兒子,使用fork()
創建,但兩個線程呢?
由於
可以在兩個進程共享相同的共享存儲器段?
是和否。通常對於現代操作系統,當第一個進程是forked時,它們共享相同的內存空間,並在所有頁面上設置"copy-on-write"。對任何讀寫內存頁面所做的任何更新都會導致爲頁面創建副本,因此將會有兩個副本,並且內存頁面將不再在父進程和子進程之間共享。這意味着只有只讀頁面或尚未寫入的頁面纔會被共享。
如果一個進程有而不是從另一個分叉,那麼他們不共享任何內存。一個例外是,如果您運行同一程序的兩個實例,那麼它們可能會共享code and maybe even static data segments,但不會共享其他頁面。
還有specific memory-map calls共享相同的內存段。該調用指定映射是隻讀還是讀寫。如何做到這一點非常依賴操作系統。
可以兩個線程共享相同的共享內存嗎?
當然可以。通常,多線程進程中的所有內存都由所有線程「共享」。這通常是線程的定義,它們都在相同的內存空間中運行。
線程還會增加與處理器/內核綁定的高速內存中的cached memory segments的複雜性。這個緩存的內存是而不是共享,並且根據同步操作將內存頁面的更新刷新到中央存儲中。
是的,兩個進程都可以連接到共享內存段。如果共享內存段不是真的,那麼共享內存段的用處不大,因爲這是共享內存段背後的基本思想 - 這就是爲什麼它是多種形式的IPC(進程間通信)之一。
在同一個進程中的兩個線程也可以附加到共享內存段,但考慮到他們已經共享他們所屬的進程的整個地址空間,可能沒有多少意義(儘管有人可能會將這看作是一個挑戰,以提出一個或多或少有效的用例)。
我認爲更接近'不太有效'比:)更多請不要向開發者建議他們使用線程做更奇怪的事情,這已經夠糟糕了,因爲它是
一般來說,過程的一個重點是防止共享內存!通過共享內存段進行的進程間通信當然可以用在最常見的操作系統上,但這種機制在默認情況下並不存在。無法正確設置和管理共享區域可能會導致segFault/AV(如果幸運的話)和UB(如果不幸的話)。
線程屬於同一個過程,但是,沒有這樣的硬件內存管理保護幾乎可以共享他們喜歡,很明顯的缺點是,它們會破壞幾乎任何他們喜歡的。我從來沒有發現這是一個巨大的問題,尤其是。與現代OO語言傾向於將指針結構化爲對象實例(Java,C#,Delphi)。
一般地說,每個過程中,爲了避免不必要的相互作用(包括那些將代表安全問題)佔據從所有其他分離的存儲器空間。但是,通常有一個過程共享部分內存的方法。有時候這樣做是爲了減少RAM佔用空間(VAX/VMS中的「已安裝文件」就是這樣一個例子)。它也可以成爲協作過程溝通的非常有效的方式。如何實現/結構化/管理共享(例如,父/子)取決於特定操作系統提供的功能和應用程序代碼中實現的設計選擇。
在一個過程中,每個線程都可以訪問完全相同的內存空間,同一進程的所有其他線程。一個線程具有獨特的自身的唯一事情是「執行上下文」,其中一部分是它的棧(雖然沒有什麼可以阻止一個線程訪問或操縱「屬於」同一處理的另一個線程的堆棧)。
回覆「這緩存內存不是共享的和更新的內存頁取決於同步操作被刷新到中央存儲」:好事還是壞事? – Pacerier 2017-10-19 21:23:05
回覆「主題也已經緩存綁在處理器/核高速內存內存段增加了複雜性」:這是甚至OS內核的事情?或者只是一個軟件語言庫功能? – Pacerier 2017-10-20 02:35:32
@Pacerier是一件非常好的事情。本地CPU內存緩存是多線程程序所帶來的許多性能提升。 _hardware_不支持操作系統和軟件。該軟件需要考慮內存緩衝區來控制刷新和更新,但是由於CPU設計,它們會自動發生。 – Gray 2017-10-20 15:07:15