精华内容
下载资源
问答
  • (1)struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何...
  • C语言中的FILE结构体

    万次阅读 多人点赞 2017-05-20 21:51:10
    联系2.2和2.3上面的内容,可以发现,应该是这样的:FILE结构体中的_file成员应该是指向进程级打开文件表,然后,通过进程级打开文件表可以找到系统级打开文件表,进而可以通过FCB操作物理磁盘上面的文件。...

    内存中的数据都是暂时的,当程序结束时,它们都将丢失。为了永久性的保存大量的数据,C语言提供了对文件的操作。

    1、文件和流

    C将每个文件简单地作为顺序字节流(如下图)。每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中。当打开文件时,就建立了和文件的关系。在开始执行程序的时候,将自动打开3个文件和相关的流:标准输入流、标准输出流和标准错误。流提供了文件和程序的通信通道。例如,标准输入流使得程序可以从键盘读取数据,而标准输出流使得程序可以在屏幕上输出数据。打开一个文件将返回指向FILE结构(在stdio.h中定义)的指针,它包含用于处理文件的信息,也就是说,这个结构包含文件描述符。文件描述符是操作系统数组(打开文件列表的索引)。每个数组元素包含一个文件控制块(FCB, File Control Block),操作系统用它来管理特定的文件。标准输入、标准输出和标准错误是用文件指针stdin、stdout和stderr来处理的。

    2、C语言文件操作的底层实现简介

    2.1 FILE结构体

    C语言的stdio.h头文件中,定义了用于文件操作的结构体FILE。这样,我们通过fopen返回一个文件指针(指向FILE结构体的指针)来进行文件操作。可以在stdio.h(位于visual studio安装目录下的include文件夹下)头文件中查看FILE结构体的定义,如下:

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. struct _iobuf {  
    2.         char *_ptr;  
    3.         int   _cnt;  
    4.         char *_base;  
    5.         int   _flag;  
    6.         int   _file;  
    7.         int   _charbuf;  
    8.         int   _bufsiz;  
    9.         char *_tmpfname;  
    10.         };  
    11. typedef struct _iobuf FILE;  

    2.2 C语言文件管理的实现

     

    C程序用不同的FILE结构管理每个文件。程序员可以使用文件,但是不需要知道FILE结构的细节。实际上,FILE结构是间接地操作系统的文件控制块 (FCB)来实现对文件的操作的,如下图:

    上面图中的_file实际上是一个描述符,作为进入打开文件表索引的整数。

    2.3 操作系统文件管理简介

    从2.2中的图可以看出,C语言通过FILE结构可以间接操作文件控制块(FCB)。为了加深对这些的理解,这里科普下操作系统对打开文件的管理。

    文件是存放在物理磁盘上的,包括文件控制块(FCB)和数据块。文件控制块通常包括文件权限、日期(创建、读取、修改)、拥有者、文件大小、数据块信息。数据块用来存储实际的内容。对于打开的文件,操作系统是这样管理的:系统维护了两张表,一张是系统级打开文件表【指向i节点】,一张是进程级打开文件表(每个进程有一个)【指向FILE结构体】。系统级打开文件表复制了文件控制块的信息等;进程级打开文件表保存了指向系统级文件表的指针及其他信息。 系统级文件表每一项都保存一个计数器,即该文件打开的次数。我们初次打开一个文件时,系统首先查看该文件是否已在系统级文件表中,如果不在,则创建该项信息,否则,计数器加1。当我们关闭一个文件时,相应的计数也会减1,当减到0时,系统将系统级文件表中的项删除。 进程打开一个文件时,会在进程级文件表中添加一项。每项的信息包括当前文件偏移量(读写文件的位置)、存取权限、和一个指向系统级文件表中对应文件项的指针。系统级文件表中的每一项通过文件描述符(一个非负整数)来标识。

    联系2.2和2.3上面的内容,可以发现,应该是这样的:FILE结构体中的_file成员应该是指向进程级打开文件表,然后,通过进程级打开文件表可以找到系统级打开文件表,进而可以通过FCB操作物理磁盘上面的文件。

    2.4 文件操作的例子

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include <stdio.h>  
    2. void main() {  
    3.     FILE * fp1;  
    4.     FILE * fp2;  
    5.     fp1 = fopen(“filetest.cpp”,”r”);  
    6.     fp2 = fopen(“filetest.cpp”,”r”);  
    7.     char buffer[256];  
    8.     fscanf(fp1,“%s”,buffer);  
    9.     printf(“%s\n”,buffer);  
    10.     fscanf(fp2,“%s”,buffer);  
    11.     printf(“%s\n”,buffer);  
    12.     printf(“fp1(filetest.cpp):%d\n”,fp1->_file);  
    13.     printf(“fp2(filetest.cpp):%d\n”,fp2->_file);  
    14.     printf(“stdin:%d\n”,stdin->_file);  
    15.     printf(“stdout:%d\n”,stdout->_file);  
    16.     printf(“stderr:%d\n”,stderr->_file);  
    17. }  

    filetest.cpp中的内容如下:

     

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include<stdio.h>  
    2. int main()  
    3. {  
    4.     printf(“Hello World!\n”);  
    5.     return 0;  
    6. }  

    运行结果如下:

     

    通过这个程序可以看出,应该是每打开一次文件,哪怕多次打开的都是同一个文件,进程级打开文件表中应该都会添加一个记录。如果是打开的是同一个文件,这多条记录对应着同一个物理磁盘文件。由于每一次打开文件所进行的操作都是通过进程级打开文件表中不同的记录来实现的,这样,相当于每次打开文件的操作是相对独立的,这就是上面的程序的运行结果中,两次读取文件的结果是一样的(而不是第二次读取从第一次结束的位置进行)。

    另外,还可以看出,程序运行的时候,默认三个流是打开的stdin,stdout和stderr,它们的_file描述符分别是0、1和2。也可以看出,该程序打开的文件描述符依次从3开始递增。

    3、顺序访问文件

    3.1 顺序写入文件

    先看一个例子:

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include <stdio.h>  
    2. int main()  
    3. {  
    4.     int account;//账号  
    5.     char name[30];//账号名  
    6.     double balance;//余额  
    7.   
    8.     FILE *cfPtr;  
    9.     if ((cfPtr=fopen(”clients.dat”,”w”))==NULL)  
    10.     {  
    11.         printf(“File could not be opened.\n”);  
    12.     }  
    13.     else  
    14.     {  
    15.         printf(“Enter the account, name and the balance:\n”);  
    16.         printf(“Enter EOF to end input.\n”);  
    17.         printf(“? ”);  
    18.         scanf(“%d%s%lf”,&account,name,&balance);  
    19.         while(!feof(stdin))  
    20.         {  
    21.             fprintf(cfPtr,“%d %s %.2f\n”,account,name,balance);  
    22.             printf(“? ”);  
    23.             scanf(“%d%s%lf”,&account,name,&balance);  
    24.         }  
    25.         fclose(cfPtr);  
    26.     }  
    27.     return 0;  
    28. }  

    运行结果:

    从上面的例子中可以看出,写入文件大致需两步:定义文件指针和打开文件。函数fopen有两个参数:文件名和文件打开模式。文件打开模式‘w’说明文件时用于写入的。如果以写入模式打开的文件不存在,则fopen将创建该文件。如果打开现有的文件来写入,则将抛弃文件原有的内容而没有任何警告。在程序中,if语句用于确定文件指针cfPtr是否是NULL(没有成功打开文件时fopen的返回值)。如果是NULL,则将输出错误消息,然后程序终止。否则,处理输入并写入到文件中。

    foef(stdin)用来确定用户是否从标准输入输入了文件结束符。文件结束符通知程序没有其他数据可以处理了。foef的参数是指向测试是否为文件结束符的FILE指针。一旦输入了文件结束符,函数将返回一个非零值;否则,函数返回0。当没有输入文件结束符时,程序继续执行while循环。

    fprintf(cfPtr,”%d %s %.2f\n”,account,name,balance);向文件clients.dat中写入数据。稍后通过用于读取文件的程序,就可以提取数据。函数fprintf和printf等价,只是fprintf还需要一个指向文件的指针,所有数据都写入到这个文件中。

    在用户输入文件结束之后,程序用fclose关闭clients.dat文件,并结束运行。函数fclose也接收文件指针作为参数。如果没有明确地调用函数fclose,则操作系统通常在程序执行结束的稍后关闭文件。这是操作系统“内务管理”的一个示例,但是,这样可能会带来一些难以预料的问题,所以一定要注意在使用结束之后关闭文件。

    3.2 文件打开模式

     

    模式说明
    r打开文件,进行读取。
    w创建文件,以进行写入。如果文件已经存在,则删除当前内容。
    a追加,打开或创建文件以在文件尾部写入。
    r+打开文件以进行更新(读取和写入)。
    w+创建文件以进行更新。如果文件已经存在,则删除当前内容。
    a+追加,打开或者创建文件以进行更新,在文件尾部写入。

    3.3 顺序读取文件

     

    下面的例子读取的是上一个例子中写入数据生成的文件。

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include <stdio.h>  
    2. int main()  
    3. {  
    4.     int account;//账号  
    5.     char name[30];//账号名  
    6.     double balance;//余额  
    7.   
    8.     FILE *cfPtr;  
    9.     if ((cfPtr=fopen(”clients.dat”,”r”))==NULL)  
    10.     {  
    11.         printf(“File could not be opened.\n”);  
    12.     }  
    13.     else  
    14.     {  
    15.         printf(“%-10s%-13s%s\n”,”Account”,”Name”,”Balance”);  
    16.         fscanf(cfPtr,“%d%s%lf”,&account,name,&balance);  
    17.         while(!feof(cfPtr))  
    18.         {  
    19.             printf(“%-10d%-13s%lf\n”,account,name,balance);  
    20.             fscanf(cfPtr,“%d%s%lf”,&account,&name,&balance);  
    21.         }  
    22.         fclose(cfPtr);  
    23.     }  
    24.     return 0;  
    25. }  

    运行结果:

     

    上面的例子中,只需将第一个例子中的文件打开模式从w变为r,就可以打开文件读取数据。

    同样地,fscanf(cfPtr,”%d%s%lf”,&account,name,&balance);函数从文件中读取一条记录。函数fscanf和函数scanf等价看,只是fscanf接收将从中读取数据的文件指针作为参数。在第一次执行前面的语句时,account的值为100,name的值是Jones,而balance等于24.98。每次执行第二条fscanf语句时,将从文件中读取另一条记录,而account,name和balance将有新值。当到达文件结束位置时,关闭文件,而程序终止。

    要从文件中顺序检索数据,程序通常从文件的开始来读取,而且连续读取所有数据,直至找到期望的数据。在程序执行过程中,有可能会多次处理文件中的数据(重新从文件的开头处理数据)。这时候就要用到函数rewind(cfPtr);,它可以使程序的文件位置指针(表示文件中将要读取或者写入的下一个字节的位置)重新设置到文件的开头(也就是偏移量为0的字节)。注意,文件位置指针并不是指针,它是指定文件中将进行下一次读取或者写入的位置的整数值,有时候也称其为文件偏移量,它是FILE结构的成员。

    4、随机访问文件

    文件中用格式化输入函数fprintf所创建的记录的长度并不是完全一致的。然而,在随机访问文件中,单个记录的长度通常是固定的,而且可以直接访问(这样速度更快)而无需通过其他记录来查找。这使得随机文件访问适合飞机订票系统,银行系统,销售点系统和其他需要快速访问特定数据的事务处理系统。我们可以有很多方法来实现随机访问文件,但是这里我们将把讨论的范围限制在使用固定长度记录的简单方法上。

    函数fwrite把从内存中特定位置开始的指定数量的字节写入到文件位置指针指定的文件位置,函数fread从文件位置指针指定的文件位置处把指定数量的字节复制到指定的内存位置。fwrite和fread可以从磁盘上读取数据数组,以及向磁盘上写入数据数组。fread和fwrite的第三个参数是从磁盘中读取或者写入到磁盘上的数组元素的个数。

    文件处理程序很少向文件中写入字段。通常情况下,它们一次写入一个struct。

    4.1 创建随机访问的文件

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include<stdio.h>  
    2. struct clientData  
    3. {  
    4.     int acctNum;  
    5.     char lastName[15];  
    6.     char firstName[10];  
    7.     double balance;  
    8. };  
    9. int main()  
    10. {  
    11.     int i;  
    12.     struct clientData blankClient={0,”“,”“,0.0};  
    13.     FILE *cfPtr;  
    14.     if ((cfPtr = fopen(”credit.dat”,”wb”))== NULL)  
    15.     {  
    16.         printf(“File could not be opened.\n”);  
    17.     }  
    18.     else  
    19.     {  
    20.         for (i=1;i<=100;i++)  
    21.         {  
    22.             fwrite(&blankClient,sizeof(struct clientData),1,cfPtr);  
    23.         }  
    24.         fclose(cfPtr);  
    25.     }  
    26.     return 0;  
    27. }  

     

    fwrite(&blankClient,sizeof(struct clientData),1,cfPtr);用于向文件中写入一个数据块,其会在cfPtr指向的文件中写入大小为sizeof(struct clientData)的结构blankClient。当然,也可以写入对象数组的多个元素,只需把数组名传给第一个参数,把要写入的元素个数写入第三个参数即可。

    4.2 随机向随机访问文件中写入数据

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include<stdio.h>  
    2. struct clientData  
    3. {  
    4.     int acctNum;  
    5.     char lastName[15];  
    6.     char firstName[10];  
    7.     double balance;  
    8. };  
    9. int main()  
    10. {  
    11.     int i;  
    12.     struct clientData client={0,”“,”“,0.0};  
    13.     FILE *cfPtr;  
    14.     if ((cfPtr = fopen(”credit.dat”,”rb+”))== NULL)  
    15.     {  
    16.         printf(“File could not be opened.\n”);  
    17.     }  
    18.     else  
    19.     {  
    20.         printf(“Enter account number(1 to 100, 0 to end input):\n”);  
    21.         scanf(“%d”,&client.acctNum);  
    22.         while (client.acctNum!=0)  
    23.         {  
    24.             printf(“Enter lastname, firstname, balance\n”);  
    25.             fscanf(stdin,“%s%s%lf”,client.lastName,client.firstName,&client.balance);  
    26.             //在文件中定位用户指定的记录  
    27.             fseek(cfPtr,(client.acctNum-1)*sizeof(struct clientData),SEEK_SET);  
    28.             //将用户指定的信息写入文件  
    29.             fwrite(&client,sizeof(struct clientData),1,cfPtr);  
    30.   
    31.             //输入下一个账号  
    32.             printf(“Enter account number:\n”);  
    33.             scanf(“%d”,&client.acctNum);  
    34.         }  
    35.         fclose(cfPtr);  
    36.     }  
    37.     return 0;  
    38. }  

    运行结果:

     

    fseek(cfPtr,(client.acctNum-1)*sizeof(struct clientData),SEEK_SET);将cfPtr所引用文件的位置指针移动到由(client.acctNum-1)*sizeof(struct clientData)计算所得到的字节位置处,这个表达式的值称为偏移量或者位移。负号常量SEEK_SET说明,文件位置指针指向的位置是相对于文件开头的偏移量。

    ANSI标准制定了fseek的函数原型为int fseek(FILE *stream, long int offset, int whence);其中offset是stream指向的文件中从位置whence开始的字节数。参数whence可以有三个值:SEEK_SET, SEEKCUR或者SEEK_END,分别对应文件的开头当前位置和结尾。 4.2 从随机访问文件中读取数据

     

    [cpp]  view plaincopy在CODE上查看代码片派生到我的代码片



    1. #include<stdio.h>  
    2. struct clientData  
    3. {  
    4.     int acctNum;  
    5.     char lastName[15];  
    6.     char firstName[10];  
    7.     double balance;  
    8. };  
    9. int main()  
    10. {  
    11.     struct clientData client={0,”“,”“,0.0};  
    12.     FILE *cfPtr;  
    13.     if ((cfPtr = fopen(”credit.dat”,”rb”))== NULL)  
    14.     {  
    15.         printf(“File could not be opened.\n”);  
    16.     }  
    17.     else  
    18.     {  
    19.         printf(“%-6s%-16s%-11s%10s\n”,”Acct”,”Last name”,”First name”,”Balance”);  
    20.         while(!feof(cfPtr))  
    21.         {  
    22.             fread(&client,sizeof(struct clientData),1,cfPtr);  
    23.             if (client.acctNum!=0)  
    24.             {  
    25.                 printf(“%-6d%-16s%-11s%10.2f\n”,client.acctNum,client.lastName,client.firstName,client.balance);  
    26.             }  
    27.         }  
    28.         fclose(cfPtr);  
    29.     }  
    30.     return 0;  
    31. }  

    运行结果:

     

    好了,终于完了。照样和原来一样,类似于笔记的东西。whatever,晚上开会,求轻虐。吐舌头

    参考:

    http://blog.csdn.net/xia7139/article/details/17142619

    (1) 《C语言程序设计经典教程》

    (2) http://hi.baidu.com/sangwf/item/4023100cf126af3af2eafc26

    ==分割线===============================================================================================

     

    文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。

     

    文件指针:C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符。而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。

     

    附:文件系统

     

    VFS

    Linux支持各种各样的文件系统格式,如ext2、ext3、reiserfs、FAT、NTFS、iso9660等等,不同的磁盘分区、光盘或其它存储设备都有不同的文件系统格式,然而这些文件系统都可以mount到某个目录下,使我们看到一个统一的目录树,各种文件系统上的目录和文件我们用ls命令看起来是一样的,读写操作用起来也都是一样的,这是怎么做到的呢?Linux内核在各种不同的文件系统格式之上做了一个抽象层,使得文件、目录、读写访问等概念成为抽象层的概念,因此各种文件系统看起来用起来都一样,这个抽象层称为虚拟文件系统(VFS,Virtual Filesystem)。上一节我们介绍了一种典型的文件

     

    系统在磁盘上的存储布局,这一节我们介绍运行时文件系统在内核中的表示。

     

    内核数据结构

    Linux内核的VFS子系统可以图示如下:

     

     

     

    第 28 章 文件与I/O中讲过,每个进程在PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针,现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。

     

    在file结构体中维护File Status Flag(file结构体的成员f_flags)和当前读写位置(file结构体的成员f_pos)。在上图中,进程1和进程2都打开同一文件,但是对应不同的file结构体,因此可以有不同的File Status Flag和读写位置。file结构体中比较重要的成员还有f_count,表示引用计数(Reference Count),后面我们会讲到,dup、fork等系统调用会导致多个文件描述符指向同一个file结构体,例如有fd1和fd2都引用同一个file结构体,那么它的引用计数就是2,当close(fd1)时并不会释放file结构体,而只是把引用计数减到1,如果再close(fd2),引用计数就会减到0同时释放file结构体,这才真的关闭了文件。

     

    每个file结构体都指向一个file_operations结构体,这个结构体的成员都是函数指针,指向实现各种文件操作的内核函数。比如在用户程序中read一个文件描述符,read通过系统调用进入内核,然后找到这个文件描述符所指向的file结构体,找到file结构体所指向的file_operations结构体,调用它的read成员所指向的内核函数以完成用户请求。在用户程序中调用lseek、read、write、ioctl、open等函数,最终都由内核调用file_operations的各成员所指向的内核函数完成用户请求。file_operations结构体中的release成员用于完成用户程序的close请求,之所以叫release而不叫close是因为它不一定真的关闭文件,而是减少引用计数,只有引用计数减到0才关闭文件。对于同一个文件系统上打开的常规文件来说,read、write等文件操作的步骤和方法应该是一样的,调用的函数应该是相同的,所以图中的三个打开文件的file结构体指向同一个file_operations结构体。如果打开一个字符设备文件,那么它的read、write操作肯定和常规文件不一样,不是读写磁盘的数据块而是读写硬件设备,所以file结构体应该指向不同的file_operations结构体,其中的各种文件操作函数由该设备的驱动程序实现。

     

    每个file结构体都有一个指向dentry结构体的指针,“dentry”是directory entry(目录项)的缩写。我们传给open、stat等函数的参数的是一个路径,例如/home/akaedu/a,需要根据路径找到文件的inode。为了减少读盘次数,内核缓存了目录的树状结构,称为dentry cache,其中每个节点是一个dentry结构体,只要沿着路径各部分的dentry搜索即可,从根目录/找到home目录,然后找到akaedu目录,然后找到文件a。dentry cache只保存最近访问过的目录项,如果要找的目录项在cache中没有,就要从磁盘读到内存中。

     

    每个dentry结构体都有一个指针指向inode结构体。inode结构体保存着从磁盘inode读上来的信息。在上图的例子中,有两个dentry,分别表示/home/akaedu/a和/home/akaedu/b,它们都指向同一个inode,说明这两个文件互为硬链接。inode结构体中保存着从磁盘分区的inode读上来信息,例如所有者、文件大小、文件类型和权限位等。每个inode结构体都有一个指向inode_operations结构体的指针,后者也是一组函数指针指向一些完成文件目录操作的内核函数。和file_operations不同,inode_operations所指向的不是针对某一个文件进行操作的函数,而是影响文件和目录布局的函数,例如添加删除文件和目录、跟踪符号链接等等,属于同一文件系统的各inode结构体可以指向同一个inode_operations结构体。

     

    inode结构体有一个指向super_block结构体的指针。super_block结构体保存着从磁盘分区的超级块读上来的信息,例如文件系统类型、块大小等。super_block结构体的s_root成员是一个指向dentry的指针,表示这个文件系统的根目录被mount到哪里,在上图的例子中这个分区被mount到/home目录下。

     

    file、dentry、inode、super_block这几个结构体组成了VFS的核心概念。对于ext2文件系统来说,在磁盘存储布局上也有inode和超级块的概念,所以很容易和VFS中的概念建立对应关系。而另外一些文件系统格式来自非UNIX系统(例如Windows的FAT32、NTFS),可能没有inode或超级块这样的概念,但为了能mount到Linux系统,也只好在驱动程序中硬凑一下,在Linux下看FAT32和NTFS分区会发现权限位是错的,所有文件都是rwxrwxrwx,因为它们本来就没有inode和权限位的概念,这是硬凑出来的。

     

    参考:

    http://m.blog.chinaunix.net/uid-20672257-id-1901040.html

    展开全文
  • Linux file 结构体和 inode 结构体

    千次阅读 2018-02-27 11:06:11
    在设备驱动程序中,一般需要关心两个结构体file 和 inode。1. file 结构体file 结构体代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件...

    在设备驱动程序中,一般需要关心两个结构体:file 和 inode。

    1. file 结构体

    file 结构体代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的 struct file。

    它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。

    注:在内核和驱动源代码中,struct file 的指针通常被命名为 file 或 filp(即 file pointer)。

    struct file {
    	union {
    		struct llist_node	fu_llist;
    		struct rcu_head 	fu_rcuhead;
    	} f_u;
    	struct path		f_path;
    	struct inode		*f_inode;	/* cached value */
    	const struct file_operations	*f_op;		/* 和文件关联的操作 */
    
    	/*
    	 * Protects f_ep_links, f_flags.
    	 * Must not be taken from IRQ context.
    	 */
    	spinlock_t		f_lock;
    	enum rw_hint		f_write_hint;
    	atomic_long_t		f_count;
    	unsigned int 		f_flags;	        /* 文件标志,如O_RDONLY、O_NONBLOCK、O_SYNC */
    	fmode_t			f_mode;			/* 文件读/写模式,FMODE_READ、FMODE_WRITE */
    	struct mutex		f_pos_lock;
    	loff_t			f_pos;			/* 当前读写位置 */
    	struct fown_struct	f_owner;
    	const struct cred	*f_cred;
    	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;		/* 文件私有数据 */
    
    #ifdef CONFIG_EPOLL
    	/* Used by fs/eventpoll.c to link all the hooks to this file */
    	struct list_head	f_ep_links;
    	struct list_head	f_tfile_llink;
    #endif /* #ifdef CONFIG_EPOLL */
    	struct address_space	*f_mapping;
    	errseq_t		f_wb_err;
    } __randomize_layout
      __attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */
    
    struct file_handle {
    	__u32 handle_bytes;
    	int handle_type;
    	/* file identifier */
    	unsigned char f_handle[0];
    };

    文件读/写模式 mode、标志 f_flags 都是设备驱动关心的内容,而私有数据指针 private_data 在设备驱动中被广泛应用,大多被指向设备驱动自定义以用于描述设备的结构体。


    2. inode 结构体

    VFS inode 包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改事件等信息。它是 Linux 管理文件系统的基本单位,也是文件系统连接任何子目录、文件的桥梁,inode 结构体的定义如下:

    struct inode {
    	umode_t			i_mode;							/* inode的权限 */
    	unsigned short		i_opflags;					
    	kuid_t			i_uid;							/* inode拥有者的id */
    	kgid_t			i_gid;							/* inode所属的群组id */
    	unsigned int		i_flags;
    
    #ifdef CONFIG_FS_POSIX_ACL
    	struct posix_acl	*i_acl;
    	struct posix_acl	*i_default_acl;
    #endif
    
    	const struct inode_operations	*i_op;
    	struct super_block	*i_sb;
    	struct address_space	*i_mapping;
    
    #ifdef CONFIG_SECURITY
    	void			*i_security;
    #endif
    
    	/* Stat data, not accessed from path walking */
    	unsigned long		i_ino;
    	/*
    	 * Filesystems may only read i_nlink directly.  They shall use the
    	 * following functions for modification:
    	 *
    	 *    (set|clear|inc|drop)_nlink
    	 *    inode_(inc|dec)_link_count
    	 */
    	union {
    		const unsigned int i_nlink;
    		unsigned int __i_nlink;
    	};
    	dev_t			i_rdev;							/* 若是设备文件,此字段将记录设备的设备号 */
    	loff_t			i_size;							/* inode所代表的文件大小 */
    	struct timespec		i_atime;					/* inode最近一次的存取时间 */
    	struct timespec		i_mtime;					/* inode最近一次的修改时间 */
    	struct timespec		i_ctime;					/* inode的产生时间 */
    	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
    	unsigned short          i_bytes;
    	unsigned int		i_blkbits;
    	enum rw_hint		i_write_hint;
    	blkcnt_t		i_blocks;						/* inode所使用的block数,一个block为512字节 */
    
    #ifdef __NEED_I_SIZE_ORDERED
    	seqcount_t		i_size_seqcount;
    #endif
    
    	/* Misc */
    	unsigned long		i_state;
    	struct rw_semaphore	i_rwsem;
    
    	unsigned long		dirtied_when;	/* jiffies of first dirtying */
    	unsigned long		dirtied_time_when;
    
    	struct hlist_node	i_hash;
    	struct list_head	i_io_list;	/* backing dev IO list */
    #ifdef CONFIG_CGROUP_WRITEBACK
    	struct bdi_writeback	*i_wb;		/* the associated cgroup wb */
    
    	/* foreign inode detection, see wbc_detach_inode() */
    	int			i_wb_frn_winner;
    	u16			i_wb_frn_avg_time;
    	u16			i_wb_frn_history;
    #endif
    	struct list_head	i_lru;		/* inode LRU list */
    	struct list_head	i_sb_list;
    	struct list_head	i_wb_list;	/* backing dev writeback list */
    	union {
    		struct hlist_head	i_dentry;
    		struct rcu_head		i_rcu;
    	};
    	u64			i_version;
    	atomic_t		i_count;
    	atomic_t		i_dio_count;
    	atomic_t		i_writecount;
    #ifdef CONFIG_IMA
    	atomic_t		i_readcount; /* struct files open RO */
    #endif
    	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
    	struct file_lock_context	*i_flctx;
    	struct address_space	i_data;
    	struct list_head	i_devices;
    	union {
    		struct pipe_inode_info	*i_pipe;
    		struct block_device	*i_bdev;			/* 若是块设备,为其对应的block_device结构体指针 */
    		struct cdev		*i_cdev;				/* 若是字符设备,为其对应的cdev结构体指针 */
    		char			*i_link;
    		unsigned		i_dir_seq;
    	};
    
    	__u32			i_generation;
    
    #ifdef CONFIG_FSNOTIFY
    	__u32			i_fsnotify_mask; /* all events this inode cares about */
    	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
    #endif
    
    #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
    	struct fscrypt_info	*i_crypt_info;
    #endif
    
    	void			*i_private; /* fs or device private pointer */
    } __randomize_layout;

    展开全文
  • FILE结构体详解

    千次阅读 2017-05-07 21:44:15
     struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何...

    1.1 struct file
      struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。

    struct file 的最重要成员在这展示.
    1.mode_t f_mode;
    文件模式确定文件是可读的或者是可写的(或者都是), 通过位 FMODE_READ 和FMODE_WRITE. 你可能想在你的 open 或者 ioctl 函数中检查这个成员的读写许可, 但是不需要检查读写许可, 因为内核在调用你的方法之前检查. 当文件还没有为那种存取而打开时读或写的企图被拒绝, 驱动甚至不知道这个情况.
    2.loff_t f_pos;
    当前读写位置. loff_t 在所有平台都是 64 位( 在 gcc 术语里是 long long ). 驱动可以读这个值,如果它需要知道文件中的当前位置, 但是正常地不应该改变它; 读和写应当使用它们作为最后参数而收到的指针来更新一个位置, 代替直接作用于 filp->f_pos. 这个规则的一个例外是在 llseek 方法中, 它的目的就是改变文件位置.
    3.unsigned int f_flags;
    这些是文件标志, 例如 O_RDONLY, O_NONBLOCK, 和 O_SYNC. 驱动应当检查O_NONBLOCK 标志来看是否是请求非阻塞操作; 其他标志很少使用. 特别地, 应当检查读/写许可, 使用 f_mode 而不是f_flags. 所有的标志在头文件

    ifdef __NEED_I_SIZE_ORDERED

    seqcount_t i_size_seqcount;

    endif

    struct timespec i_atime;
    struct timespec i_mtime;
    struct timespec i_ctime;
    unsigned int i_blkbits;
    blkcnt_t i_blocks;
    unsigned short i_bytes;
    umode_t i_mode;
    spinlock_t i_lock;
    struct mutex i_mutex;
    struct rw_semaphore i_alloc_sem;
    const struct inode_operations *i_op;
    const struct file_operations *i_fop;
    struct super_block *i_sb;
    struct file_lock *i_flock;
    struct address_space *i_mapping;
    struct address_space i_data;

    ifdef CONFIG_QUOTA

    struct dquot *i_dquot[MAXQUOTAS];

    endif

    struct list_head i_devices;
    union {
    struct pipe_inode_info *i_pipe;
    struct block_device *i_bdev;
    struct cdev *i_cdev; //该成员表示字符设备的内核的 内部结构。当inode指向一个字符设备文件时,该成员包含了指向struct cdev结构的指针,其中cdev结构是字符设备结构体。
    };
    int i_cindex;

    __u32 i_generation;

    ifdef CONFIG_DNOTIFY

    unsigned long i_dnotify_mask;
    struct dnotify_struct *i_dnotify;

    endif

    ifdef CONFIG_INOTIFY

    struct list_head inotify_watches;
    struct mutex inotify_mutex;

    endif

    unsigned long i_state;
    unsigned long dirtied_when;

    unsigned int i_flags;

    atomic_t i_writecount;

    ifdef CONFIG_SECURITY

    void *i_security;

    endif

    void *i_private;
    };

      我们在进程中打开一个文件F,实际上就是要在内存中建立F的dentry,和inode结构,并让它们与进程结构联系来,把VFS中定义的接口给接起来。我们来看一看这个经典的图:
    这里写图片描述

    下图为多个进程打开同一文件的情况:
    这里写图片描述

    展开全文
  • file结构体详解

    千次阅读 2017-07-23 19:37:02
     struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数...

    转载自:

    1.1 struct file
      struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。

     

    struct file 的最重要成员在这展示.
    1.mode_t f_mode;
          文件模式确定文件是可读的或者是可写的(或者都是), 通过位 FMODE_READ 和FMODE_WRITE. 你可能想在你的 open 或者 ioctl 函数中检查这个成员的读写许可, 但是不需要检查读写许可, 因为内核在调用你的方法之前检查. 当文件还没有为那种存取而打开时读或写的企图被拒绝, 驱动甚至不知道这个情况.
    2.loff_t f_pos;
          当前读写位置. loff_t 在所有平台都是 64 位( 在 gcc 术语里是 long long ). 驱动可以读这个值,如果它需要知道文件中的当前位置, 但是正常地不应该改变它; 读和写应当使用它们作为最后参数而收到的指针来更新一个位置, 代替直接作用于 filp->f_pos. 这个规则的一个例外是在 llseek 方法中, 它的目的就是改变文件位置.
    3.unsigned int f_flags;
          这些是文件标志, 例如 O_RDONLY,O_NONBLOCK, 和 O_SYNC. 驱动应当检查O_NONBLOCK 标志来看是否是请求非阻塞操作; 其他标志很少使用. 特别地, 应当检查读/写许可, 使用 f_mode 而不是f_flags. 所有的标志在头文件<linux/fcntl.h> 中定义.
    4.struct file_operations *f_op;
          和文件关联的操作. 内核安排指针作为它的open 实现的一部分, 接着读取它当它需要分派任何的操作时.filp->f_op 中的值从不由内核保存为后面的引用; 这意味着你可改变你的文件关联的文件操作, 在你返回调用者之后新方法会起作用. 例如, 关联到主编号 1 (/dev/null,/dev/zero, 等等)的 open 代码根据打开的次编号来替代 filp->f_op 中的操作. 这个做法允许实现几种行为, 在同一个主编号下而不必在每个系统调用中引入开销. 替换文件操作的能力是面向
    对象编程的"方法重载"的内核对等体.
    5.void *private_data;
         open 系统调用设置这个指针为 NULL, 在为驱动调用 open 方法之前. 你可自由使用这个成员或者忽略它; 你可以使用这个成员来指向分配的数据, 但是接着你必须记住在内核销毁文件结构之前, 在 release 方法中释放那个内存. private_data 是一个有用的资源, 在系统调用间保留状态信息, 我们大部分例子模块都使用它.
    6.struct dentry *f_dentry;
    关联到文件的目录入口( dentry)结构. 设备驱动编写者正常地不需要关心 dentry 结构, 除了作为 filp->f_dentry->d_inode 存取 inode 结构.


    file 结构如下所示:
      struct file {
      union {
      struct list_head fu_list; 文件对象链表指针linux/include/linux/list.h
      struct rcu_head fu_rcuhead; RCU(Read-CopyUpdate)是Linux 2.6内核中新的锁机制
      } f_u;
      struct path f_path; 包含dentry和mnt两个成员,用于确定文件路径
      #define f_dentry f_path.dentryf_path的成员之一,当前文件的dentry结构
      #define f_vfsmnt f_path.mnt 表示当前文件所在文件系统的挂载根目录
      const struct file_operations *f_op;与该文件相关联的操作函数
      atomic_t f_count; 文件的引用计数(有多少进程打开该文件)
      unsigned int f_flags; 对应于open时指定的flag
      mode_t f_mode; 读写模式:open的mod_t mode参数
      off_t f_pos; 该文件在当前进程中的文件偏移量
      struct fown_struct f_owner; 该结构的作用是通过信号进行I/O时间通知的数据。
      unsigned int f_uid, f_gid; 文件所有者id,所有者组id
      struct file_ra_state f_ra; 在linux/include/linux/fs.h中定义,文件预读相关
      unsigned long f_version;
      #ifdef CONFIG_SECURITY
      void *f_security;
      #endif
      
      void *private_data;
      #ifdef CONFIG_EPOLL
      
      struct list_headf_ep_links;
      spinlock_t f_ep_lock;
      #endif
      struct address_space*f_mapping;
      };
      1.2 struct dentry
      dentry的中文名称是目录项,是Linux文件系统中某个索引节点(inode)的链接。这个索引节点可以是文件,也可以是目录。 inode(可理解为ext2 inode)对应于物理磁盘上的具体对象,dentry是一个内存实体,其中的d_inode成员指向对应的inode。也就是说,一个inode可以在运行的时候链接多个dentry,而d_count记录了这个链接的数量。
      struct dentry {
      atomic_t d_count; 目录项对象使用计数器,可以有未使用态,使用态和负状态
      unsigned int d_flags; 目录项标志
      struct inode * d_inode; 与文件名关联的索引节点
      struct dentry * d_parent; 父目录的目录项对象
      struct list_head d_hash; 散列表表项的指针
      struct list_head d_lru; 未使用链表的指针
      struct list_head d_child; 父目录中目录项对象的链表的指针
      struct list_head d_subdirs; 对目录而言,表示子目录目录项对象的链表
      struct list_head d_alias; 相关索引节点(别名)的链表
      int d_mounted; 对于安装点而言,表示被安装文件系统根项
      struct qstr d_name; 文件名
      unsigned long d_time;
      structdentry_operations *d_op; 目录项方法
      struct super_block * d_sb; 文件的超级块对象
      vunsigned longd_vfs_flags;
      void * d_fsdata; 与文件系统相关的数据
      unsigned char d_iname [DNAME_INLINE_LEN];存放短文件名
      };
      1.3 struct files_struct
      对于每个进程,包含一个files_struct结构,用来记录文件描述符的使用情况,定义在include/linux/file.h中
      struct files_struct
      {
      atomic_t count; 使用该表的进程数
      struct fdtable *fdt;
      struct fdtable fdtab;
      spinlock_t file_lock____cacheline_aligned_in_smp;
      int next_fd; 数值最小的最近关闭文件的文件描述符,下一个可用的文件描述符
      struct embedded_fd_set close_on_exec_init;执行exec时需要关闭的文件描述符初值集合
      struct embedded_fd_set open_fds_init;文件描述符的屏蔽字初值集合
      struct file * fd_array[NR_OPEN_DEFAULT];默认打开的fd队列
      };
      struct fdtable {
      unsigned int max_fds;
      struct file ** fd; 指向打开的文件描述符列表的指针,开始的时候指向fd_array,
      当超过max_fds时,重新分配地址
      fd_set *close_on_exec; 执行exec需要关闭的文件描述符位图(fork,exec即不被子进程继承的文件
      描述符)
      fd_set *open_fds; 打开的文件描述符位图
      struct rcu_head rcu;
      struct fdtable *next;
      };
      1.4 struct fs_struct
      struct fs_struct {
      atomic_t count; 计数器
      rwlock_t lock; 读写锁
      int umask;
      struct dentry * root, * pwd, *altroot;根目录("/"),当前目录以及替换根目录
      struct vfsmount * rootmnt, * pwdmnt, *altrootmnt;
      };
      1.5 struct inode
      索引节点对象由inode结构体表示,定义文件在linux/fs.h中。
      struct inode {
      struct hlist_node i_hash; 哈希表
      struct list_head i_list; 索引节点链表
      struct list_head i_dentry; 目录项链表
      unsigned long i_ino; 节点号
      atomic_t i_count; 引用记数
      umode_t i_mode; 访问权限控制
      unsigned int i_nlink; 硬链接数
      uid_t i_uid; 使用者id
      gid_t i_gid; 使用者id组
      kdev_t i_rdev; 实设备标识符
      loff_t i_size; 以字节为单位的文件大小
      struct timespec i_atime; 最后访问时间
      struct timespec i_mtime; 最后修改(modify)时间
      struct timespec i_ctime; 最后改变(change)时间
      unsigned int i_blkbits; 以位为单位的块大小
      unsigned long i_blksize; 以字节为单位的块大小
      unsigned long i_version; 版本号
      unsigned long i_blocks; 文件的块数
      unsigned short i_bytes; 使用的字节数
      spinlock_t i_lock; 自旋锁
      struct rw_semaphore i_alloc_sem;索引节点信号量
      struct inode_operations *i_op; 索引节点操作表
      struct file_operations *i_fop; 默认的索引节点操作
      struct super_block *i_sb; 相关的超级块
      struct file_lock *i_flock; 文件锁链表
      struct address_space *i_mapping;相关的地址映射
      struct address_space i_data; 设备地址映射
      struct dquot*i_dquot[MAXQUOTAS];节点的磁盘限额
      struct list_head i_devices; 块设备链表
      struct pipe_inode_info *i_pipe;管道信息
      struct block_device *i_bdev; 块设备驱动
      unsigned long i_dnotify_mask;目录通知掩码
      struct dnotify_struct *i_dnotify;目录通知
      unsigned long i_state; 状态标志
      unsigned long dirtied_when;首次修改时间
      unsigned int i_flags; 文件系统标志
      unsigned char i_sock; 套接字
      atomic_t i_writecount; 写者记数
      void *i_security; 安全模块
      __u32 i_generation; 索引节点版本号
      union {
      void *generic_ip;文件特殊信息
      } u;
      };

     

    1、struct inode──字符设备驱动相关的重要结构介绍

    内核中用inode结构表示具体的文件,而用file结构表示打开的文件描述符。Linux2.6.27内核中,inode结构体具体定义如下:
    struct inode
     {
    struct hlist_node   i_hash;
    struct list_head   i_list;
    struct list_head   i_sb_list;
    struct list_head   i_dentry;
    unsigned long      i_ino;
    atomic_t      i_count;
    unsigned int      i_nlink;
    uid_t         i_uid;
    gid_t         i_gid;
     dev_t         i_rdev;  //该成员表示设备文件的inode结构,它包含了真正的设备编号。
    u64         i_version;
    loff_t         i_size;
    #ifdef __NEED_I_SIZE_ORDERED
    seqcount_t      i_size_seqcount;
    #endif
    struct timespec      i_atime;
    struct timespec      i_mtime;
    struct timespec      i_ctime;
    unsigned int      i_blkbits;
    blkcnt_t      i_blocks;
    unsignedshort         i_bytes;
    umode_t         i_mode;
    spinlock_t      i_lock;   
    struct mutex      i_mutex;
    struct rw_semaphore   i_alloc_sem;
    const struct inode_operations   *i_op;
    const struct file_operations   *i_fop;   
    struct super_block   *i_sb;
    struct file_lock   *i_flock;
    struct address_space   *i_mapping;
    struct address_space   i_data;
    #ifdef CONFIG_QUOTA
    struct dquot      *i_dquot[MAXQUOTAS];
    #endif
    struct list_head   i_devices;
    union {
    struct pipe_inode_info   *i_pipe;
    struct block_device   *i_bdev;
     struct cdev      *i_cdev; //该成员表示字符设备的内核的内部结构。当inode指向一个字符设备文件时,该成员包含了指向struct cdev结构的指针,其中cdev结构是字符设备结构体。
    };
    int         i_cindex;

    __u32         i_generation;

    #ifdef CONFIG_DNOTIFY
    unsigned long      i_dnotify_mask;
    struct dnotify_struct   *i_dnotify;
    #endif

    #ifdef CONFIG_INOTIFY
    struct list_head   inotify_watches;
    struct mutex      inotify_mutex;   
    #endif

    unsigned long      i_state;
    unsigned long      dirtied_when;   

    unsigned int      i_flags;

    atomic_t      i_writecount;
    #ifdef CONFIG_SECURITY
    void         *i_security;
    #endif
    void         *i_private;
    };


      我们在进程中打开一个文件F,实际上就是要在内存中建立F的dentry,和inode结构,并让它们与进程结构联系来,把VFS中定义的接口给接起来。我们来看一看这个经典的图:

    file结构体详解

     

    下图为多个进程打开同一文件的情况:

    file结构体详解
    展开全文
  • FILE结构体

    2018-05-03 16:28:13
    联系2.2和2.3上面的内容,可以发现,应该是这样的:FILE结构体中的_file成员应该是指向进程级打开文件表,然后,通过进程级打开文件表可以找到系统级打开文件表,进而可以通过FCB操作物理磁盘上面的文件。...
  • Linux下的FILE结构体

    千次阅读 2017-02-19 20:34:26
    struct file结构体定义在/linux/include/linux/fs.h(Linux 2.6.11内核)中,其原型是: struct file { /* * fu_list becomes invalid after file_free is called and queued via * fu_rcuhead for RCU fr
  • FILE结构体成员

    千次阅读 2017-05-01 20:01:09
    可以在stdio.h(位于visual studio安装目录下的include文件夹下)头文件中查看FILE结构体的定义 2 FILE结构体的成员 #ifndef _FILE_DEFINED struct _iobuf { char *_ptr; //文件输入的下一个位置 int _...
  • hi all and barry, ...驱动中添加一个设备结构体,然后定义了这个结构体的全局指针变量,接着我们就能在  驱动程序中使用这个指针了。我看到很多驱动程序中都把结构体指针付给private_data,  然后对...
  • Linux中的file结构体解析

    千次阅读 2017-02-20 11:07:07
    Linux–struct file结构体struct file(file结构体): struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。 它由...
  • FILE结构体 base指针:指向缓存区 ptr指针:指向下一个字符的位置   标准C的IO缓存类型 全缓存:要求填满整个缓存区才进行I/O系统调用操作。对于磁盘文件通常使用全缓存访问。 行缓存:涉及一个终端时(例如...
  • 练习open/read/write/close等文件相关系统调用接口,纵向对比fd与FILE结构体 对之前编写的自主shell进行修改,使其支持输入/输出/追加重定向 &lt;1&gt;.open函数: 函数原型: int open(const char *...
  • struct file 结构体

    千次阅读 2017-11-11 21:30:30
  • file结构体

    2018-03-10 17:22:42
     struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何...
  • 这篇片博客会比较长,里面的很多实例都会进行详细的演示和分析,读者耐心一点,尽量找完整的时间一次看完 FILE 结构体fopen函数mode 详解:文件读操作文件写操作filea 操作小结 FILE 结构体 FILE 结构体是对缓冲区和...
  • C语言_文件操作_FILE结构体

    千次阅读 2016-08-27 23:56:19
    联系2.2和2.3上面的内容,可以发现,应该是这样的:FILE结构体中的_file成员应该是指向进程级打开文件表,然后,通过进程级打开文件表可以找到系统级打开文件表,进而可以通过FCB操作物理磁盘上面的文件。
  • Linux(三)文件描述符和FILE结构体

    千次阅读 2018-04-11 13:53:14
    当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件,于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*file...
  • 本篇文章主要讲解C++中的文件操作的相关简介。 一.C++文件简介 c++支持以下两种文件类型: 1.文本文件,又称ASCII字符文件,其每一个字节存放一个ASCII字符。...指针fp指向FILE结构,用于存放文件信
  • 零、前言 程序可以理解为硬盘上的普通二进制文件...在每一个PCB中,都有一个文件描述符表,通过文件描述符索引指向 file 结构体 (系统打开文件表)。 文件描述符在形式上是一个非负整数,实际上,它是一个索引值,指
  • fd(文件描述符)与FILE结构体

    千次阅读 2018-04-11 16:14:28
    2、本质上访问文件都是通过fd访问的,库函数封装了fd,所以,FILE结构体内部肯定封装了fd。 3.fork缓冲问题。 //行缓冲:比如写入显示器中,输入的数先进入行缓冲区,当满足条件时在进一步输出到屏幕。 ...
  • FILE结构体(文件描述符及缓冲区)

    千次阅读 2017-05-13 21:51:25
    FILE结构体 C语言的stdio.h头文件中,定义了用于文件操作的结构体FILE。这样,我们通过fopen返回一个文件指针(指向FILE结构体的指针)来进行文件操作。可以在stdio.h(位于visual studio安装目录下的include文件夹下)...
  • 参考资料: 《Linux驱动开发入门与实战》,概念及源码主要参考《Linux驱动开发入门与实战》...Linux 字符设备驱动结构(一)—— cdev 结构体、设备号相关知识解析 https://blog.csdn.net/zqixiao_09/article/det...
  • Linux FILE结构体

    2020-08-24 16:50:27
    FILE结构体 struct file { …  atomic_t f_count; //文件的引用计数(有多少进程打开该文件) unsigned int f_flags; //对应于open时指定的flag mode_t f_mode; //读写模式:open的mod_t mode参数 off_t f_pos; //该...
  • 文件标识符(fd)和FILE结构体

    千次阅读 2018-03-24 22:28:34
    当我们打开一个文件的时候,操作系统在内存中会创建相应的数据结构来描述这个文件,所以就有了file结构体。当进程执行open系统调用的时候,就需要将文件和进程关联起来,每个进程都有一个指针files*,指向表files_...
  • FILE结构体 文件描述符
  • struct file结构体

    2020-01-24 13:29:36
    介绍struct file结构体的设计目的于来源
  • C语言 FILE结构体解释

    千次阅读 2016-09-25 21:17:48
    struct _iobuf { char *_ptr; //文件输入的下一个位置 int _cnt; //当前缓冲区的相对位置 ...int _file; //文件的有效性验证 int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取 int _buf
  • FILE结构体与fd文件标识符

    千次阅读 2017-05-13 20:23:36
    FILE结构体我们通常对文件进行操作时,都会使用一些与文件相关的函数,比如:打开文件:FILE *fopen(const char *path,const char* mode) 关闭文件:int fclose(FILEE *fp) 读文件:size_t fread(void *ptr,size_t ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 129,152
精华内容 51,660
关键字:

file结构体