标准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.