1.回顾一下文件
我们之前对文件的理解是在语言层上,而语言层去理解文件是不可能的!!!
下面是一份c语言文件操作代码!!!
#include<stdio.h>
int main()
{
FILE* fd = fopen("log.txt", "w");
if(fd == NULL)
{
perror("fopen");
return 1;
}
fclose(fd);
return 0;
}
我们要进行文件操作,前提是我们的程序跑起来了。
文件打开和关闭是,是CPU在执行我们的代码。
w含义:
1.如果不存在,就在当前路径下,新建指定的文件。
2.默认打开文件的时候。就先把目标文件清空!--》所以可以用来新建文件,清空文件!
我们又使用输出重定向符号操作文件,我们发现文件被清空了,输出重定向一定是文件操作!!!
2.文件进一步理解
打开文件本质其实进程(task_struct)打开文件(struct xxxx)
文件没有被打开时,在哪里?磁盘存在
1.进程能打开很多文件吗?可以
2.系统中可不可以存在很多进程呢??
很多情况下,os内部,一定存在大量的被打开的文件。OS要不要把这些打开的文件进行管理呢?
重点来了,讲到管理,就要先描述,在组织!!!
那预言一波可知:每一个被打开的文件,在OS内部,一定要存在对应的描述文件属性的结构体,类似PCB。
文件 = 属性 + 内容。
7 int main()
8 {
9 FILE* fp = fopen("log.txt", "a");
10 if(fp == NULL)
11 {
12 perror("fopen");
13 return 1;
14 }
15 fprintf(fp, "hello Linux!, %d", 10);
16
17 fclose(fp);
18 return 0;
19 }
a含义:向文件中追加字符串,不会清空文件。
且追加重定向符号也可作此操作,可见重定向操作一定是文件操作!!!
c/c++/java/python访问文件的方式有些不一样!!!
3.理解文件
a.操作文件,本质:进程在操作文件。进程和文件的关系
b.文件->磁盘->外设->硬件->向文件中写入,本质是向硬件中写入->用户没有权利直接写入->OS是硬件的管理者->通过OS写入->OS必须给我们提供系统调用(OS不相信任何人)(访问文件我们也可以使用系统调用啊!)->fopen/fread/fwrite/fclose/scanf/cin/cout?->我们用的c/c++...都是对系统调用接口的封装!
为什么?怎么办?
认识一下系统调用并且使用。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
umask(0);
int fd = open("bite1.txt", O_WRONLY | O_CREAT, 0666);
if(fd < 0)
{
perror("open");
return 1;
}
close(fd);
return 0;
}
这是一个使用系统调用操作文件的程序,那么umask是可以设置 当前进程的掩码为0,使得我们在open第三个参数设置权限位时不会受到掩码的影响。
第二个参数是用的宏来代表是写还是读等操作,以位图的方式存储对应数据。
32个比特位。用比特位来进行标志位的传递。 ---- OS设计很多系统调用接口的方法。
open: 以写的方式打开,不存在就创建,存在就先清空!
open与fopen什么联系?
0:标准输入(键盘)
1:标志输出(显示器)
2:标志错误(显示器)
这些又有什么联系?
我们在进程中去打开多个文件时的open返回值从3开始依次增加是怎么回事?
文件描述符fd,fd的本质是什么?
那就说个结论吧:其实是内核的进程:文件映射关系的数组的下标!
我们已经理解什么是fd,0,1,2默认打开了?
0:标准输入(键盘)
1:标志输出(显示器)
2:标志错误(显示器)
硬件啊->理解Linux一切皆文件
struct file中有函数指针,同一个指针会指向不同的方法,这不就是我们C++学习到的面向对象中的多态吗?
那把c语言struct看做类。
如果我们用c实现类?
所以以上内容就都能贯通了,本质是c语言中的文件操作函数底层都是对系统调用接口的封装,封装了系统调用的细节。
所以就理解了Linux一切皆文件!
4.c语言为什么要这么做?
可以使用系统调用,也可以使用语言提供的文件方法
系统不同,系统调用接口可能不一样
代码就不具备平台性
所以所有的语言都想具有跨平台性!!
所有的语言要对不同的平台的系统调用进行封装
不同的语言封装的时候,文件接口就有差别了!