linux的程序
Linux 核心在系統啟動的最後階段會啟動 init 程序。Linux 系統的程序之間存在著明顯的繼承關係,所有的程序都是 pid 為 1 的 init 程序的後代。
其他一些作業系統在建立程序時,首先在地址空間裡建立程序,讀入可執行檔案,最後開始執行。Linux 是類 Unix 的作業系統,關於程序建立,它不同於前面那些作業系統,而是定義了 fork() 和 exec() 兩組函式。這裡以 fork() 函式為例介紹題主所說的“寫時複製”。
fork() 函式透過複製父程序建立子程序,子程序與父程序的區別僅僅在於 pid,ppid 和一些資源的統計量,比如掛起的訊號等。在早期,fork() 函式會將父程序的所有其他資源都複製給子程序。這種設計過於簡單粗暴,因為子程序也許並不需要父程序的資源,如果子程序被建立後,轉而執行和之前毫不相關的工作,那之前複製資源的開銷就浪費了,一點意義也沒有。
為了解決上面提到的可能會出現浪費的問題,“寫時複製”的概念就被提出了。寫時複製是一種可以推遲甚至免去複製資料的技術。子程序被建立後,系統將父程序的資源以只讀的方式共享給子程序,這樣子程序能夠使用原本應該複製給子程序的資料,而同時又不會“汙染”父程序。
這樣一來,如果子程序只需要讀取父程序資料,或者不需要使用父程序的資料,那麼複製就免去了。如果子程序需要寫這部分資料,則為了保證程序之間的資料獨立性,系統才會將父程序的資源複製給子程序。
結合上面這兩點,就是“寫時複製”的含義了,下面給出 demo:
對於上面這種情況,因為子程序沒有用到父程序的 buf,所以系統就免去了複製 buf 100MB 的開銷,提升了效率。
而對於上面這種情況,因為子程序需要寫 buf,系統就不可避免的要把父程序的資源複製給子程序了。
這就是“寫時複製”了。
linux的程序
Linux 核心在系統啟動的最後階段會啟動 init 程序。Linux 系統的程序之間存在著明顯的繼承關係,所有的程序都是 pid 為 1 的 init 程序的後代。
其他一些作業系統在建立程序時,首先在地址空間裡建立程序,讀入可執行檔案,最後開始執行。Linux 是類 Unix 的作業系統,關於程序建立,它不同於前面那些作業系統,而是定義了 fork() 和 exec() 兩組函式。這裡以 fork() 函式為例介紹題主所說的“寫時複製”。
linux建立程序的資源fork() 函式透過複製父程序建立子程序,子程序與父程序的區別僅僅在於 pid,ppid 和一些資源的統計量,比如掛起的訊號等。在早期,fork() 函式會將父程序的所有其他資源都複製給子程序。這種設計過於簡單粗暴,因為子程序也許並不需要父程序的資源,如果子程序被建立後,轉而執行和之前毫不相關的工作,那之前複製資源的開銷就浪費了,一點意義也沒有。
為了解決上面提到的可能會出現浪費的問題,“寫時複製”的概念就被提出了。寫時複製是一種可以推遲甚至免去複製資料的技術。子程序被建立後,系統將父程序的資源以只讀的方式共享給子程序,這樣子程序能夠使用原本應該複製給子程序的資料,而同時又不會“汙染”父程序。
這樣一來,如果子程序只需要讀取父程序資料,或者不需要使用父程序的資料,那麼複製就免去了。如果子程序需要寫這部分資料,則為了保證程序之間的資料獨立性,系統才會將父程序的資源複製給子程序。
例項結合上面這兩點,就是“寫時複製”的含義了,下面給出 demo:
char *buf = (char*)malloc(100*1024*1024);int pid = fork();if(pid==0){ printf("child exit\n"); free(buf); exit(0);}else{ wait(&status); free(buf); exit(0);}對於上面這種情況,因為子程序沒有用到父程序的 buf,所以系統就免去了複製 buf 100MB 的開銷,提升了效率。
char *buf = (char*)malloc(100*1024*1024);int pid = fork();if(pid==0){ buf[0] = 1; printf("child exit\n"); free(buf); exit(0);}else{ wait(&status); free(buf); exit(0);}而對於上面這種情況,因為子程序需要寫 buf,系統就不可避免的要把父程序的資源複製給子程序了。
這就是“寫時複製”了。