亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

FORK()函數的理解是什么

發布時間:2021-10-14 15:22:04 來源:億速云 閱讀:184 作者:柒染 欄目:編程語言

FORK()函數的理解是什么,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

  對于剛剛接觸Unix/Linux操作系統,在Linux下編寫多進程的人來說,fork是最難理解的概念之一:它執行一次卻返回兩個值。

  首先我們來看下fork函數的原型:

  #i nclude <sys/types.h>

  #i nclude <unistd.h>

  pid_t fork(void);

  返回值:

  負數:如果出錯,則fork()返回-1,此時沒有創建新的進程。最初的進程仍然運行。

  零:在子進程中,fork()返回0

  正數:在負進程中,fork()返回正的子進程的PID

  其次我們來看下如何利用fork創建子進程。

  創建子進程的樣板代碼如下所示:

  pid_t child;

  if((child = fork())<0)

  /*錯誤處理*/

  else if(child == 0)

  /*這是新進程*/

  else

  /*這是最初的父進程*/

  fock函數調用一次卻返回兩次;向父進程返回子進程的ID,向子進程中返回0,

  這是因為父進程可能存在很多過子進程,所以必須通過這個返回的子進程ID來跟蹤子進程,

  而子進程只有一個父進程,他的ID可以通過getppid取得。

  下面我們來對比一下兩個例子:

  第一個:

  #include <unistd.h>

  #include <stdio.h>

  int main()

  {

  pid_t pid;

  int count=0;

  pid = fork();

  printf( "This is first time, pid = %d/n", pid );

  printf( "This is second time, pid = %d/n", pid );

  count++;

  printf( "count = %d/n", count );

  if ( pid>0 )

  {

  printf( "This is the parent process,the child has the pid:%d/n", pid );

  }

  else if ( !pid )

  {

  printf( "This is the child process./n")

  }

  else

  {

  printf( "fork failed./n" );

  }

  printf( "This is third time, pid = %d/n", pid );

  printf( "This is fouth time, pid = %d/n", pid );

  return 0;

  }

  運行結果如下:

  問題:

  這個結果很奇怪了,為什么printf的語句執行兩次,而那句“count++;”的語句卻只執行了一次

  接著看:

  #include <unistd.h>

  #include <stdio.h>

  int main(void)

  {

  pid_t pid;

  int count=0;

  pid = fork();

  printf( "Now, the pid returned by calling fork() is %d/n", pid );

  if ( pid>0 )

  {

  printf( "This is the parent process,the child has the pid:%d/n", pid );

  printf( "In the parent process,count = %d/n", count );

  }

  else if ( !pid )

  {

  printf( "This is the child process./n");

  printf( "Do your own things here./n" );

  count ++;

  printf( "In the child process, count = %d/n", count );

  }

  else

  {

  printf( "fork failed./n" );

  }

  return 0;

  }

  運行結果如下:

  現在來解釋上面提出的問題。

  看這個程序的時候,頭腦中必須首先了解一個概念:在語句pid=fork()之前,只有一個進程在執行這段代碼,但在這條語句之后,就變成兩個進程在執行了,這兩個進程的代碼部分完全相同,將要執行的下一條語句都是if ( pid>0 )……。

  兩個進程中,原先就存在的那個被稱作“父進程”,新出現的那個被稱作“子進程”。父子進程的區別除了進程標志符(process ID)不同外,變量pid的值也不相同,pid存放的是fork的返回值。fork調用的一個奇妙之處就是它僅僅被調用一次,卻能夠返回兩次,它可能有三種不同的返回值:

  1. 在父進程中,fork返回新創建子進程的進程ID;

  2.在子進程中,fork返回0;

  3.如果出現錯誤,fork返回一個負值;

  fork出錯可能有兩種原因:(1)當前的進程數已經達到了系統規定的上限,這時errno的值被設置為EAGAIN。(2)系統內存不足,這時errno的值被設置為ENOMEM。

  接下來我們來看看APUE2中對fork的說明:

  The new process created by fork is called the child process. This function is called once but returns twice. The only difference in the returns is that the return value in the child is 0, whereas the return value in the parent is the process ID of the new child. The reason the child's process ID is returned to the parent is that a process can have more than one child, and there is no function that allows a process to o^ain the process IDs of its children. The reason fork returns 0 to the child is that a process can have only a single parent, and the child can always call getppid to o^ain the process ID of its parent. (Process ID 0 is reserved for use by the kernel, so it's not possible for 0 to be the process ID of a child.)

  被fork創建的新進程叫做自進程。fork函數被調用一次,卻兩次返回。返回值唯一的區別是在子進程中返回0,而在父進程中返回子進程的pid。在父進程中要返回子進程的pid的原因是父進程可能有不止一個子進程,而一個進程又沒有任何函數可以得到他的子進程的pid。

  Both the child and the parent continue executing with the instruction that follows the call to fork. The child is a copy of the parent. For example, the child gets a copy of the parent's data space, heap, and stack. Note that this is a copy for the child; the parent and the child do not share these portions of memory. The parent and the child share the text segment (Section 7.6).

  子進程和父進程都執行在fork函數調用之后的代碼,子進程是父進程的一個拷貝。例如,父進程的數據空間、堆棧空間都會給子進程一個拷貝,而不是共享這些內存。

  Current implementations don't perform. a complete copy of the parent's data, stack, and heap, since a fork is often followed by an exec. Instead, a technique called copy-on-write (COW) is used. These regions are shared by the parent and the child and have their protection changed by the kernel to read-only. If either process tries to modify these regions, the kernel then makes a copy of that piece of memory only, typically a "page" in a virtual memory system. Section 9.2 of Bach [1986] and Sections 5.6 and 5.7 of McKusick et al. [1996] provide more detail on this feature.

  我們來給出詳細的注釋

  #include <unistd.h>

  #include <stdio.h>

  int main(void)

  {

  pid_t pid;

  int count=0;

  /*此處,執行fork調用,創建了一個新的進程, 這個進程共享父進程的數據和堆棧空間等,這之后的代碼指令為子進程創建了一個拷貝。 fock 調用是一個復制進程,fock 不象線程需提供一個函數做為入口, fock調用后,新進程的入口就在 fock的下一條語句。*/

  pid = fork();

  /*此處的pid的值,可以說明fork調用后,目前執行的是父進程還是子進程*/

  printf( "Now, the pid returned by calling fork() is %d/n", pid );

  if ( pid>0 )

  {

  /*當fork在子進程中返回后,fork調用又向父進程中返回子進程的pid, 如是該段代碼被執行,但是注意的事,count仍然為0, 因為父進程中的count始終沒有被重新賦值,  這里就可以看出子進程的數據和堆棧空間和父進程是獨立的,而不是共享數據*/

  printf( "This is the parent process,the child has the pid:%d/n", pid );

  printf( "In the parent process,count = %d/n", count );

  }

  else if ( !pid )

  { /*在子進程中對count進行自加1的操作,但是并沒有影響到父進程中的count值,父進程中的count值仍然為0*/

  printf( "This is the child process./n");

  printf( "Do your own things here./n" );

  count++;

  printf( "In the child process, count = %d/n", count );

  }

  else

  {

  printf( "fork failed./n" );

  }

  return 0;

  }

  也就是說,在Linux下一個進程在內存里有三部分的數據,就是"代碼段"、"堆棧段"和"數據段"。"代碼段",顧名思義,就是存放了程序代碼的數據,假如機器中有數個進程運行相同的一個程序,那么它們就可以使用相同的代碼段。"堆棧段"存放的就是子程序的返回地址、子程序的參數以及程序的局部變量。而數據段則存放程序的全局變量,常數以及動態數據分配的數據空間(比如用malloc之類的函數取得的空間)。系統如果同時運行數個相同的程序,它們之間就不能使用同一個堆棧段和數據段。

  仔細分析后,我們就可以知道:

  一個程序一旦調用fork函數,系統就為一個新的進程準備了前述三個段,首先,系統讓新的進程與舊的進程使用同一個代碼段,因為它們的程序還是相同的,對于數據段和堆棧段,系統則復制一份給新的進程,這樣,父進程的所有數據都可以留給子進程,但是,子進程一旦開始運行,雖然它繼承了父進程的一切數據,但實際上數據卻已經分開,相互之間不再有影響了,也就是說,它們之間不再共享任何數據了。

  fork()不僅創建出與父進程代碼相同的子進程,而且父進程在fork執行點的所有上下文場景也被自動復制到子進程中,包括:

  ——全局和局部變量

  ——打開的文件句柄

  ——共享內存、消息等同步對象

  而如果兩個進程要共享什么數據的話,就要使用另一套函數(shmget,shmat,shmdt等)來操作。現在,已經是兩個進程了,對于父進程,fork函數返回了子程序的進程號,而對于子程序,fork函數則返回零,這樣,對于程序,只要判斷fork函數的返回值,就知道自己是處于父進程還是子進程中。

看完上述內容,你們掌握FORK()函數的理解是什么的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南宁市| 丰都县| 惠安县| 临夏县| 泊头市| 宜川县| 沅江市| 陈巴尔虎旗| 买车| 临桂县| 龙南县| 交口县| 德保县| 东安县| 乌鲁木齐市| 高密市| 大丰市| 定南县| 湖北省| 重庆市| 通城县| 翁源县| 禄丰县| 八宿县| 宾阳县| 炎陵县| 峡江县| 廊坊市| 石嘴山市| 左贡县| 襄城县| 宜春市| 湖州市| 南宫市| 遵化市| 精河县| 漯河市| 武定县| 巢湖市| 玛沁县| 长汀县|