Linux之file_struct&fd(file descriptor)

  Linux中每个进程会产生一个PCB(Process Control Block)进程控制块,既然是一个进程,那么就会在这个进程中对文件进行操作,所以每个PCB中会对应生成一个struct file(文件描述符表),直观的看。每个位置都对应一个指针指向目标文件。这个位置使用open函数来确定的。

open函数

  open函数的原型为:

  int open(const char *pathname, int flags);
  int open(const char *pathname, int flags, mode_t mode);

   其中char*的pathname代表的时文件的路径和名称;
   flags代表的是打开文件的方式,且flags是以int(整型)数据的32比特位表示,所以可以传入多个参数。
   例如:O_WRONLY|O_CREAT:表示以只写方式打开并创建文件(注意中间的’|’符号)。
   参数选项:

   O_RDONLY--只读--00            O_WRONLY--只写--01
   O_RDWR--读写--10               O_CREAT--创建--100

   mode:表示创建完成的文件的权限,可以直接传入8进制数字,例如:400
   返回值:即表示当前操作成功之后系统分配的文件描述符。
   但是,默认情况下,系统默认:0号下标代表stdin;1号下标代表stdout;2号下标代表stderr。
   创建新文件时会将系统中未使用的最小的文件描述符传给返回值,一般情况下,因为0/1/2已经用过,所以第一个文件的文件描述符都为3。
   但是若手动关闭0或1或2号文件流,则会选择最小的。
例:

close(0); 
close(2);
int fd1 = open ("myfile1.txt",O_WRONLY|O_CREAT, 600);
int fd2 = open ("myfile2.txt",O_WRONLY|O_CREAT, 600);

  则此时创建的文件最小的是0,接下来是2,然后才是3,即fd1=0,fd2=2。
  open函数的返回值就是在文件描述符表中确定文件位置的数据。

struct file

  struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。
  它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中。
  struct file的指针通常被命名为file或filp。其有两个非常重要的字段:文件描述符和缓冲区。
  文件描述的产生和作用在上文已经阐述的很清晰了,它和struct file的关系如下图所示这里写图片描述
  这样就很清晰了。

缓冲区

   系统中共存在三种缓冲区:无缓冲,行缓冲,全缓冲。
   无缓冲:一般在在执行系统调用的情况下采用,指的是标准I/O不对字符进行缓冲存储,标准库中的stderr就是采用无缓冲式,保证只要有错误出现就输出。
   行缓冲:系统在执行I/O操作涉及到终端时,就会采用行缓冲。在遇到换行符’\n’时,输入/出之前缓冲区的所有字符。
   全缓冲:这种情况只有在缓冲区全部写满之后才会冲洗缓冲区。对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
  输入/输出重定向:
  重定向:本质上是修改文件描述符的内容
  ‘>’:输出重定向
  ‘>>’:追加重定向
  ‘<’:输入重定向
  例:echo “hello world!\n” > world.txt
  则会将hello world重定向到world.txt文件中
  重定向也可以理解为:在将需要将输出的数据保存在一个文件里面时,创建一个文件,但这个文件此时对应的file_struct中的下标并不是最小且未使用的,而是1号下标。这是因为系统只认文件描述符的原因,所以重定向就是替换file_struct中1号下标的指向,使其指向新创建的保存数据的文件,而已经不是stdout了。所以,使用echo “hello world!\n” > world.txt时,’>’就相当去替换1号下标的指向。所以最终不是输出在显示器上,而是保存在文件里。
  几个函数的冲洗缓冲区的方式:
  printf、fwrite等一些库函数在正常且正确的将需要操作的数据操作完毕后,是不会“管理”缓冲区的,所以此前缓冲区中的数据还留在缓冲区中,如果将当前进程创建出一个子进程,且将函数输出重定向到一个文件中,就会发现本来子进程中什么也没干,但是在子进程的区域还是会有printf、fwrite等库函数操作的数据,这是因为在之前printf、fwrite等库函数操作完数据后,并没有冲洗缓冲区,导致缓冲区还存在数据,此时的子进程因为采用写时拷贝使用父进程的数据,所以此时也会给自己拷贝一份。
  file struct中的其他成员:
  mode_t f_mode:文件模式确定文件时可读、可写或者可读写的的,通过位FMODE_READ和FMODE_WRITE,在open函数中检测这个成员的读写状态时,不需要检查读写许可。
   loff_t f_pos:当前读写位置,在所有平台都市64位,每次读、写后更新这个指针,但需要注意的是,llseek方法可以改变这个指针的指向。
   unsigned int f_flags:文件标志。例如:O_RDONLY, O_NONBLOCK, 和 O_SYNC。
   struct file_operations * f_op:和文件关联的操作。
   void* private_data:open系统电调用设置这个值为NULL,在为open调用系统调用前,你可自由的使用或者忽略这个成员。在系统调用间保留状态信息。
   struct denrty* f_dentry:关联到文件的目录入口( dentry )结构。
其他成员的详细请戳:http://blog.sina.com.cn/s/blog_7943319e01018m3w.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值