博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初级文件IO——若干种文件共享操作 如何影响 文件文件描述符表
阅读量:5797 次
发布时间:2019-06-18

本文共 4412 字,大约阅读时间需要 14 分钟。

同一进程共享操作相同的文件

在同一个进程中多次open打开同一文件时,文件描述符可能会相同吗?

答:不可能。在同一进程里面,一旦某个文件描述符被用了,在close释放之前,别人不可能使用,所以指向同一文件的描述符不可能相同。

代码演示

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 8 #define FILE_NAME "./file.txt" 9 10 void print_error(char * str)11 {12 perror(str);13 exit(-1);14 }15 16 int main(void)17 {18 int fd1 = 0;19 int fd2 = 0;20 21 fd1 = open(FILE_NAME, O_RDWR|O_TRUNC|O_APPEND);22 if(-1 == fd1) print_error("1 open fail");23 24 fd2 = open(FILE_NAME, O_RDWR|O_TRUNC|O_APPEND);25 if(fd2 == -1) print_error("2 open fail");26 27 printf("fd1 = %d, fd2 = %d\n", fd1, fd2); 28 29 while(1)30 {31 write(fd2, "world\n", 6);32 sleep(1);33 write(fd1, "hello\n", 6);34 }35 36 return 0;37 }
View Code

file.txt文件内容会出现覆盖写情况,看看共享操作时的文件描述符表长啥样

由图知道,正是由于不同的文件描述符,各自对应一个独立的文件表,在文件表中有属于自己的“文件位移量”,开始时都是0。各自从0开始写,每写一个字节向后移动一个字节,他们写的位置是重叠的,因此肯定会相互的覆盖。

问题如何解决

指定O_APPEND即可解决。必须每个open都要指定,有一个不指定就会覆盖,就先过马路一样,都要准守交通规则才能安全,开车的和行人,只要有一个不准守都会出事。

为什么使用O_APPEND可以解决?

文件长度信息是大家共享的,当文件被写入数据后,文件长度就会被更新,都指定O_APPEND后,使用不同的文件描述符写数据时,都会使用文件长度更新自己的文件位移量,保证每次都是在文件的最末尾写数据,就不会出现相互覆盖的情况。

多个进程之间,共享操作相同文件

代码演示

shareOp_file1.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 8 #define FILE_NAME "./file.txt" 9 10 11 void print_error(char * str)12 {13 perror(str);14 exit(-1);15 }16 17 18 int main(void)19 {20 int fd1 = 0;21 22 fd1 = open(FILE_NAME, O_RDWR|O_TRUNC|O_APPEND);23 if(-1 == fd1) print_error("1 open fail");24 25 26 printf("fd1 = %d\n", fd1); 27 28 while(1)29 {30 write(fd1, "hello\n", 6);31 sleep(1);32 }33 34 35 36 return 0;37 }
View Code

shareOp_file2.c

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 8 #define FILE_NAME "./file.txt" 9 10 11 void print_error(char * str)12 {13 perror(str);14 exit(-1);15 }16 17 18 int main(void)19 {20 int fd1 = 0;21 22 fd1 = open(FILE_NAME, O_RDWR|O_TRUNC|O_APPEND);23 if(-1 == fd1) print_error("1 open fail");24 25 26 printf("fd1 = %d\n", fd1); 27 28 while(1)29 {30 write(fd1, "world\n", 6);31 sleep(1);32 }33 34 35 36 return 0;37 }
View Code

不同进程打开同一文件时,各自使用的文件描述符值可能相等,比如我们例子中的1和2进程,它们open后的描述符就相等。之所以相同,是因为不同的进程有自己独立的文件描述符池,都是0~1023的范围,各自分配自己的,有可能分派到相等值的文件描述符。

进程表 和 文件描述符表

覆盖的原因

和单个进程打开多个文件类似,这种情况也会覆盖写。其原因是因为因为各自有独立的文件位移量。

解决办法

同样的,指定O_APPEND标志,写操作时,使用文件长度去更新文件位移量,保证各自操作时,都在文件的尾部操作,就不会出现相互覆盖的情况。

父子进程共享操作文件

独立打开文件

这种情况即多个进程独立打开同一文件实现共享操作,只不过这里面进程之间是父子关系

代码演示

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 int main(void)10 {11 pid_t ret = 0;12 int fd = 0;13 14 ret = fork();15 if(ret > 0)16 {17 fd = open("./file.txt", O_RDWR|O_CREAT|O_APPEND, 0664);18 19 write(fd, "hello\n", 6);20 }21 else if(ret == 0)22 {23 fd = open("./file.txt", O_RDWR|O_CREAT|O_APPEND, 0664);24 25 write(fd, "world\n", 6);26 }27 28 return 0;29 }
View Code

文件表结构

独立打开同一文件时,父子进程各自的文件描述符,指向的是不同的文件表。因为拥有不同的文件表,所以他们拥有各自独立的文件读写位置,会出现相互覆盖情况,如果不想相互覆盖,需要加O_APPEND标志。

fork之前打开文件

代码演示

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 int main(void)10 {11 pid_t ret = 0;12 int fd = 0;13 14 fd = open("./file.txt", O_RDWR|O_CREAT, 0664);15 ret = fork();16 if(ret > 0)17 {18 write(fd, "hello\n", 6);19 printf("p, uid = %d, gid = %d\n", getuid(), getgid());20 }21 else if(ret == 0)22 {23 write(fd, "world\n", 6);24 printf("c, uid = %d, gid = %d\n", getuid(), getgid());25 }26 27 return 0;28 }
View Code

文件表结构

子进程会继承父进程已经打开的文件描述符,如果父进程的3描述符指向了某个文件,子进程所继承的文件描述符3也会指向这个文件。像这种继承的情况,父子进程这两个相同的“文件描述符”指向的是相同的“文件表”。由于共享的是相同的文件表,所以拥有共同的文件读写位置,不会出现覆盖的情况。

子进程的0 1 2这三个打开的文件描述符,其实也是从父进程那里继承过来的,并不是子进程自己去打开的,同样的父进程的0 1 2又是从它的父进程那里继承过来的,最根溯源的话,都是从最原始的进程哪里继承过来的,参考: ,最原始的进程是init进程。

init进程会去打开标准输入,标注输出、标准出错输出这三个文件,然后0 1 2分别指向打开的文件,之后所有进程的0 1 2,实际上都是从最开始的init进程那里继承而来的。

 

 

转载于:https://www.cnblogs.com/kelamoyujuzhen/p/9687450.html

你可能感兴趣的文章
Valid Parentheses
查看>>
【ES6】数值的扩展
查看>>
性能测试之稳定性测试
查看>>
ES6的 Iterator 遍历器
查看>>
2019届高二(下)半期考试题(文科)
查看>>
【REDO】删除REDO LOG重做日志组后需要手工删除对应的日志文件(转)
查看>>
nginx 301跳转到带www域名方法rewrite(转)
查看>>
AIX 配置vncserver
查看>>
windows下Python 3.x图形图像处理库PIL的安装
查看>>
【IL】IL生成exe的方法
查看>>
network
查看>>
SettingsNotePad++
查看>>
centos7安装cacti-1.0
查看>>
3个概念,入门 Vue 组件开发
查看>>
没有JS的前端:体积更小、速度更快!
查看>>
数据指标/表现度量系统(Performance Measurement System)综述
查看>>
GitHub宣布推出Electron 1.0和Devtron,并将提供无限制的私有代码库
查看>>
Angular2, NativeScript 和 React Native比较[翻译]
查看>>
论模式在领域驱动设计中的重要性
查看>>
京东AI研究院何晓冬:将先进的技术和模型落地到产业
查看>>