歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux管理 >> Linux維護

Linux系統調用fork()函數的方法

fork()函數是分叉函數,現有的進程可以調用fork()函數來新建一個新進程,那麼在Linux下要如何調用fork()函數呢?又或者fork()函數要如何在Linux下實現呢?隨小編一起來瞧瞧吧。

1.傳統的fork()系統調用直接把所有的資源復制給新創建的進程.Linux的fork()使用寫時拷貝(copy-on-write)頁實現。寫時拷貝是一種可以推遲甚至免除拷貝數據的技術,內核此時並不復制整個進程地址空間,而是讓父進程和子進程共享同一個拷貝。

只有在需要寫入的時候,數據才會被復制,從而使各個進程擁有各自的拷貝,也就是說,資源的復制只有在需要寫入的時候才進行,在此之前,只是以只讀的方式共享。這種技術使地址空間上的頁的拷貝被推遲到實際發生寫入的時候才進行。在頁跟本不會被寫入的情況下(比如:fork()後立即調用exec())它們就無需復制了。

2.linux通過系統調用clone()來實現fork()。然後由clone()來調用do_fork()。

linux下fork()函數的實現:

Linux通過clone()系統調用實現fork()。這個調用通過一系列的參數標志來指明父,子進程需要共享的資源。fork(),vfork()和__clone()庫函數都根據各自需要的參數標志去調用clone()。然後由clone()去調用do_fork()。

do_frok完成了創建中的大部分工作,它的定義在ker/frok.c文件中。該函數調用copy_process()的函數,然後讓進程開始運行。copy_process()函數完成的工作很有意思:

1.調用dup_task_struct()為新進程創建一個內核棧,thread_info結構和task_struct,這些值與當前進程的值相同。此時,子進程和父進程的描述符是完全相同的。

2.檢查新創建的這個子進程後,當前用戶所擁有的進程數目沒有超出給它分配的資源的限制。

3.現在,子進程著手使自己與父進程區別開來。進程描述符內的許多成員都要被清0或者設為初始值。進程描述符的成員值並不是繼承而來的,而主要是統計信息。進程描述符中的大多數數據都是共享的。

4.接下來,子進程的狀態被設置為TASK_UNINTERRUPTIBLE以保證它不會投入運行。

5.copy_process()調用copy_flags()以更新task_struct的flags成員。表明進程是否擁有超級用戶權限的PF_SUPERPRIV的標志被清0.表明進程還沒有調用exec()函數的PF_FORKNOEXEC標志被設置。

6.調用get_pid()為新進程獲取一個有效的PID。

7.根據傳遞給clone()的參數標志,copy_process()拷貝或共享打開的文件,文件系統信息,信號處理函數,進程地址空間和命名空間等。再一半情況下,這些資源會被給定進程的所有線程共享;否則,這些資源對每個進程是不同的,因此被拷貝到了這裡。

8.讓父進程和子進程平分剩余的時間片。

9.最後,copy_process()做掃尾工作並返回一個指向子進程的指針。

再回到do_fork()函數,如果copy_process()函數返回成功,新創建的子進程被喚醒並讓其投入運行。內核有意選擇子進程首先執行。因為一半子進程都會馬上調用exec()函數,這樣可以避免寫時拷貝的額外開銷,如果父進程首先執行的話,有可能會開始向地址空間寫入。

上面就是Linux調用fork()函數的方法介紹了,本文除了介紹了Linux下調用fork()函數的方法,還對fork()函數的實現做了詳細介紹,希望對你有所幫助。

Copyright © Linux教程網 All Rights Reserved