标准I/O函数的实现是基于缓冲的,并且程序能够在同一个流上执行输入和输出。因此有两个限制:
限制一:跟在输出函数之后的输入函数。如果中间没有插入队fflust, fseek, fsetpos或者rewind的调用,一个输入函数跟随在一个输出函数之后。
限制二:跟在输入函数之后的输出函数。如果中间没有插入队fflust, fseek, fsetpos或者rewind的调用,一个输出函数跟随在一个输入函数之后
这并不是硬性限制,即,即使你违反这两个限制,也不会有什么编译连接错误,程序同样可以执行。只是程序可能不会按预期执行。
因为带缓冲的I/O并不是你每次调用都会陷入内核。它会把你写入的数据先放入缓冲,等缓冲区满了,再调用Unix I/O函数实际写入文件。缓冲的读函数每次陷入内核都会读取一块很大的数据或者遇到EOF,标准I/O读函数实际上是每次从缓冲区读取数据,缓冲区没有数据才会陷入内核。
当需要同一个流上同时进行读写时,为了程序能正确执行,应该遵从这两个限制。
下面的例子是一直不停的向文件中写入0,1,2… n同时把当前写入的数显示在标准输出上。
int main() { //文件要存在 FILE *fp = fopen("tt.txt", "rw+"); if (fp == NULL) { perror("fopen: "); return 0; } int v = 0, n; char buff[10]; sprintf(buff, "%d", v); while(fwrite(buff, strlen(buff), 1, fp)>0) { fflush(fp); n = strlen(buff); fseek(fp, -n, SEEK_CUR); memset(buff, 0, 10); fread(buff, n, 1, fp); printf("-%s-\n", buff); v++; sprintf(buff, "%d", v); sleep(1); } fclose(fp); }
同时不建议把标准I/O用于套接字描述符,因为对套接字使用lseek函数是非法的。参考《深入理解计算机系统》p611.