<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    嵌入式 fork與vfork的區別

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    fork()與vfock()都是創建一個進程,那他們有什么區別呢?總結有以下三點區別: 
    1.  fork  ():子進程拷貝父進程的數據段,代碼段 
        vfork ( ):子進程與父進程共享數據段 
    2.  fork ()父子進程的執行次序不確定 
        vfork 保證子進程先運行,在調用exec 或exit 之前與父進程數據是共享的,在它調用exec
         或exit 之后父進程才可能被調度運行。 
    3.  vfork ()保證子進程先運行,在她調用exec 或exit 之后父進程才可能被調度運行。如果在
       調用這兩個函數之前子進程依賴于父進程的進一步動作,則會導致死鎖。 
    下面通過幾個例子加以說明: 
    第一:子進程拷貝父進程的代碼段的例子: 

    1. #include<sys/types.h>  
    2. #include<unistd.h>  
    3. #include<stdio.h>  
    4.   
    5. int main()  
    6. {  
    7.     pid_t pid;  
    8.     pid = fork();  
    9.     if(pid<0)  
    10.         printf("error in fork!\n");  
    11.     else if(pid == 0)  
    12.         printf("I am the child process,ID is %d\n",getpid());  
    13.     else   
    14.         printf("I am the parent process,ID is %d\n",getpid());  
    15.     return 0;  
    16.   
    17. }  


    運行結果: 

    1. [root@localhost fork]# gcc -o fork fork.c   
    2. [root@localhost fork]# ./fork  
    1. I am the child process,ID is 4711  
    2. I am the parent process,ID is 4710  


    為什么兩條語 都會打印呢?這是因為fork()函數用于從已存在的進程中創建一個新的進 
    程,新的進程稱為子進程,而原進程稱為父進程,fork ()的返回值有兩個,子進程返回0,
    父進程返回子進程的進程號,進程號都是非零的正整數,所以父進程返回的值一定大于零,
    在pid=fork();語句之前只有父進程在運行,而在pid=fork();之后,父進程和新創建的子進程 
    都在運行,所以如果pid==0,那么肯定是子進程,若pid !=0 (事實上肯定大于0),那么是 
    父進程在運行。而我們知道fork()函數子進程是拷貝父進程的代碼段的,所以子進程中同樣 
    有 
    if(pid<0) 
             printf("error in fork!"); 
         else if(pid==0) 
             printf("I am the child process,ID is %d\n",getpid()); 
         else 
             printf("I am the parent process,ID is %d\n",getpid()); 

    這么一段代碼,所以上面這段代碼會被父進程和子進程各執行一次,最終由于子進程的pid= =0,

    而打印出第一句話,父進程的pid>0,而打印出第二句話。于是得到了上面的運行結果。 
    再來看一個拷貝數據段的例子: 

    1. #include<sys/types.h>  
    2. #include<unistd.h>  
    3. #include<stdio.h>  
    4.   
    5. int main()  
    6. {  
    7.     pid_t pid;  
    8.     int cnt = 0;  
    9.     pid = fork();  
    10.     if(pid<0)  
    11.         printf("error in fork!\n");  
    12.     else if(pid == 0)  
    13.     {  
    14.         cnt++;  
    15.         printf("cnt=%d\n",cnt);  
    16.         printf("I am the child process,ID is %d\n",getpid());  
    17.     }  
    18.     else  
    19.     {  
    20.         cnt++;  
    21.         printf("cnt=%d\n",cnt);  
    22.         printf("I am the parent process,ID is %d\n",getpid());  
    23.     }  
    24.     return 0;  
    25. }  

     

    大家覺著打印出的值應該是多少呢?是不是2 呢?先來看下運行結果吧 

    1. [root@localhost fork]# ./fork2  
    2. cnt=1  
    3. I am the child process,ID is 5077  
    4. cnt=1  
    5. I am the parent process,ID is 5076  

     

    為什么不是2 呢?因為我們一次強調fork ()函數子進程拷貝父進程的數據段代碼段,所以 
    cnt++; 
        printf("cnt= %d\n",cnt);

        return 0 
    將被父子進程各執行一次,但是子進程執行時使自己的數據段里面的(這個數據段是從父進 
    程那copy 過來的一模一樣)count+1,同樣父進程執行時使自己的數據段里面的count+1, 
    他們互不影響,與是便出現了如上的結果。


    那么再來看看vfork ()吧。如果將上面程序中的fork ()改成vfork(),運行結果是什么 
    樣子的呢? 

    1. [root@localhost fork]# gcc -o fork3 fork3.c   
    2. [root@localhost fork]# ./fork3  
    3. cnt=1  
    4. I am the child process,ID is 4711  
    5. cnt=1  
    6. I am the parent process,ID is 4710  
    7. 段錯誤  

     

    本來vfock()是共享數據段的,結果應該是2,為什么不是預想的2 呢?先看一個知識點: 
    vfork 和fork 之間的另一個區別是:vfork 保證子進程先運行,在她調用exec 或exit 之 
    后父進程才可能被調度運行。如果在調用這兩個函數之前子進程依賴于父進程的進一步動 
    作,則會導致死鎖。 
    這樣上面程序中的fork ()改成vfork()后,vfork ()創建子進程并沒有調用exec 或exit,
    所以最終將導致死鎖。 
    怎么改呢?看下面程序: 

    1. #include<sys/types.h>  
    2. #include<unistd.h>  
    3. #include<stdio.h>  
    4.   
    5. int main()  
    6. {  
    7.     pid_t pid;  
    8.     int cnt = 0;  
    9.     pid = vfork();  
    10.     if(pid<0)  
    11.         printf("error in fork!\n");  
    12.     else if(pid == 0)  
    13.     {  
    14.         cnt++;  
    15.         printf("cnt=%d\n",cnt);  
    16.         printf("I am the child process,ID is %d\n",getpid());  
    17.        _exit(0);  
    18.     }  
    19.     else  
    20.     {  
    21.         cnt++;  
    22.         printf("cnt=%d\n",cnt);  
    23.         printf("I am the parent process,ID is %d\n",getpid());  
    24.     }  
    25.     return 0;  
    26.   
    27. }  


     

    如果沒有_exit(0)的話,子進程沒有調用exec 或exit,所以父進程是不可能執行的,在子 
    進程調用exec 或exit 之后父進程才可能被調度運行。 
    所以我們加上_exit(0);使得子進程退出,父進程執行,這樣else 后的語句就會被父進程執行, 
    又因在子進程調用exec 或exit之前與父進程數據是共享的,所以子進程退出后把父進程的數 
    據段count改成1 了,子進程退出后,父進程又執行,最終就將count變成了2,看下實際 
    運行結果: 

    1. [root@localhost fork]# gcc -o fork3 fork3.c   
    2. [root@localhost fork]# ./fork3  
    3. cnt=1  
    4. I am the child process,ID is 4711  
    5. cnt=2  
    6. I am the parent process,ID is 4710  

     

    網上抄的一段,可以再理解理解: 
    為什么會有vfork,因為以前的fork 很傻, 它創建一個子進程時,將會創建一個新的地址 
    空間,并且拷貝父進程的資源,而往往在子進程中會執行exec 調用,這樣,前面的拷貝工 
    作就是白費力氣了,這種情況下,聰明的人就想出了vfork,它產生的子進程剛開始暫時與 
    父進程共享地址空間(其實就是線程的概念了),因為這時候子進程在父進程的地址空間中 
    運行,所以子進程不能進行寫操作,并且在兒子 霸占”著老子的房子時候,要委屈老子一 
    下了,讓他在外面歇著(阻塞),一旦兒子執行了exec 或者exit 后,相 于兒子買了自己的 
    房子了,這時候就相 于分家了。

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全