初级文件IO——文件共享操作 初级文件IO——概述、API

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

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

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

代码演示

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 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 <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 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 <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 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标志,写操作时,使用文件长度去更新文件位移量,保证各自操作时,都在文件的尾部操作,就不会出现相互覆盖的情况。

dup、dup2复制文件描述符

API参考:初级文件IO——概述、API

代码演示

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 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 int main(void)
18 {
19     int fd1 = 0;
20     int fd2 = 0;
21     
22     fd1 = open(FILE_NAME, O_RDWR|O_TRUNC);
23     if(-1 == fd1) print_error("1 open fail");
24 
25     //fd2 = dup(fd1);
26     fd2 = dup2(fd1, 4);
27 
28     printf("fd1 = %d, fd2 = %d\n", fd1, fd2);
29 
30     while(1)
31     {
32         write(fd1, "hello\n", 6);
33         sleep(1);
34         write(fd2, "world\n", 6);
35     }
36         
37     return 0;
38 }
View Code

没有出现相互覆盖

即使不指定O_APPEND也不会出现相互覆盖现象。看下面文件描述符表

使用dup、dup2复制方式实现文件共享时,不管复制出多少个文件描述符,它们永远只有一个文件表,所以使用所有描述符去操作文件时,最后使用的都是通过同一个文件位移量,不管谁操作后文件位移量都会被更新,因此不会出现覆盖。

利用dup、dup2实现文件重定位

什么是重定位

某文件描述符原来指向了A文件,输出数据是输出到A文件,但是重定位后,文件描述符指向了B文件,输出时数据输出到了B文件,这就是重定位。所谓重定位,说白了就是,文件描述符所指向的文件该变了,使得数据输出的目标文件也随之变。

回顾printf与write的关系

printf输出时,原本通过1,将数据输出到标准输出文件(显示器)的,但是现在,我想让printf输出到file.txt文件,而不是输出到屏幕,应该怎么办?

最简单的办法是就是,把printf函数调用的write函数里面的1,改成指向file.txt文件的新描述符即可,但是不幸的是write中的1写死了,1这个数字改不了,怎么办?

1这个数改不了,但是可以对1进行重定位,让1不再指向标准输出文件,而是指向file.txt,printf的数据,就输出到了

file.txt文件中。

实现步骤

①open file.txt文件,返回一个文件描述符,比如3

3 ——> file.txt

②close(1),不要再让1指向标准输出文件(/dev/stdout)

③ 使用dup、dup2把3复制到1上,让1也指向file.txt文件

1这个文件描述符就被重定位了,凡是通过1输出的数据,都被写到了file.txt中,printf底层调用的是write(1, ...),用的也是1,printf的数据就被输出到了file.txt中。相当于printf函数的输出目的地,被重定位为了新的文件,这就是重定位。

代码演示

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <stdlib.h>
 6 #include <unistd.h>
 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);
22     if(-1 == fd1) print_error("1 open fail");
23     //close(1);
24     //dup(fd1);
25     
26     dup2(fd1, 1);
27     
28     //printf("fd2 = %d\n", fd2);
29     printf("hello world\n");    
30 
31     return 0;
32 }
View Code

猜你喜欢

转载自www.cnblogs.com/kelamoyujuzhen/p/9687450.html
今日推荐