可以说一切文件系统的基础是系统调用: open , creat, Xseek , read, write ... ,因为操作FS 必须不停的和IO进行打交道,要想获得高性能FS,就要在IO上下大功夫.另外高级IO没有提供读取文件的元数据的方式,比如文件的size, create Time
............................................................
各个IO操作参数不说,请参考APUE或其它,若不清楚,可以回帖一起讨论
文件打开都是通过文件描述符进行应用,文件描述符是一个Non-Negative. 有 0 (standard inpu), 1(output), 2(erroor) ,在低级IO中用STDIN_FILENO, STDOUT_FILENO 和 STDERR_FILENO 进行代替. 文件描述符 是个很小的正整数,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表 .
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main() { int fd1,fd2; fd1 = open("test", O_RDONLY, 0); /* close(fd1); */ /**< 打开和关闭close注释查看文件描述符 */ fd2 = open("test", O_RDONLY, 0); printf("%d\n",fd1); return 0; }
再看这段代码:
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main() { int fd1,fd2,fd3; fd1 = open("test", O_RDONLY, 0); fd2 = open("test", O_RDONLY, 0); fd3 = open("test", O_RDONLY, 0); //....不停的open呢? printf("%d\n",fd3); return 0; }
下面再看个有意思的:
read 和 write 的原型:
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, void *buf, size_t count);
注意到函数前的返回类型没? 这里说下ssize_t 为int型 ,而size_t为unsigned int .为什么不用size_t 留给读者去思考吧.
根据内核数据结构来分析IO操作.
下面仔细看下面的图:
示例程序,test文件中有crazy内容
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main() { int fd1,fd2; char c; fd1 = open("test", O_RDONLY, 0); fd2 = open("test", O_RDONLY, 0); read(fd1, &c, 1); read(fd2, &c, 1); printf("%c\n",c); return 0; }请问输出什么?
此图分为三个表:依次为 描述符表,文件表,V-Node表
文件表:包含一些文件位置,引用计数(由描述符表指向的引用数)
V-Node表:包含一些 文件大小 ,文件类型等信息
此图是引用不同的文件.还可以共享文件,引用同一个文件.
再看下父子进程共享文件.
再来看这个程序,test还是 "crazy" 内容
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main() { int fd1; char c; fd1 = open("test", O_RDONLY, 0); if (fork() == 0) { read(fd1, &c, 1); exit(0); } wait(NULL); read(fd1, &c, 1); printf("%c\n",c); return 0; }
...............................
最后来看下dup2 ,先看段代码:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main() { int fd1,fd2; char c; fd1 = open("test", O_RDONLY, 0); fd2 = open("test", O_RDONLY, 0); read(fd2, &c, 1); dup2(fd2, fd1); read(fd1, &c, 1); printf("%c\n",c); return 0; }
再来看下图:
再参考原先这个图
描述符1对应于文件A,描述符4对应于文件B,A和B的引用计数都为1 ,dup2(4,1)后,两个文件描述符都指向B,文件A和它的文件表和V-node表都已经删除.文件B的引用计数增加了1 现在为2 .
(读 <<Computer Systems A Programmer's Perspective>> 总结)