基础IO[一]

文件=文件内容+属性

文件在硬盘上放着,我们的流程->写代码->编译->运行->访问文件。那么本质上是谁在访问?

是进程在访问。进程访问文件是需要通过接口来访问。

文件在磁盘上放着,要向硬件写入文件,谁有权限呢?必须让操作系统提供接口,用户和操作之间提供一个软件层,来帮助用户访问文件。操作系统提供文件类的系统调用接口,语言上,对接口进行了封装,让接口进行更好的使用。而且系统级别的封装不具有跨平台的条件。

一切皆文件

对于文件

一般的普通文件:read,write

显示器:printf ,cout -一种输出

键盘:cin,scanf——一种输入

文件所具有的属性输入和输出,对于一般文件而言自不必说,但是对于硬件呢?系统方面提供了接口使得可以输入和输出,而对于Linux系统而言一切皆文件,是只要有接口提供了可以输入的输出,那么这个文件无论是常规意义上的一般文件还是硬件设备,只要它可以输入和输出,他就是文件按,文件最重要的特征就是输入和输出,而只要提供输入和输出的接口的,我们都可以称呼他为文件。这里的一切皆文件也是软件层的概念。

当一个进程运行起来的时候,每个进程都会记录自己当前所处的工作路径 /proc cwd就是当前工作路径,这个路径就是当前路径。

文件写入的时候只需要保存有效数字,不需要\0作为结尾

如何使用一个值代表多种状态呢?可以通过位运算,一个字节8个比特位,每一个比特位都可以代表不同的状态。


  1 #include
  2 #include
  3 #include
  4 
  5 #define ONE 0x1
  6 #define TWO 0x2
  7 #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 }
~

运行结果

基础IO[一]_第1张图片

这是操作系统传递标志位的一种方式。 

简单的系统调用

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  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); //第一个代表路径,第二个代表标志位,只读或者只写

但是这样的我们会发现创建的文件权限好像不太对啊

基础IO[一]_第2张图片

那是因为我们在创建文件的时候需要加入,权限的选项。

 int fd =open("log.txt",O_WRONLY | O_CREAT,0666); //第一个代表路径,第二个代表标志位,只读或者只写                  

但是这个时候权限好像少了点什么

基础IO[一]_第3张图片这是因为在创建的时候umask会进行过滤,但是我们不想让umask过滤怎么办呢?

系统中有一个接口可以设置umask

基础IO[一]_第4张图片

对umask进行设置之后就正常了

基础IO[一]_第5张图片 基础IO[一]_第6张图片

打开之后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对象。充当一个被打开的对象,包含一个被打开文件的几乎所有内容,权限属性缓冲区等。如果有很多再用双链表链接起来。

基础IO[一]_第7张图片

fd就代表当前进程的struct数组下标对应的文件。fd再内核中本质上是一个下标。

文件描述符是有上限的。

你可能感兴趣的:(Linux,服务器,linux)