linux多进程原理,linux多进程间文件共享机制

一、原理

linux支持多进程间共享打开文件,即同一时刻允许多个进程同时打开同个文件,每个进程之间的读写操作互不影响。

为了实现这一个机制,linux内核使用了三种数据结构来表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。

1.1 内核数据结构

每个进程的进程表中有一个记录项,包含了当前进程所有打开的文件描述符,它包含了一个指向文件表项的指针和文件描述符标志。

内核中,为所有打开的文件维持一张表,它包含了以下内容:

当前文件打开的状态:以何种方式打开的该文件,只读、只写或是可读可写等。

当前文件的偏移量:当前文件指针所处的位置。

指向该文件节点表的指针:节点包含了当前文件的属性信息。

每个文件的信息被封装在一个v节点表项中,包含了当前文件的文件名、所有者以及inode等信息。

三者之间的状态关系为:

f0bcc7abfbc9a14b0e6d16f3626fab3d.png

1.2 多进程共享同一个文件

对于多个进程打开的同一个文件,其状态关系为:

1357ad36e5a5d814c937bc73380c714b.png

正因为每个文件描述符都有一个属于自己的文件表项,所以每个进程间的文件指针偏移相互独立,互相读写不干扰:

每次完成write后,文件表项的当前文件指针偏移量也会立马加上写入的字节数。

如果打开文件的时候加了O_APPEND参数,每次写入数据前会先把偏移量设置到文件末尾。

通过lseek函数只修改当前文件偏移量,不进行任何I/O操作。

有一个要注意的是,每次fork进程后,子进程会复制父进程的文件描述符,两者相互独立。

二、dup和dup2

dup和dup2都可以用来复制一个现有的文件描述符,其用法如下:

#include

int dup(int fd);

int dup2(int fd1, int fd2);

1

2

3

4

#include

intdup(intfd);

intdup2(intfd1,intfd2);

dup函数直接把复制后的文件描述符返回,返回的一定是当前文件描述符表中的最小数值。

对于dup2,可以通过fd2表示新描述符的值,如果fd2已经打开,系统会先关闭。如果fd1等于fd2,则直接返回不关闭。

复制过后的文件描述符共享一个文件表项,共享后的状态如下:

79225169c01f80bde8b240085bc112f9.png

我们可以通过一个程序来验证这一个结论:

#include

#include

#include

#include

#include

int main() {

char buff[6] = { 0 };

int fd_1, fd_2;

fd_1 = open("data.txt", O_RDONLY);

if (fd_1 == -1) {

perror("open file error");

return -1;

}

fd_2 = dup(fd_1);

if (fd_2 == -1) {

perror("dup error");

return -1;

}

if (read(fd_1, buff, 5) == -1) {

perror("read error at fd_1");

return -1;

}

printf("fd_1 read: %s\n", buff);

if (read(fd_2, buff, 5) == -1) {

perror("read error at fd_2");

}

printf("fd_2 read: %s\n", buff);

close(fd_1);

close(fd_2);

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

#include

#include

#include

#include

#include

intmain(){

charbuff[6]={0};

intfd_1,fd_2;

fd_1=open("data.txt",O_RDONLY);

if(fd_1==-1){

perror("open file error");

return-1;

}

fd_2=dup(fd_1);

if(fd_2==-1){

perror("dup error");

return-1;

}

if(read(fd_1,buff,5)==-1){

perror("read error at fd_1");

return-1;

}

printf("fd_1 read: %s\n",buff);

if(read(fd_2,buff,5)==-1){

perror("read error at fd_2");

}

printf("fd_2 read: %s\n",buff);

close(fd_1);

close(fd_2);

return0;

}

上面的代码中通过fd_1打开文件data.txt,fd_2复制fd_1,两个文件描述符文件从文件中读取5个字节数据并打印出来。

编译代码执行:

# 先写十个字节数据到文件

> echo "HelloWorld" > data.txt

> mkdir debug

# 编译

> gcc dup.c -o debug/dup

# 执行

> ./debug/dup

fd_1 read: Hello

fd_2 read: World

1

2

3

4

5

6

7

8

9

# 先写十个字节数据到文件

>echo"HelloWorld">data.txt

>mkdirdebug

# 编译

>gccdup.c-odebug/dup

# 执行

>./debug/dup

fd_1read:Hello

fd_2read:World

可以看到,fd_2读取的数据是从第5个字节开始,即从fd_1读完偏移处开始,两者确实共享了同一个文件表项。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值