文件流的缓冲模式有三种:
_IONBF unbuffered(不带缓冲)
_IOLBF line buffered(行缓冲)
_IOFBF fully buffered(全缓冲)
在对文件以流形式进行操作时,文件表项中的位移量因流的缓冲模式类型不同而不同,如下代码:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int fp;
FILE *PF;
int i=0;
unsigned char c;
PF=fopen(argv[1],"r");
fp=fileno(PF);
if(fork()==0)
{
c=fgetc(PF);
printf("child%c\n",c);
printf("offset of file is %d\n",lseek(fp,0,SEEK_CUR));
sleep(1);
fclose(PF);
return(1);
}
else{
sleep(1);
// rewind(PF);
c=fgetc(PF);
printf("parent %c\n",c);
return(1);
}
return 0;
}
在编译之后,以./test a.c运行,a.c文件包含1000多左右字符,程序的实际输出如下
#a
#offset of file is 1295
造成上述结果是因为父子进程中的文件描述项指向同一文件表项,也即共享其中的状态标志和位移量,而子进程在进行fgetc操作时因PF所指向的文件的系统对流缓冲模式默认为全缓冲,造成fgetc读入的内容长度为全缓冲决的默认长度,文件偏移量也相应偏移对应缓冲块长度,因此文件长度(1295)小于缓冲块的默认长度,文件偏移量也变为1295,父进程再次进行fgetc操作时也相应地从1295处开始,造成其所读内容为▒(数值255所对应文件字符).
若对上述程序进行如下修改,也即在
int main(int argc, char *argv[])
{
int fp;
FILE *PF;
int i=0;
unsigned char c;
PF=fopen(argv[1],"r");
fp=fileno(PF);
if(fork()==0)
{
setvbuf(PF, NULL, _IONBF, 0);
//设置文件流缓冲模式为无缓冲
c=fgetc(PF);
printf("child%c\n",c);
printf("offset of file is %d\n",lseek(fp,0,SEEK_CUR));
sleep(1);
fclose(PF);
return(1);
}
else{
sleep(1);
// rewind(PF);
c=fgetc(PF);
printf("parent %c\n",c);
return(1);
}
return 0;
}
此时文件实际输出内容为
child#
offset of file is 1
parent i
总结:
对文件进行流模式操作时,其虽带来一定的便捷,但也在某些可能情况下带来问题,特别是在多进程对同一文件进行操作环境需加以特别关注
阅读(1327) | 评论(0) | 转发(0) |