(转)进程多次打开同一文件分析
父子进程打开同一个文件
首先明确一下,同一个文件在同一个进程中可以被打开多次,只是返回的文件描述符不同。
read、write、lseek都涉及到文件指针,文件指针是跟文件描述符关联在一起,跟物理文件是分开的。看一段程序:
1 #include<stdio.h> 2 #include<string.h> 3 #include<fcntl.h> 4 #include<unistd.h> 5 #include<sys/types.h> 6 #include<sys/stat.h> 7 8 main(){ 9 int fd1,fd2; 10 if((fd1=open("test",O_RDWR|O_CREAT,0600))==-1) 11 perror("open fd1"); 12 if((fd2=open("test",O_RDWR|O_CREAT,0600))==-1) 13 perror("open fd2"); 14 printf("fd1=%d\tfd2=%d\n",fd1,fd2); 15 if(write(fd1,"123\n",4)==-1) 16 perror("write fd1"); 17 if(write(fd2,"456\n",4)==-1) 18 perror("write fd2"); 19 lseek(fd1,0,SEEK_SET); 20 char buf[10]={0}; 21 if(read(fd2,buf,4)<0) 22 perror("read"); 23 printf("read from fd2 %s\n",buf); 24 memset(buf,0x00,sizeof(buf)); 25 if(read(fd1,buf,4)<0) 26 perror("read"); 27 printf("read from fd1 %s\n",buf); 28 close(fd1); 29 close(fd2); 30 }
输出:
fd1=3 fd2=4
read from fd2
read from fd1 456
在没有lseek干扰的情况下,对于read其初始位置是文件开头,以后每次read都从上次读或写结束的位置开始;对于write,每次都从文件的末尾开始。在上面的程序中,先是通过fd1在文件开头写入"123",调用write(fd2,"456\n",4) 时还是在文件开头写入,所以把“123”覆盖了。如果把第17行换成write(fd1,"456\n",4)则不会覆盖之前写入的内容。当调用 lseek(fd1,0,SEEK_SET)之后,read(fd1,buf,4)就是从文件的开头开始读,而read(fd2,buf,4)是从 write(fd2,"456\n",4)结束的位置开始读,所以读到的内容为空。
fork后子进程复制了父进程的文件描述符。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/stat.h>
main(){
int fd1;
if((fd1=open("./file1",O_RDWR))==-1)
perror("openfd1");
pid_t pid=fork();
if(pid==0){
sleep(1);
int fd2;
if((fd2=open("./file1",O_RDWR))==-1)
perror("openfd2");
printf("fd1=%d\tfd2=%d\n",fd1,fd2);
lseek(fd1,0,SEEK_SET);
if(write(fd1,"a",1)==-1)
perror("writefd1");
lseek(fd2,1,SEEK_SET);
if(write(fd2,"b",1)==-1)
perror("writefd2");
close(fd1);
close(fd2);
}
else{
printf("fd1=%d\n",fd1);
lseek(fd1,0,SEEK_SET);
if(write(fd1,"c",1)==-1)
perror("writefd1again");
close(fd1);
}
}
上述代码相当于文件被打开了3次--所以也要close()3次,但是lseek跟文件打开几次没有关系,它只认那一个物理文件,所以文件最终的内容是:ab。
在父进程中已经打开的文件描述符(包括套接口描述符等),在子进程中可以直接使用,每fork一次,这些描述符的引用计数就被加1,所以也要关闭多次,直到引用计数为0.
原文来自:博客园(华夏35度)http://www.cnblogs.com/zhangchaoyang
作者:Orisun