文件指针指向进程用户区的一个叫做FILE结构体的东西,FILE结构体中有两个重要的内容分别是文件描述符和缓冲区;
1,文件描述符
一个进程打开或者创建一个新文件文件的时候返回该文件的文件描述符,当后读写文件时将文件描述符作为参数,文件描述符是一个非负的索引值,指向内核中每个进程文件的记录表,所有对设备和文件的操作都通过文件描述符来完成。files_struct结构体中fd字段指向一个叫做文件描述符表的数组,以叫做文件描述符数组,该数组的下标也就是文件描述符,文件描述符的分配规则是从0到n选取一个未被分配的索引值,当一个进程启动时会默认产生三个文件描述符。
stdin (0),stdout(1),stderr(2);分别对应宏STD_FILENO、STDOUT_FILENO和STDERR_FILENO;
所以一般来说一个新创建的文件的文件描述符都是从3开始,依次排序。如果人为关掉默认打开的文件描述符,则新分配的文件描述符就不是从3开始啦。内核会为每一个进程在pcb中保存打开文件的记录表,记录表中的每一项就是打开文件的索引值。Linux用一个数组来管理打开文件的file对象,数组中每一个元素都指向打开文件的描述符,而数组的下标就是文件描述符。
稍微 解释解释一下一个文件的打开过程;
上面说过,进程通过系统调用open()打开文件,open操作在内核里是通过sys_open()实现,同时,sys_open将创建file对像,并在进程打开文件表中寻找未被使用最小
项的下标作为文件描述符,当进程需要对一个文件进行读写操作时只要获取文件描述符就可以找到file对象,file对象中的f_op指向file_operation结构体,这个结构体中的成员都是函数指针,指向各种文件操作的内核函数;
2 缓冲区;
结果显示
使用重定向之后的·结果:
两种结果差异是为什么呢;
因为printf,fwrite是库函数,库函数默认有缓冲区,当输出到屏幕上时,缓冲方式变为行缓冲,然而当把myfile.c的运行结果重定向到file中,缓冲方式变为全缓冲,当代码执行到fork()时,缓冲区还没有填满,此时缓冲区内的东西对于父子进程是共享的。所以会打印两次printf,fwrit;