COW奶牛!Copy On Write機制了解一下

前言

只有光頭才能變強

在讀《Redis設計與實現》關于哈希表擴容的時候,發現這么一段話:

執行BGSAVE命令或者BGREWRITEAOF命令的過程中,Redis需要創建當前服務器進程的子進程,而大多數操作系統都采用寫時復制(copy-on-write)來優化子進程的使用效率,所以在子進程存在期間,服務器會提高負載因子的閾值,從而避免在子進程存在期間進行哈希表擴展操作,避免不必要的內存寫入操作,最大限度地節約內存。

觸及到知識的盲區了,于是就去搜了一下copy-on-write寫時復制這個技術究竟是怎么樣的。發現涉及的東西蠻多的,也挺難讀懂的。于是就寫下這篇筆記來記錄一下我學習copy-on-write的過程。

本文力求簡單講清copy-on-write這個知識點,希望大家看完能有所收獲。

一、Linux下的copy-on-write

在說明Linux下的copy-on-write機制前,我們首先要知道兩個函數:fork()exec()。需要注意的是exec()并不是一個特定的函數, 它是一組函數的統稱, 它包括了execl()execlp()execv()execle()execve()execvp()

1.1簡單來用用fork

首先我們來看一下fork()函數是什么鬼:

fork is an operation whereby a process creates a copy of itself.

fork是類Unix操作系統上創建進程的主要方法。fork用于創建子進程(等同于當前進程的副本)。

  • 新的進程要通過老的進程復制自身得到,這就是fork!

如果接觸過Linux,我們會知道Linux下init進程是所有進程的爹(相當于Java中的Object對象)

  • Linux的進程都通過init進程或init的子進程fork(vfork)出來的。

下面以例子說明一下fork吧:


#include?<unistd.h>??
#include?<stdio.h>??int?main?()???
{???pid_t?fpid;?//fpid表示fork函數返回的值??int?count=0;// 調用fork,創建出子進程??fpid=fork();// 所以下面的代碼有兩個進程執行!if?(fpid?<?0)???printf("創建進程失敗!/n");???else?if?(fpid?==?0)?{??printf("我是子進程,由父進程fork出來/n");???count++;??}??else?{??printf("我是父進程/n");???count++;??}??printf("統計結果是:?%d/n",count);??return?0;??
}??

得到的結果輸出為:


我是子進程,由父進程fork出來統計結果是: 1我是父進程統計結果是: 1

解釋一下:

  • fork作為一個函數被調用。這個函數會有兩次返回,將子進程的PID返回給父進程,0返回給子進程。(如果小于0,則說明創建子進程失敗)。
  • 再次說明:當前進程調用fork(),會創建一個跟當前進程完全相同的子進程(除了pid),所以子進程同樣是會執行fork()之后的代碼。

所以說:

  • 父進程在執行if代碼塊的時候,fpid變量的值是子進程的pid
  • 子進程在執行if代碼塊的時候,fpid變量的值是0

1.2再來看看exec()函數

從上面我們已經知道了fork會創建一個子進程。子進程的是父進程的副本

exec函數的作用就是:裝載一個新的程序(可執行映像)覆蓋當前進程內存空間中的映像,從而執行不同的任務

  • exec系列函數在執行時會直接替換掉當前進程的地址空間

我去畫張圖來理解一下:

exec函數的作用

參考資料:

  • 程序員必備知識——fork和exec函數詳解https://blog.csdn.net/bad_good_man/article/details/49364947
  • linux中fork()函數詳解(原創!!實例講解):https://blog.csdn.net/jason314/article/details/5640969
  • linux c語言 fork() 和 exec 函數的簡介和用法:https://blog.csdn.net/nvd11/article/details/8856278
  • Linux下Fork與Exec使用:https://www.cnblogs.com/hicjiajia/archive/2011/01/20/1940154.html
  • Linux 系統調用 —— fork()內核源碼剖析:https://blog.csdn.net/chen892704067/article/details/76596225

1.3回頭來看Linux下的COW是怎么一回事

fork()會產生一個和父進程完全相同的子進程(除了pid)

如果按傳統的做法,會直接將父進程的數據拷貝到子進程中,拷貝完之后,父進程和子進程之間的數據段和堆棧是相互獨立的

父進程的數據拷貝到子進程中

但是,以我們的使用經驗來說:往往子進程都會執行exec()來做自己想要實現的功能。

  • 所以,如果按照上面的做法的話,創建子進程時復制過去的數據是沒用的(因為子進程執行exec(),原有的數據會被清空)

既然很多時候復制給子進程的數據是無效的,于是就有了Copy On Write這項技術了,原理也很簡單:

  • fork創建出的子進程,與父進程共享內存空間。也就是說,如果子進程不對內存空間進行寫入操作的話,內存空間中的數據并不會復制給子進程,這樣創建子進程的速度就很快了!(不用復制,直接引用父進程的物理空間)。
  • 并且如果在fork函數返回之后,子進程第一時間exec一個新的可執行映像,那么也不會浪費時間和內存空間了。

另外的表達方式:

在fork之后exec之前兩個進程用的是相同的物理空間(內存區),子進程的代碼段、數據段、堆棧都是指向父進程的物理空間,也就是說,兩者的虛擬空間不同,但其對應的物理空間是同一個

當父子進程中有更改相應段的行為發生時,再為子進程相應的段分配物理空間

如果不是因為exec,內核會給子進程的數據段、堆棧段分配相應的物理空間(至此兩者有各自的進程空間,互不影響),而代碼段繼續共享父進程的物理空間(兩者的代碼完全相同)。

而如果是因為exec,由于兩者執行的代碼不同,子進程的代碼段也會分配單獨的物理空間。

Copy On Write技術實現原理:

fork()之后,kernel把父進程中所有的內存頁的權限都設為read-only,然后子進程的地址空間指向父進程。當父子進程都只讀內存時,相安無事。當其中某個進程寫內存時,CPU硬件檢測到內存頁是read-only的,于是觸發頁異常中斷(page-fault),陷入kernel的一個中斷例程。中斷例程中,kernel就會把觸發的異常的頁復制一份,于是父子進程各自持有獨立的一份。

Copy On Write技術好處是什么?

  • COW技術可減少分配和復制大量資源時帶來的瞬間延時
  • COW技術可減少不必要的資源分配。比如fork進程時,并不是所有的頁面都需要復制,父進程的代碼段和只讀數據段都不被允許修改,所以無需復制

Copy On Write技術缺點是什么?

  • 如果在fork()之后,父子進程都還需要繼續進行寫操作,那么會產生大量的分頁錯誤(頁異常中斷page-fault),這樣就得不償失。

幾句話總結Linux的Copy On Write技術:

  • fork出的子進程共享父進程的物理空間,當父子進程有內存寫入操作時,read-only內存頁發生中斷,將觸發的異常的內存頁復制一份(其余的頁還是共享父進程的)。
  • fork出的子進程功能實現和父進程是一樣的。如果有需要,我們會用exec()把當前進程映像替換成新的進程文件,完成自己想要實現的功能。

參考資料:

  • Linux進程基礎:http://www.cnblogs.com/vamei/archive/2012/09/20/2694466.html
  • Linux寫時拷貝技術(copy-on-write)http://www.cnblogs.com/biyeymyhjob/archive/2012/07/20/2601655.html
  • 當你在 Linux 上啟動一個進程時會發生什么?https://zhuanlan.zhihu.com/p/33159508
  • Linux fork()所謂的寫時復制(COW)到最后還是要先復制再寫嗎?https://www.zhihu.com/question/265400460
  • 寫時拷貝(copy-on-write) COW技術https://blog.csdn.net/u012333003/article/details/25117457
  • Copy-On-Write 寫時復制原理https://blog.csdn.net/ppppppppp2009/article/details/22750939

二、解釋一下Redis的COW

基于上面的基礎,我們應該已經了解COW這么一項技術了。

下面我來說一下我對《Redis設計與實現》那段話的理解:

  • Redis在持久化時,如果是采用BGSAVE命令或者BGREWRITEAOF的方式,那Redis會fork出一個子進程來讀取數據,從而寫到磁盤中
  • 總體來看,Redis還是讀操作比較多。如果子進程存在期間,發生了大量的寫操作,那可能就會出現很多的分頁錯誤(頁異常中斷page-fault),這樣就得耗費不少性能在復制上。
  • 而在rehash階段上,寫操作是無法避免的。所以Redis在fork出子進程之后,將負載因子閾值提高,盡量減少寫操作,避免不必要的內存寫入操作,最大限度地節約內存。

參考資料:

  • fork()后copy on write的一些特性:https://zhoujianshi.github.io/articles/2017/fork()%E5%90%8Ecopy%20on%20write%E7%9A%84%E4%B8%80%E4%BA%9B%E7%89%B9%E6%80%A7/index.html
  • 寫時復制:https://miao1007.github.io/gitbook/java/juc/cow/

三、文件系統的COW

下面來看看文件系統中的COW是啥意思:

Copy-on-write在對數據進行修改的時候,不會直接在原來的數據位置上進行操作,而是重新找個位置修改,這樣的好處是一旦系統突然斷電,重啟之后不需要做Fsck。好處就是能保證數據的完整性,掉電的話容易恢復

  • 比如說:要修改數據塊A的內容,先把A讀出來,寫到B塊里面去。如果這時候斷電了,原來A的內容還在!

參考資料:

  • 文件系統中的 copy-on-write 模式有什么具體的好處?https://www.zhihu.com/question/19782224/answers/created
  • 新一代 Linux 文件系統 btrfs 簡介:https://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/

最后

最后我們再來看一下寫時復制的思想(摘錄自維基百科):

寫入時復制(英語:Copy-on-write,簡稱COW)是一種計算機程序設計領域的優化策略。其核心思想是,如果有多個調用者(callers)同時請求相同資源(如內存或磁盤上的數據存儲),他們會共同獲取相同的指針指向相同的資源,直到某個調用者試圖修改資源的內容時,系統才會真正復制一份專用副本(private copy)給該調用者,而其他調用者所見到的最初的資源仍然保持不變。這過程對其他的調用者都是透明的(transparently)。此作法主要的優點是如果調用者沒有修改該資源,就不會有副本(private copy)被建立,因此多個調用者只是讀取操作時可以共享同一份資源。

至少從本文我們可以總結出:

  • Linux通過Copy On Write技術極大地減少了Fork的開銷
  • 文件系統通過Copy On Write技術一定程度上保證數據的完整性

其實在Java里邊,也有Copy On Write技術。

Java中的COW

這部分留到下一篇來說,敬請期待~

如果大家有更好的理解方式或者文章有錯誤的地方還請大家不吝在評論區留言,大家互相學習交流~~~

參考資料:

  • 寫時復制,寫時拷貝,寫時分裂,Copy on write:https://my.oschina.net/dubenju/blog/815836
  • 不會產奶的COW(Copy-On-Write)https://www.jianshu.com/p/b2fb2ee5e3a0

一個堅持原創的Java技術公眾號:Java3y,歡迎大家關注

3y所有的原創文章:

  • 文章的目錄導航(腦圖+海量視頻資源):https://github.com/ZhongFuCheng3y/3y

轉載于:https://www.cnblogs.com/Java3y/p/9884583.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279051.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279051.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279051.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

參數回調

1.場景 參數回調方式與調用本地 callback 或 listener 相同&#xff0c;只需要在 Spring 的配置文件中聲明哪個參數是 callback 類型即可。 Dubbo 將基于長連接生成反向代理&#xff0c;這樣就可以從服務器端調用客戶端邏輯 2.

matlab胡良劍第五章,MATLAB習題參考答案(胡良劍,孫曉君)

MATLAB習題參考答案第一章 MATLAB入門4、求近似解解&#xff1a;>> x-2:0.05:2;yx.^4-2.^x兩個近似解&#xff1a;y1f(-0.85) -0.0328; y2f(1.250) 0.0630第二章 MATLAB編程與作圖1、 設x是數組&#xff0c;求均值和方差 解&#xff1a;函數文件如下&#xff1a;function…

windows 全局變量_如何在Windows中使用全局系統環境變量

windows 全局變量Any system administrator who spends a good bit of time in the command prompt or batch scripts is probably well aware of built in environment variables Windows offers (i.e. Path, WinDir, ProgramFiles, UserProfile, etc.). If you find yourself…

Day2-T1

原題目 Describe&#xff1a;貪心&#xff0c;左邊和右邊中選字典序小的 code&#xff1a; #include<bits/stdc.h> using namespace std; int n,step,head,tail; char p[50005]; int main() {freopen("bcl.in","r",stdin);freopen("bcl.out&quo…

hadoop編譯java,Hadoop源碼編譯(2.4.1)

背景Hadoop 2.4.1預編譯版本自帶的libhadoop.so是在32位機器上編譯上,導致在64位OS上運行時&#xff0c;總出現如下告警&#xff1a;WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable查看…

C# System.Windows.Forms.NumericUpDown 控件全選其中文字

num_length.Focus(); UpDownBase updbText (UpDownBase)num_length; num_length.Select(0, updbText.Text.Length);轉載于:https://www.cnblogs.com/LuoEast/p/7942476.html

twitter api使用_使用P2創建自己的Twitter風格的組博客

twitter api使用Would you like a great way to post stuff quickly online and communicate with your readers? Here’s how you can use the P2 theme to transform WordPress into a great collaboration and communications platform. 您是否想以一種很好的方式在網上快…

10_30_unittest

1、斷言 1&#xff09;、self.assertEqual(2,res)#期望值qian、結果值hou2&#xff09;TextTestRunner 源碼 必要的參數3&#xff09;測試結果 上下文管理器 with open("test.txt",w,encodingutf-8) as file:runner unittest.TextTestRunner(streamfile,verbosity2)…

用maven profile實現環境配置切換

前言 互聯網后端服務通常會部署多個環境&#xff1a;開發環境、測試環境、預發布環境和生產環境。不同的環境通常有各自的環境配置&#xff0c;例如mysql服務器的地址、用戶名密碼&#xff0c;zookeeper的ip和端口等等。為了使打出的jar包能獲取不同環境的配置&#xff0c;業界…

laravel graphql php,結合 Laravel 初步學習 GraphQL

本文字數&#xff1a;7134&#xff0c;大概需要14.27分鐘。按照官網所述的&#xff1a;A query language for your API一種用于 API 的查詢語言GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a…

wi-fi共享大師免廣告_如何保護Wi-Fi網絡免受入侵

wi-fi共享大師免廣告Insecure Wi-Fi is the easiest way for people to access your home network, leech your internet, and cause you serious headaches with more malicious behavior. Read on as we show you how to secure your home Wi-Fi network. 不安全的Wi-Fi是人們…

MongoDb分片集群認證

本文主要基于已經搭建好的未認證集群&#xff0c;結合上篇Mongodb副本集分片集群模式環境部署&#xff08;https://www.cnblogs.com/woxingwoxue/p/9875878.html&#xff09;&#xff0c; MongoDb分片集群認證幾個主要流程1.在分片集群環境中&#xff0c;副本集內成員之間需要用…

漢克爾變換matlab,HankelTransform

HankelTransform所屬分類&#xff1a;matlab例程開發工具&#xff1a;matlab文件大小&#xff1a;135KB下載次數&#xff1a;66上傳日期&#xff1a;2011-09-17 13:41:39上 傳 者&#xff1a;甜頭說明&#xff1a; Matlab Hankel變換源代碼&#xff0c;可以直接當做MATLAB too…

【材質】色彩基礎

RBG顏色空間 目前&#xff0c;絕大部分顯示器采用的是RGB顏色標準&#xff0c;因此幾乎所有軟件也采用此標準&#xff0c;UE4也不例外。 R、G、B這三個字母分別代表紅色&#xff08;red&#xff09;、綠色&#xff08;green&#xff09;、藍色&#xff08;blue&#xff09;三條…

使用mintty(_如何使用Mintty改善Cygwin控制臺

使用mintty(Cygwin’s great for getting some Linux command-line goodness in Windows, but using the Windows Shell to access it kills some of that magic. Using Mintty and a few other methods, you can make the experience much more luxurious. Cygwin非常適合在Wi…

18.phpmyadmin 4.8.1 遠程文件包含漏洞(CVE-2018-12613)

phpmyadmin 4.8.1 遠程文件包含漏洞&#xff08;CVE-2018-12613&#xff09; phpMyAdmin是一套開源的、基于Web的MySQL數據庫管理工具。其index.php中存在一處文件包含邏輯&#xff0c; 通過二次編碼即可繞過檢查&#xff0c;造成遠程文件包含漏洞。 受影響版本: phpMyAdmin 4.…

開源php面板,寶塔面板nginx安裝終于搞定了

server{listen 80;server_name lvyou.yssknet.com;index index.php index.html index.htm default.php default.htm default.html;root ***********/public;#SSL-START SSL相關配置&#xff0c;請勿刪除或修改下一行帶注釋的404規則#error_page 404/404.html;#SSL-END#ERROR-PA…

[Erlang 0004] Centos 源代碼編譯 安裝 Erlang

由于最終部署的生產環境是Centos&#xff0c;所以我需要在Centos中安裝Erlang B13R04 &#xff0c;第一次做這件事情破費周折&#xff0c;主要是對Erlang依賴的庫不熟悉&#xff0c;總是編譯不過&#xff1b;這里梳理一下安裝過程中的細節&#xff1a; Erlang依賴哪些庫&#x…

關于“Python”的核心知識點整理大全38

14.1.1 創建 Button 類 由于Pygame沒有內置創建按鈕的方法&#xff0c;我們創建一個Button類&#xff0c;用于創建帶標簽的實心矩形。 你可以在游戲中使用這些代碼來創建任何按鈕。下面是Button類的第一部分&#xff0c;請將這個類保存為 文件button.py&#xff1a; button.py …

同步您的Google Chrome書簽,主題等

Do you regularly use Google Chrome on multiple computers? Here’s how you can keep almost everything in your browser synced easily in Google Chrome. 您是否經常在多臺計算機上使用Google Chrome&#xff1f; 您可以通過以下方法在Google Chrome瀏覽器中輕松同步瀏…