1、 重定向
1)Linux2.6.9上,一个进程可以打开的文件描述符为1024个,WindowsXP sp3上为512个,均包括默认打开的stdin,stdout以及stderr。每次fopen返回新的FILE结构,其中_file记录了当前文件描述符(int类型),_flag记录文件打开方式(1为读,2为写,128为读写)。
2)freopen并不创建新的FILE结构,也不改变文件描述符_file,仅仅改写_flag,当然还通过某种方式告知内核该文件描述符引用的文件变化了,令人郁闷的是,这个变化并不体现在FILE结构中。
freopen到底干了什么?freopen后,FILE*中的文件描述符并没有变,它实际上是修改了文件描述符表中的文件表指针。即先通过fopen打开一个文件,得到新的文件表,将原来的文件表引用计数器递减,然后修改文件描述符表中的文件表指针。只有内核才能通过文件描述符,找到其对应的文件表指针,从文件描述符到文件表指针系统没有提供用户接口。
3)fclose(fp)时,将fp结构中的_flag设置为0,表示该结构可以回收利用,即可分配给下一个调用fopen的返回值使用。stdin,stdout以及stderr是指向FILE结构的指针,也可以使用fclose将其关闭。也就是说其他使用fopen打开的文件描述符也可以占用stdin,stdout以及stderr原先使用的FILE结构(如果它们之前被fclose关闭的话),stdin,stdout以及stderr被没有什么“特权”。需要注意的是如果stdin,stdout以及stderr被关闭,它们仍然指向原FILE结构,但这个结构很可能已经被其他文件描述符占用了!使用fclose关闭一个FILE*后不应该再使用它。
2、 文件描述符与FILE*的关系
Linux系统
从FILE*到文件描述可以使用:
int fileno(FILE *)
从文件描述符到FILE* 可以用:
FILE* fdopen(int fd, char *mode)
示例:FILE* pfile = fdopen(fd, “w”); //以写方式打开
dup()或者DuplicateHandle()复制的是文件文件描述符表,即文件描述符变了,但指向同一个文件表,而fork()复制父进程的内容,连文件描述符都相同,当然也指向同一个文件表。
dup和dup2的本质,将新的文件描述符关联到原文件描述符所关联的文件表。dup(intfd)创建一个新的文件描述符,将其关联到fd关联的文件表,然后返回这个新的文件描述符。dup2(intfd1, int fd2)使用fd2关联到fd1所关联的文件表,如果fd已经打开,则先将其关闭。
3、 O_APPEND标志的作用
它的意思是每次写操作之前将当前文件偏移量移到文件末尾,从而避免多个进程同时写文件时相互覆盖写入文件的数据。我之前以为只是打开文件时移到文件末尾,以后就不用管了。
4、 文件缓冲
int servbuf(FILE *f, char *buf, int mode, size_t size);
其中mode可以是
_IOFBF:全缓冲,如果buf为NULL,则由标准库分配内存,如果由用户提供,注意这段buf的作用域,必须保证fflush之前它是有效的。
_IOLBF:行缓冲,如果buf为NULL,则由标准库分配内存,如果由用户提供,注意这段buf的作用域,必须保证fflush之前它是有效的。
_IONBF:无缓冲,忽略buf和size参数
对于全缓冲和行缓冲,size必须大于等于2,且C运行期库自动取偶数。
大于缓冲长度时才刷到文件中,默认打开一个文件时f->_bufsize为0