fork和緩衝區

  fork在面試中常常被問到,在這裏複習一下。面試

  frok建立子進程,父子進程共享.text段,子進程得到父進程數據段、堆和棧的副本,因爲在fork以後常常跟隨者exec,因此不少實現並不執行父進程數據段、堆和棧的徹底複製,而是使用寫時複製(Copy-On-Write,COW)技術。這些區域由父子進程共享,並被內核設爲只讀,若是父子進程試圖修改這些區域,則內核只爲修改區域的那塊內存製做一個副本。函數

接下來的程序演示一下fork函數的功能spa

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>

void err_sys(const char *s)
{
    printf("error:%s",s);
    exit(EXIT_FAILURE);
}

int glob = 6;
char buf[] = "a write to stdout\n";

int main()
{
    int var;
    pid_t pid;

    var = 88;
    if(write(STDOUT_FILENO,buf,sizeof(buf)-1) != sizeof(buf)-1)
        err_sys("write error");
    printf("before fork\n");
    if((pid = fork())<0)
        err_sys("fork error");
    else if(pid == 0)
    {
        glob++;
        var++;
    }
    else
        sleep(2);
    printf("pid = %d,glob = %d,var = %d\n",getpid(),glob,var);
    exit(0);
}

 編譯獲得fork_sample,運行結果以下:.net

當直接執行fork_sample時,結果不出乎意料。在fork前先打印"before fork\n",fork以後父子進程分別打印。unix

可是當程序輸出重定向到temp文件時(即./fork_sample > temp的做用),讀取temp文件(即cat temp),咱們發現"before fork\n"被輸出了兩遍,這是爲何呢?code

這得從標準I/O庫的緩衝提及。blog

標準I/O庫提供了三種類型的緩衝:進程

(1) 全緩衝:填滿標準I/O緩衝區才實際進行I/O操做。內存

(2)行緩衝:在輸入和輸出中遇到換行符時,標準I/O庫執行I/O操做,當流涉及終端時,一般使用行緩衝。get

(3)不帶緩衝:標準出錯流stderr一般是不帶緩衝的。

上面說的緩衝指的是應用層的緩衝,在進行實際的I/O操做時,相關的系統調用(read和write)其實在內核也有緩衝區的。

當直接執行./fork_sample時,因爲標準輸出時行緩衝的,因此遇到換行符'\n'後緩衝區被沖洗。

當將程序輸出重定向到別的文件時,是標準輸出是全緩衝的,fork以前printf的數據仍在緩衝區中,在fork時該緩衝區也被複制到子進程中,所以咱們就會看到"before fork\n"輸出了兩次。

相關文章
相關標籤/搜索