文件=文件内容+属性
文件在硬盘上放着,我们的流程->写代码->编译->运行->访问文件。那么本质上是谁在访问?
是进程在访问。进程访问文件是需要通过接口来访问。
文件在磁盘上放着,要向硬件写入文件,谁有权限呢?必须让操作系统提供接口,用户和操作之间提供一个软件层,来帮助用户访问文件。操作系统提供文件类的系统调用接口,语言上,对接口进行了封装,让接口进行更好的使用。而且系统级别的封装不具有跨平台的条件。
一切皆文件
对于文件
一般的普通文件:read,write
显示器:printf ,cout -一种输出
键盘:cin,scanf——一种输入
文件所具有的属性输入和输出,对于一般文件而言自不必说,但是对于硬件呢?系统方面提供了接口使得可以输入和输出,而对于Linux系统而言一切皆文件,是只要有接口提供了可以输入的输出,那么这个文件无论是常规意义上的一般文件还是硬件设备,只要它可以输入和输出,他就是文件按,文件最重要的特征就是输入和输出,而只要提供输入和输出的接口的,我们都可以称呼他为文件。这里的一切皆文件也是软件层的概念。
当一个进程运行起来的时候,每个进程都会记录自己当前所处的工作路径 /proc cwd就是当前工作路径,这个路径就是当前路径。
文件写入的时候只需要保存有效数字,不需要\0作为结尾
如何使用一个值代表多种状态呢?可以通过位运算,一个字节8个比特位,每一个比特位都可以代表不同的状态。
1 #include<stdio.h>2 #include<string.h>3 #include<unistd.h>4 5 #define ONE 0x16 #define TWO 0x27 #define THREE 0x4 8 void show (int flag)9 {10 if(ONE&flag)11 printf("hello one\n");12 if(TWO&flag)13 printf("hello two\n");14 if(THREE&flag)15 printf("hello three\n");16 // printf("hello four\n"); 17 }18 19 int main()20 {21 show(ONE);22 printf("-------------------------------------\n");23 show(TWO);//设置一个标志位哦24 printf("-------------------------------------\n");25 show(ONE|TWO);//设置1和2两个标志位,位运算或之后的值代表着这个值无论是ONE还是TWO与运算都能得到原来的值26 printf("-------------------------------------\n");27 show(ONE | TWO | THREE);28 return 0;29 }
~
运行结果
这是操作系统传递标志位的一种方式。
简单的系统调用
1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 #include<string.h>5 #include<fcntl.h>6 #include<stdlib.h>7 8 int main()9 {10 int fd =open("log.txt",O_WRONLY); //第一个代表路径,第二个代表标志位,只读或者只写11 if(fd<0)12 {13 perror("open fail\n");14 exit(1);15 16 }17 else{18 printf("success 退出码:%d\n",fd); 19 }20 21 return 0;22 }
这是没有log.txt没有这个文件那么我们的运行结果是什么?
这和C语言的不一样啊,怎么回事呢?这是因为C语言在语言层帮我们封装了,导致我们使用起来很方便,但是系统原生的很简洁。我们需要加其他的选项才可以实现。
我们需要使用之前的位运算来加上其他的选项达成,没有文件就创建的效果
int fd =open("log.txt",O_WRONLY | O_CREAT); //第一个代表路径,第二个代表标志位,只读或者只写
但是这样的我们会发现创建的文件权限好像不太对啊
那是因为我们在创建文件的时候需要加入,权限的选项。
int fd =open("log.txt",O_WRONLY | O_CREAT,0666); //第一个代表路径,第二个代表标志位,只读或者只写
但是这个时候权限好像少了点什么
这是因为在创建的时候umask会进行过滤,但是我们不想让umask过滤怎么办呢?
系统中有一个接口可以设置umask
对umask进行设置之后就正常了
打开之后write和read都同理
而且为什么退出码是3? 0 1 2都去哪里了?
分析接口细节
我们在打开文件时有一个FILE* 那么 FILE是什么呢?答案是结构体,由C标准库提供的结构体,内部有多个成员。那么站在系统层,系统认fd还是FILE,那么可以得出结论,FILE结构体里面绝对封装了fd。那么怎么证明。
printf("stdin:%d\n",stdin->_fileno);
使用这句代码我们可以查看他的打印结果,可以查看到内部的fd
这里我们可以看出内部的fd为1。其他的结果以此类推。
那么什么是fd呢?进程要访问文件,必须先打开文件,文件要被访问,必须先加载到内存之中才能之间被访问,那么如果打开大量的文件,也需要管理起来,先描述再组织。就需要为每一个打开的文件创建struct_file对象。充当一个被打开的对象,包含一个被打开文件的几乎所有内容,权限属性缓冲区等。如果有很多再用双链表链接起来。
fd就代表当前进程的struct数组下标对应的文件。fd再内核中本质上是一个下标。
文件描述符是有上限的。