[基础IO]文件描述符{C库函数\系统接口\初识fd}

1.基础知识

1.1对文件的认识

  1. 文件 = 内容 + 属性(也是数据)
  2. 文件的所有操作: a. 对内容 b. 对属性 对内容操作可能引起属性操作 如: 增加内容 文件变大 标识文件大小的属性变化
  3. 文件在磁盘上存放 磁盘是硬件 用户访问文件: 代码–编译—可执行程序—运行—进程通过OS提供的系统调用接口访问文件
  4. 向磁盘(硬件)写入内容 只有OS有权利 普通用户要想写入 只能使用OS提供的文件类系统调用接口
    在这里插入图片描述

1.2对系统调用接口的认识

  1. 要想用系统调用接口 首先得了解怎么用 及使用者需要对系统有一定的认识与了解 而系统调用接口使用较难或者说系统太难理解 学习计算机的同学都是从易到难学习的 C/C++/java等等 或者说先是学习较简单的语言 然后再学例如计算机组成原理/编译原理/操作系统等较难课程 而从计算机发展历史看 实际上是先有的计算机组成/OS 而后才有的语言 但是我们不得不从语言开始学 因为一开始就学OS根本就学不懂 这就好比我们先学语言 再学数据结构一样 我们首先需要具备一定的语言知识 才能更好的学习底层 其次 底层配合语言让我们对计算机的理解更加深刻
  2. 为了让初学者去使用接口 或者说让这些系统调用接口能够被更好的使用 在接口上做了封装 形成各类语言的库函数 学习这些语言的人就能调用库函数来间接实现对接口的调用
  3. 不同的语言有不同的风格和体系 这也造成了不同语言的文件函数使用上具有很大差异 但是底层都是封装的系统接口
  4. 而你使用的OS基本上只有一个 基于此OS的系统调用接口 只有一套 如果我们学习了本质即底层 那么学习其他语言的接口将会是如鱼得水
  5. 上面为我们讲到 语言对系统调用接口封装形成库函数一大目的是更好更方便更简单的使用系统调用接口 那么还有第二大目的就是实现语言的跨平台性 如果语言不提供对文件的系统调用接口的封装 那么用该语言写出的代码一旦涉及到访问文件的操作都必须/只能调用系统调用接口 而在linux下写的语言就必须调用Linux的接口 这份语言 到windows下 由于Windows没有linux的接口或者说二者根本就无法用统一接口调用对应操作 使得这份语言不具备跨平台性

语言是如何实现跨平台的?

把基于所有平台(windows/Linux/MacOS)的代码都实现一遍条件编译 动态裁剪 在什么机器上跑 就用对应的封装

对显示器的认识

  1. 显示器是硬件 pintf/cout向显示器打印 本质上也是向硬件写入
  2. 磁盘我们无法向显示器一样直观看到 所以向显示器打印内容时 我们不觉得奇怪 因为一眼就能看到
  3. 向显示器打印和磁盘上文件的写入本质没有区别

1.3如何理解LInux下一切皆文件?

在Linux中,一切皆文件的原则是指Linux将所有的资源都视为文件或文件类型的一种。这包括硬件设备、目录、文件、进程、套接字等等。在Linux中,每个文件都有一个唯一的文件描述符,它是一个非负整数,用于标识打开的文件。通过文件描述符,我们可以对文件进行读写等操作。这种一切皆文件的设计理念使得Linux系统的操作变得非常简单和统一,因为所有的资源都可以通过相同的方式进行访问和操作。同时,这种设计理念也为Linux系统提供了很好的可扩展性和灵活性,因为新的设备和资源可以很容易地被添加到系统中,并且可以通过相同的方式进行管理和访问。

举个例子,如果你想要查看CPU的温度,你可以在Linux中打开一个文件,该文件位于/sys/class/thermal/thermal_zone0/temp,然后读取该文件的内容,就可以得到CPU的温度信息。这个文件就是一个虚拟文件,它代表了CPU的温度传感器,通过读取该文件的内容,我们就可以获取到CPU的温度信息。

另外,Linux中的文件类型也非常丰富,包括普通文件、目录文件、字符设备文件、块设备文件、套接字文件等等。每种文件类型都有自己的特点和用途,例如普通文件用于存储文本、二进制数据等,目录文件用于存储其他文件和目录等。理解Linux中的文件类型对于正确地使用和管理Linux系统非常重要。

如何理解文件?

  1. 最初我们认识到的文件是从语言级别认识的 例如C语言调用fopen/fread/fwrite等函数可以对文件进行打开关闭读写操作
  2. 后来我么认识并了解到 显示器和键盘也具有文件的一些属性如 读和写 printf/cout向显示器打印内容 实际上就是一种write scanf/cin从键盘获取数据 实际上就是一种read 至于为什么从键盘输入的内容能显示到显示器上 这实际上是一种回显 这些调用库函数实现对文件的读写操作 是站在程序的角度 而程序要想能够执行这些操作 首先他得运行成为进程 即代码和数据加载到内存 即以上这些过程 是站在内存的角度 通过进程来完成的
  3. 从文件中读数据到文件中的流程: 进程调用fopen/fread(Input)函数从A文件中读入数据到进程的内部(内存) 然后调用fwrite(Outpute)函数写到B文件中
  4. 由此我们得出文件的概念: 站在系统的角度 能够被input读取或者能够被output写出的设备 就叫做文件
  5. 之前认识的文件是文件的子集,是狭义上的文件即磁盘上的文件
  6. 广义上的文件如显示器,键盘,网卡,声卡,显卡,磁盘,几乎所有的外设,都可以称之为文件

2.C语言的库函数

2.1FILE *fopen(const char *path, const char *mode);

在这里插入图片描述

mode的不同作用和目的

在这里插入图片描述
r: 为了读打开一个文件 文件流定位在文件首 原文件不存在则报错
w: 为了写打开一个文件 清空文件原有内容 文件不存在创建一个新文件 文件流定位在文件首
a: 为了追加打开一个文件 文件不存在创建一个新文件 文件流定位在文件尾
(r+ w+ a+ : 为了读和写打开文件 其他对应一致)

2.2对fopen()的mode的w/a的深层认识

w/a 打开不存在的文件时 会创建一个新文件 这个文件创建在哪里?

  1. 当前路径
  2. 准确一点是源代码对应的可执行程序所在的路径
  3. 精确一点是Linux下源代码对应的可执行程序运行变为进程所处的工作路径 (Windows-VS下的源代码和可执行程序不在同一路径 有所区别)
  4. fopen()会将不存在文件名建立在 “当前路径” 下 以此作为新文件的路径

谁创建的?

源代码对应的可执行程序运行起来成为进程后进程调用系统接口创建的 ==> OS创建的!

ls /proc/pid -l.会显示什么?

  1. cwd: current work directory 当前进程所执行的程序的所在目录
  2. exe: 当前进程所执行的可执行程序路径+文件名
    即 当一个进程运行时 会记录自己当前所处的工作路径 可执行程序的路径变化 对应的进程的工作路径也会变化
    继续回答上面的问题 当前路径指的是什么?. 一个进程运行时 当前所处的工作路径

2.3fclose()

在这里插入图片描述

2.4size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

在这里插入图片描述

回顾之前的字符串函数

在这里插入图片描述

2.5put()系列 – fputs()

在这里插入图片描述
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);

2.6get()系列 – fgets()

在这里插入图片描述 #include <stdio.h>
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c, FILE *stream);

2.7C语言文件库函数

1.用C语言将字符串写到文件里 计算字符串长度时strlen()函数用+1吗?

  1. 在C语言里字符串末尾有一个标识字符串结尾的标识符叫\0 它不属于字符串的内容 \0是C语言自己的规定
  2. 用C语言将字符串写到文件后 文件上的字符串与C语言再无瓜葛 文件要保存的是数据 不用也压根没必要遵守某种语言的规定 所以答案是不用+1
  3. 如果+1 文件内容会出现某一处乱码 因为文件无法对\0做有效解读

那文件里的字符串没有\0读的时候怎么分辨?\n怎么分辨?

读是用语言读的 语言级别上读的时候识别到后加上就行了 这就是系统与语言的区别

命令行下模拟w操作

echo hello txt > test.txt//向文件写内容.
> test.txt//输出重定向: 先打开文件 清空内容 又什么都不写 模拟完成.
实际上 echo命令 底层就是C语言调用fopen函数执行w操作完成的

按行读取char *fgets(char *s, int size, FILE *stream);

会自动在读到的字符串尾部+\0

C语言程序执行后三个标准输入输出流

FILE* : 把硬件看成了文件
extern FILE *stdin; --键盘
extern FILE *stdout; --显示器
extern FILE *stderr; --显示器

在这里插入图片描述

2.代码理解

int main(int argc, char *argv[
  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿猿收手吧!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值