APUE第3章讲的是文件IO,需要了解一些Linux底层的东西,不然看起来好费劲(我现在就这样- -|)。

首先,讲了文件描述符,文件描述符简单的说就是一个非负整数,你可以通过这个整数来找到打开的文件,比如我们用open函数时返回的是一个整数,这就是open所打开的这个文件的文件描述符,文件描述符是内核向进程返回的。另外shell中的标准输入的文件描述符是0,标准输出是1,错误输出是2,这个是默认这么做的,与内核无关。但是不遵照这个惯例的话,那么很多系统应用程序就不能正常工作。文件描述符的范围是0~OPEN_MAX(每个进程的最大打开文件数),早期的上限是19(即允许每个进程打开20个文件),现在很多系统则增至63.

讲了一个文件空洞的东西,就是如果你现在的文件长度是n,然后你用lseek把文件指针位置定位到了一个大于n的位置,接下来你写一些东西,那么就形成了一个文件空洞,中间那一部分就是文件空洞,文件空洞是不占空间的,你可以用两个同样长度的文件,然后比较他们的文件大小,还有没有写过的字节读出来通通为0

dup和dup2函数,都包含在unistd.h文件中。看到这两个函数的时候,不怎么懂,现在也不保证很懂(-_-|).

dup的原型是int dup(int filedes) ;//传入参数是已打开的文件描述符,返回一个未用的最小的文件描述符。

dup2的原型是int dup2(int oldfiledes,int newfiledes);//返回oldfiledes的一个文件描述符copy,然后返回的文件描述符是newfiledes。如果newfiledes已经打开,就先关闭,如果oldfiledes和newfiledes相等,那么就返回newfiledes,而不关闭它。这些返回的新文件描述符和原来的文件描述符(dup中的filedes和dup2中的oldfiledes)共享一个文件表项。如果出错返回-1,比如dup中的参数filedes是一个未打开的文件描述符

当然这两个函数都可以由fcntl函数来替代,虽然可能不完全等效。比如原子性。

fcntl原型int fcntl(int filedes,int cmd, … / int arg / );

fcntl可以复制文件描述符[cmd=F_DUPFD],可以获得/设置文件描述符[cmd=F_GETFD/F_SETFD],可以获得/设置文件状态标志[cmd=F_GETFL/F_SETFL],可以获得/设置异步I/O所有权[cmd=F_GETOWN/F_SETOWN],可以获得/设置记录锁[cmd=F_GETLK / F_SETLK / F_SETLKW]。出错返回-1.

习题3.2需要自己不用fcntl来实现一个dup2函数,有出错提示。一开始脑袋一团浆糊,网上搜到一篇写这个的,用dup函数实现,出错信息要考虑齐全,另外,就是从0到newfiledes这些描述符中,看是否打开,每个都需要试,最后如果所有条件都符合,就可以返回newfiledes,不过刚开始的童鞋可以先照着网上那份写,再自己慢慢揣摩。

习题3-4中给出,很多程序中都包含下面一段代码:
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
if(fd > 2)
close(fd);
问为啥要关闭,也就是最后的if意义和在,还需要画出fd=1和fd=3时每次调用dup2时3个描述符项及相应的文件表项的变化情况。

首先,前面3句就是相当于重定向,所有的标准输入,标准输出和错误输出都会写道fd所指的文件中去。那么如果fd>2的话,执行那3句之后就有4个文件描述符指向同一个文件表项了。但是如果fd<3的话,就只有3个。所以需要手动的把fd关闭掉

Comments