系统编程-多进程-前后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:子进程有本身的配置,和父进程的配置是相互独立的关系。所谓配置,例如文件描述信息。

 

 

 

 

 

 

.

相关文章
相关标签/搜索