目录

​编辑 系统接口进行文件访问

open 接口介绍

文件描述符fd

重定向

缓冲区

1、缓冲区是什么?

2、为什么要有缓冲区?

3、怎么办?

我们先来复习一下,c语言对文件的操作:

C默认会打开三个输入输出流,分别是stdin, stdout, stderr

1 #include

2

3 int main()

4 {

5 FILE *fp=fopen("log.txt","w");

6 if(fp==NULL)

7 {

8 perror("error!");

9 return 1;

10 }

11 fprintf(fp,"hello,%d,%s\n",10,"sxh");

12 fclose(fp);

13 return 0;

14 }

系统接口进行文件访问

操作文件,除了上述C接口(当然,C++也有接口,其他语言也有),我们还可以采用系统接口来进行文件访问;

#include

#include

#include

#include

#include

#include

int main()

{

umask(0);

int fd =open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);

if(fd<0)

{

perror("open");

return 1;

}

//const char *message ="hello Linux!\n";

const char * message ="aaaa\n";

write(fd,message,strlen(message));

close(fd);

}

open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);:以写方式打开,不存在就创建,存在就先清空!相当于c语言中的 “w” 方式;

open 接口介绍

open man 2 open

#includ e #include #include

int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode) int creat(const char *pathname, mode_t mode);

pathname:要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成; 常见的参数有:

O_RDONLY: 只读打开

O_WRONLY: 只写打开 O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限 O_APPEND: 追加写

mode: mode 只有 当 在 flags 中使用 O_CREAT 时才有效 , 否则被忽略.

返回值: 成功:新打开的文件描述符 失败:-1

文件描述符fd

我们通过系统调用I/O打开一个文件的返回值,就是文件描述符:

int fd = open("log.txt",O_WRONLY | O_CREAT |O_TRUNC,0666);

这里fd就是log.txt的文件描述符;

如果我们同时打开三个文件,并把这三个文件的文件描述符打印出来,会发现:

文件描述符是从3开始的,那0、1、2呢?

Linux进程默认情况下会有3个缺省打开的文件描述符:分别是标准输入0, 标准输出1, 标准错误2. 0,1,2对应的物理设备一般是:键盘,显示器,显示器

根据上述的图,我们可以知道:

open干什么?

1、创建file

2、开辟文件缓冲区的空间,加载文件数据(延后)

3、查看进程的文件描述符表

4、file地址,填入对应的表下标中

5、返回下标

重定向

看一下下面的代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 const char *filename="log.txt";

9

10 int main()

11 {

12 //close(0);

13 close(1);

14 //close(2);

15 int fd =open(filename,O_CREAT | O_WRONLY | O_TRUNC,0666);

16 if(fd<0)

17 {

18 perror("open");

19 return 1;

20 }

21 printf("printf,fd:%d\n",fd);

22 fprintf(stdout,"fprintf,fd:%d\n",fd);

23

24 fflush(stdout);

25

26

27 close(fd);

28 return 0;

29

30 }

先看现象:

1、如果我们关闭的是0:打印出来的log.txt的文件描述符是0;关闭的是2,则打印出来的文件描述符是2;关闭的是1,则不会显示出来;因为文件描述符1表示的是显示器,而我们把显示器关掉了自然打印不出来;

2、我们会在log.txt中打印出printf和fprintf的内容:

现象解释:

文件描述符规则:查看自己的文件描述表,分配最小的没有使用的文件描述符;

由于我们把显示器给关掉了,那么文件描述符1就是最小的没有使用的,这样log.txt就会被分配1为文件描述符;这其实就是一个重定向操作;

看下面的图:

一开始fd_array[1]指向的是显示器,由于close(1),加上open log.txt这样fd_array[1]指向的就是log.txt;

因为重定向的本质是在内核中改变文件描述符特点下标的内容,与上层无关;

fprintf()/printf() --->stdout --->struct FILE --->stdout ---->_fileno ==1;

所以fprintf()/printf() 看的就是_fileno ==1;由于重定向后log.txt的fd为1 ,自然fprintf()/printf()的内容打印到log.txt中;

如果我们一直用这种手动重定向的方式,比较麻烦;可以用系统调用:dup2()

看一下代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 const char *filename="log.txt";

9

10 int main()

11 {

12 int fd = open(filename,O_CREAT | O_WRONLY | O_TRUNC,0666);

13 //dup2(fd,1);

14

15 printf("hello world,fd:%d\n",fd);

16 fprintf(stdout,"hello world\n");

17 fflush(stdout);

18 close(fd);

19 return 0;

20 }

上述的代码运行结果:会直接打印到显示器上;

如果把dup2(fd,1);复原:显示器上不会显示,而是在log.txt上显示

其实本质就是将fd覆盖1 指向下标的内容;

缓冲区

1、缓冲区是什么?

缓冲区就是一段内存空间

2、为什么要有缓冲区?

给上层提供高效的IO体验,间接提高整体效率

3、怎么办?

a、刷新策略 1、立即刷新 fflush(stdout)(c语言的刷新)、fsync(fd)(系统调用的刷新) 2、行刷新 (显示器) 3、全缓冲 (缓冲区写满,才刷新,普通文件) b、特殊情况 进程退出,系统会自动刷新 强制刷新