系統編程-多進程-前後fork或open一個文件的區別

 

Linux內核的文件結構體ui

struct file {
    .........    
    struct path        f_path;            //文件的路徑
#define f_dentry    f_path.dentry
#define f_vfsmnt    f_path.mnt
    const struct file_operations    *f_op;//訪問方式
    atomic_long_t        f_count;        //文件的引用計數,引用計數值爲0時,文件纔會關閉
    unsigned int         f_flags;        //標誌位
    mode_t            f_mode;            //讀寫等權限
    loff_t            f_pos;             //讀到了哪一個位置
    struct fown_struct    f_owner;
    unsigned int        f_uid, f_gid;   //文件所屬uid,gid
    struct file_ra_state    f_ra;

    u64            f_version;
#ifdef CONFIG_SECURITY
    void            *f_security;
#endif
    /* needed for tty driver, and maybe others */
    void            *private_data;
    
    .............
};

文件的引用計數,引用計數值爲0時,文件纔會被關閉。atom

 

兩種情景分析:spa

1.fork()以前就open了文件,而且讀取了部份內容3d

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h>

int main()
{
    int fd = open("tmp.txt",O_RDONLY);
    assert(fd!=-1);

    char buff[10]={0};

    pid_t pid = fork();

    if(pid == 0){
            read(fd,buff,1);  //子進程讀1個字節內容
        printf("buff = %s\n",buff);

    }else if(pid  > 0){
        sleep(5);         //保證子進程能夠先讀文件
        read(fd,buff,2);  //父進程讀2個字節
        printf("buff = %s\n",buff);
        wait(NULL);       //收屍,不獲取死因
    }
    
    close(fd);
    return 0;    
}

 tmp.txt的內容爲「niceday」指針

root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# gcc process.c  -o ab
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# 
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# ./ab
buff = n
buff = ic

小結:code

先open再fork,文件只被打開一次,父子進程共享一個文件描述信息,包括引用計數、讀取位置等等。blog

雖然父子進程都讀取了該文件,因爲文件的引用計數始終爲1,因此只須要close一次便可。繼承

能夠在子進程代碼分支中close,也能夠在父進程代碼分支close,還能夠在公共部分close。進程

子進程複製了父進程的文件表項指針, 指向的是同一個文件表項,以下圖:ci

 

 

2.fork()調用以後open文件

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h>

int main()
{
    pid_t pid = fork();

    int fd = open("tmp.txt",O_RDONLY);
    assert(fd!=-1);

    char buff[10]={0};

    if(pid == 0){
            read(fd,buff,1);  //子進程讀1個字節內容
        printf("buff = %s\n",buff);

    }else if(pid  > 0){
        sleep(5);         //保證子進程能夠先讀文件
        read(fd,buff,2);  //父進程讀2個字節
        printf("buff = %s\n",buff);
        wait(NULL);       //收屍,不獲取死因
    }
    
    close(fd);
    return 0;    
}

tmp.txt的內容爲「niceday」, 同上。

root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# gcc process.c  -o ab
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# 
root@lmw-virtual-machine:/home/lmw/MINE/Linux_C_exercise/process# ./ab
buff = n
buff = ni

小結:

此時的文件描述信息再也不是共享的,一個文件被打開了兩次,即引用計數值爲2,每一個進程都有本身的一份,因此兩個進程讀寫操做互不影響。

 

總結:

先open,再fork:子進程無條件繼承父進程的文件描述信息,子進程和父進程指向同一個文件描述信息。
先fork,再open:子進程有本身的配置,和父進程的配置是相互獨立的關係。所謂配置,例如文件描述信息。

 

 

 

 

 

 

.

相關文章
相關標籤/搜索