Linux---基础IO详解

一、理解文件

1、1-1、狭义理解

在侠义上,文件就是存储在磁盘等介质上的数据集合,比如.txt、.c、.jpg。等

特点是:有文件名、有大小、有内容、是我们最直观接触到的文件形式。

2、1-2、广义理解:

Linux的核心思想是:Linux下一切皆文件,在Linux系统中,几乎所有的资源都被抽象成文件。

包括:普通文件、目录、设备(键盘、显示器、磁盘、网卡)、管道、套接字(socket)等

好处:

统一了操作接口,对设备的读写就像对普通文件的读写一样。

文件=文件的内容+文件的属性(元数据)

1-3、文件操作的归类认知

1、打开(open):建立进程与文件的链接,获取操作句柄。

2、读写(read/weite):从文件中读取数据,或向文件写入数据。

3、定位(seek):移动文件内部的读写位置指针。

4、关闭(close):断开进程与文件的连接,释放资源。

1-4、系统角度

从操作系统视角看,文件是一个被管理的对象,有对应的元数据(如:权限、大小、创建时间)

进程通过文件描述符(File Descriptor)来引用和操作这些文件对象。

Fopen

访问为文件之前,必须先打开文件,用fopen,用完再用close,动态的打开,文件是一个动态被打开的过程(程序跑起来之后,临时做的fopen就是典型的动态打开),不是编译时打开,而是运行时才打开。

打开文件就是进程在打开文件,因为是动态打开的,程序跑起来,就是进程;所以是进程打开文件的,研究文件和程序的关系,本质是研究进程和文件的关系。

路径

访问任何文件,必须要有路径要么用户自己提供要么用户使用进程的cwd

二、回顾c文件接口

2-1 、输出信息到显示器的方法

1、printf();格式化输出到标准输出(stdout)

2、puts():输出字符串并自动换行

3、putchar():输出单个字符

4、fprintf(stdout,...):等价于printf(),显式指定输出到stdout

5、write(1,...):使用系统调用直接向文件描述符(stdout)写入。

2-2、stdin 、 stdout、 stderr

1、标准输入(stdin):文件描述符为0,默认是键盘、用于读取数据

2、标准输出(stdout):文件描述符是1,默认是显示器,用于输出正常信息

3、标准错误(stderr):文件描述符为2,默认是显示器,用于输出错误信息

在c语言中,他们是三个预定义的FILE* 指针:stdin、stdout、stderr

重定向的本质就是改变着三个流的指向。例如:command> output.txt就是将stdout重定向到文件。

|----|-----|--------|-------|------|------------|
| 模式 | 含义 | 文件不存在时 | 文件存在时 | 初始位置 | 读写限制 |
| r | 只读 | 报错 | 打开 | 文件开头 | 只能读 |
| r+ | 读写 | 报错 | 打开 | 文件开头 | 可读可写 |
| w | 只写 | 创建新文件 | 清空内容 | 文件开头 | 只能写 |
| w+ | 读写 | 创建新文件 | 清空内容 | 文件开头 | 可读可写 |
| a | 追加 | 创建新文件 | 打开 | 文件末尾 | 只能写且只能追加 |
| a+ | 读追加 | 创建新文件 | 打开 | 文件末尾 | 读从开头,写总是追加 |

问题1:打开文件,就是把文件加载到内存?

不是。fopen只是"建立连接,登记信息",文件内存还在硬盘里,根本没进内存。 打开文件=办个手续,不是把东西搬进来。只有调用读/写函数时,才加载。

文件的分类

Linux存在大量文件,分为打开的和没有被打开的,文件从位置上:1、内存级被打开的文件和没有被打开的。

文件从位置上,1、内存级被打开的文件 2、磁盘文件

Linux中,可以存在很多被打开的文件!

os如何管理这些文件呢?

三、Linux进行文件操作

1、打开文件open

open和它的参数介绍

运行结果:由于打开的这个文件不存在,所以要新建文件,但是新建文件需要设置文件权限,用第二个open。

所以必须对源文件进行修改:

结果是:

但是这个log.txt的权限是乱码,所以必须给它设置权限,此时就需要open的第三个参数

如下图:

此时他的权限就是正常的,如下:

但是这里的权限为什么是664呢?

那些因为在Linux系统里,里面会有umask权限掩码,它是002(八进制)--->000 000 010(二进制),权限666减去umask掩码002就是664.

此时可以改写系统的Umask掩码 如下:

再来看运行结果:这下权限都是可读可写权限了

umask

那么我们自己设置了umask掩码,系统里面也有umask掩码

2、关闭文件close

close使用方法

3、向文件描述符写write

open...库函数封装系统调用=内核不让你进,给你一层"安全外套"

O_TRUNC

你这里的 O_TRUNC 是 Linux 系统调用 open() 的一个标志位,,是 O_TRUNC(Truncate 的缩写)。

它的作用是:

  • 如果要打开的文件已经存在,并且是以只写或读写方式打开的,那么 O_TRUNC 会把文件的原有内容全部清空(截断为 0 字节),然后再写入新内容。

  • 如果文件不存在,这个标志位就没有效果。

简单来说, O_TRUNC 就是"清空重写"的意思,确保写入的内容是全新的,而不是追加到旧内容后面。

open() 常用标志位(如 O_RDONLY , O_WRONLY , O_CREAT , O_APPEND 等)

于是呢,我们就成功的将数据写进去了

此时,log.txt的内容是;

我们修改写入文件的内容:

在编译之前log.txt是有老内容的。如下图

在让这个文件运行。结果会从上次结果的开始进行覆盖式的。

修改:

之后重新编译运行,结果是:

O_APPEND

O_APPEND = 追加模式

  • 写文件时,永远从文件末尾写

  • 不会覆盖原来的内容,只在后面加

我们直接看效果:这就是追加后的结果

问题:这里的fd为什么是3呢?

答:在 Linux 中,每个进程启动时,系统会自动打开 3 个标准文件描述符:

  • 0 :标准输入(stdin)

  • 1 :标准输出(stdout)

  • 2 :标准错误(stderr)

当程序调用 open() 打开新文件时,内核会分配当前最小的未被使用的整数作为文件描述符。因为 0、1、2 已被占用,所以第一个新打开的文件,其文件描述符就是 3。

你看到的 fd: 3 ,就是程序中新打开文件的文件描述符。

库函数封装了系统调用

write(1,msg,strlen(msg)),1代表标准输出, msg指的是输出内容的指向。

运行结果:

问题:文件描述符的本质是什么?

答:数组下标

为什么要c封装,理解一下C的IO函数。

答**:你的程序
↑↓ (用 fopen / fread / fwrite / printf)
struct FILE (封装层:缓冲区、状态、方便操作)
↑↓ (真正干活:open / read / write)
操作系统内核(文件描述符 0 1 2 3...)**

C 语言 IO 总结

  1. 系统调用:open / read / write
  • 用 数字 fd(0、1、2、3...)

  • 直接跟操作系统打交道

  • 无缓冲、麻烦、效率低、只能读写字节

  1. C 标准库:FILE / fopen / printf / fread*
  • 是对上面系统调用的 封装

  • 用 FILE 结构体 * 管理一个文件(文件流)

  • 自带 缓冲区,速度快

  • 能格式化、按行、跨平台、好用

  1. 关系(最重要)
  • stdin / stdout / stderr 是 FILE*,不是数字

  • fileno(fp) 能从 FILE* 拿到 fd 数字

  • 封装 = 为了让你写代码更简单、更快、更安全

系统调用玩数字 fd,C 库玩 FILE 封装。

c封装好处

1. 有缓冲区,速度更快

不用每写一个字节就调用系统,减少开销。
2. 功能更强

能 printf 格式化、 fgets 按行读、 fscanf 解析数据。
3. 跨平台

Windows、Linux、mac 都能用同一套代码。
4. 更简单、更安全

自动帮你管错误、文件位置、状态,不用自己写底层。

为什么语言要有很好的跨平台性?

为了有更多的用户。

相关推荐
内心的一片海37 分钟前
服务器内存异常占用
运维·服务器
文静小土豆1 小时前
Centos7负载异常过高排查思路(Load Average)
linux
Deitymoon1 小时前
linux——原子操作
linux
liulilittle2 小时前
C++ 无锁编程:单停多发送场景高性能方案
服务器·开发语言·c++·高性能·无锁·原子
m0_738120722 小时前
渗透基础知识ctfshow——Web应用安全与防护(第一章)
服务器·前端·javascript·安全·web安全·网络安全
亚空间仓鼠2 小时前
OpenEuler系统常用服务(四)
linux·运维·服务器·网络
郝学胜-神的一滴2 小时前
Socket实战:从单端聊天到多用户连接的实现秘籍
服务器·开发语言·python·网络协议·pycharm
MichealChen0105082 小时前
Influxdb-cluster使用docker部署
运维·docker·容器
昪彧翀忞2 小时前
dhcp小实验
linux·服务器·网络
bukeyiwanshui2 小时前
20260407系统间复制文档
linux