您的位置:首页 > 运维架构 > Linux

文件进程linux系统编程之文件与I/O(五):打开文件的内核结构file和重定向

2013-05-14 20:51 363 查看
最近研究文件进程,稍微总结一下,以后继续补充:

一、打开文件内核数据结构

1、一个进程打开两个文件



文件状态标记:读、写、追加、同步、非阻塞等

2、一个进程两次打开同一文件



3、两个进程打开同一文件



示例程序:

C++ Code

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

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

/*************************************************************************
> File Name: file_share.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

#define ERR_EXIT(m) \

do { \

perror(m); \

exit(EXIT_FAILURE); \

}
while(
0)

int main(
int argc,
char *argv[])

{

int fd1, fd2;

char buf1[
1024] = {
0};

char buf2[
1024] = {
0};

/* 进程控制块PCB
* struct task {
* ...
* struct files_struct *files;
* }
* 同一个进程两次打开同一个文件,一个进程具有的一个文件描述符表其中一个fd索引对应的指针指向一个
* 文件表(包括文件状态(读写追加同步非阻塞等),当前文件偏移量,
* 文件引用次数(当有两个fd指向同个文件表时引用计数为2,见dup,也可用于重定向),
* 文件操纵指针, V节点指针等)不同享,
* V节点表(包括V节点信息(struct stat), i节点信息等)同享
*/

/* 两个进程打开同一个文件的情况与上类同*/

fd1 = open(
"test.txt", O_RDONLY);

if (fd1 == -
1)

ERR_EXIT(
"open error");

read(fd1, buf1,
5);

printf(
"buf1=%s\n", buf1);

fd2 = open(
"test.txt", O_RDWR);

if (fd2 == -
1)

ERR_EXIT(
"open error");

read(fd2, buf2,
5);

printf(
"buf2=%s\n", buf2);

write(fd2,
"AAAAA",
5);

memset(buf1,
0,
sizeof(buf1));

read(fd1, buf1,
5);

printf(
"buf1=%s\n", buf1);

close(fd1);

close(fd2);

return
0;

}

每日一道理

美丽是平凡的,平凡得让你感觉不到她的存在;美丽是平淡的,平淡得只剩下温馨的回忆;美丽又是平静的,平静得只有你费尽心思才能激起她的涟漪。

假设test.txt文件的内容是 ABCDEhello

测试如下:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_share
buf1=ABCDE
buf2=ABCDE
buf1=AAAAA

test.txt文件内容变成 ABCDEAAAAA

分析:由上图分析可知,一个进程两次打开同一文件,文件表是不同享的,即各有自己的文件偏移量和打开文件标记,所以两次read不同的fd都是从头开始读取,但V节点表是同享的,在fd2写入(同个文件表的read和write是同享偏移的)更改了inode指向的硬盘数据块,再次read fd1失掉的也是更改后的值。

二、I/O重定向





当我们执行了dup(3)之后,系统选择一个闲暇的文件描述符即4,这样就有两个文件描述符指向同个文件表,所以引用计数为2。利用dup等函数可以停止重定向的步调是先close输入输出文件描述符,然后执行dup(fd), 这样输入输出文件描述符也指向fd指向的文件,这样就实现了重定向。此外dup2, fcntl 函数也可以实现,其实不使用这些函数,而直接close(0/1/2)完再open也可以实现。

示例程序如下:

C++ Code

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

39

40

41

/*************************************************************************
> File Name: file_dup.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

#define ERR_EXIT(m) \

do { \

perror(m); \

exit(EXIT_FAILURE); \

}
while(
0)

/* dup dup2 fcntl */

int main(
int argc,
char *argv[])

{

int fd;

fd = open(
"test2.txt", O_WRONLY);

if (fd == -
1)

ERR_EXIT(
"open error");

/*
close(1);
dup(fd);
*/

// dup2(fd, 1);

close(
1);

if (fcntl(fd, F_DUPFD,
0) <
0)
//从0开始搜索可用的fd
ERR_EXIT(
"fcntl error");

printf(
"hello\n");
// 输出重定向到test2.txt

return
0;

}

文章结束给大家分享下程序员的一些笑话语录:

PC软件体积大,是因为一个PC软件功能往往较多,能够满足你一个方面的需求,而一个iphone软件往往没几行代码,干一件很小的事情,自然需要的软件就多。就像吃西瓜和吃瓜子的来比数目,单位不同啊。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐