【linux】基础IO(二)

我们在基础IO(一)主要讲述了fd,一切皆文件,文件的系统调用与语言文件库函数的关系,
今天主要进行对重定向与缓冲区的理解与应用。另外,对系统调用的read进行一下使用。

read的使用:

再使用read之前我们先了解一下
在这里插入图片描述
我们知道 文件 = 内容 + 属性,那么我们无非是对文件的内容或属性进行操作,这三个函数就是对文件的属性进行操作,获取对应的文件信息,可以更精细的控制read系统调用函数。
在这里插入图片描述
此函数是输出型函数,我们就从可以传入的这个结构体中获得需要的信息(我们在这只需要文件大小)。
我们写个代码验证一下
在这里插入图片描述
实验结果:

在这里插入图片描述
故我们就初步了解了这个函数的用法,接下来我们使用read函数。
先来简单看一下read函数的使用方法:
在这里插入图片描述
实验代码:
在这里插入图片描述
注意:read的返回值是返回读入字符的个数。

初步理解重定向与文件缓冲区

今天的硬菜就来了。

我们先来探讨一下fd的分配规则

先关闭标准输入
在这里插入图片描述
实验结果:
在这里插入图片描述


将标准错误关闭的结果:
在这里插入图片描述


将标准输出关闭的结果:
什么都没有打印。
在这里插入图片描述
于是我们得到一个结论:
文件标识符总是从最小的开始分配。

但是我们肯定困惑一个点,为什么关闭了1之后就不会打印了呢?

我们在代码中多加几行(fprintf与ffulsh)。在这里插入图片描述

在这里插入图片描述
我们运行程序还是没有打印,
但是我们在创建的文件中发现了原本打印在显示器中的文件打印到了文件中。这是为什么呢?

而注释掉fflush,log.txt文件中也什么都没有了,这就涉及到了两个知识点

重定向:

在这里插入图片描述
于是我们对重定向有了大概得认识、

缓冲区:

那么FILE内除了_fileno外还有别的吗
答案是还有,还有缓冲区的存在!
在这里插入图片描述
于是我们就可以理解上面的问题了
close(1)后向stdout(1)写入,再fflush,不会打印到显示器而是会打印到新打开的文件中,原因是因为重定向,再刷新语言层的缓冲区。

而如果我们不加fflush就不会刷新是因为,我们的进程在return的时候会先刷新缓冲区等清理工作,而我们在进程return之前先close(1),导致无法向1的内容中写入,缓冲区的内容就会丢失。

再理解重定向与文件缓冲区

重定向

我们上述进行的重定向操作实在是比较粗糙,还要先关闭一个文件再打开一个新的。
那我们不想这样做怎么办?
利用系统调用dup2
在这里插入图片描述
在这里插入图片描述

这个函数就是进行重定向的函数。经过学习我们也知道并不是两个fd之间的拷贝,而是他们指向的内容进行拷贝。

经过man的描述,我们也知道了dup2的使用方法。
那我们进行使用一下
在这里插入图片描述
上述操作进行了重定向,因此是向log.txt中进行写入。
在这里插入图片描述
事实也确实如此。


缓冲区:

我们现在已经知道两个缓冲区

  1. 用户级缓冲区
  2. 内核级缓冲区

那么说了这么久,缓冲区到底有什么存在的意义?

  • 解耦
  • 提高效率

解耦我们暂时先不谈。

主要谈谈第二点:
我们知道,文件的写入读出本质都是拷贝,那么我们多了一个缓冲区,多拷贝一次效率快岂不是在扯淡?

答案并不是:

  1. 他可以提高我们使用者的效率,就像你要送一个物品给你的朋友(你在海南他在东北),你是开车去送还是直接顺丰?答案是我们当然选择直接快递,这样提高了我们的效率
  2. 提高IO效率,我们先输出一个结论,调用系统调用是有成本的,OS这么忙还要配合你,无疑是要加重负担。就像我们寄快递,但是只有你一件快递就要求快递员给你送,还是再多囤一囤再一块送?无疑第二种效率更高

我们总结一下:

缓冲区是什么?

  • 一段内存空间。

为什么存在?

  • 给上层提供良好的IO体验,提高整体效率

怎么做

  • 刷新策略(针对用户层面):

a.

  1. 立即刷新,fflush(stdout),fsync(fd)我们暂时还没有用到,刷新内核缓冲区到硬件
  2. 行刷新,针对显示器
  3. 全缓冲,缓冲区写满才刷新,普通文件。

b.特殊情况

  1. 进程退出
  2. 强制刷新,类似a1

练习

那么我们现在写一段奇怪的代码。
在这里插入图片描述
这段代码的现象显而易见。
在这里插入图片描述
重定向到log.txt
在这里插入图片描述
OK,都没问题


那么我们加一个fork?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
为什么重定向到普通文件中时printf与fprintf会多打印一次?

我们这里要用到刚刚讲过的知识点,
首先我们知道一切的罪魁祸首一定是fork。
其次我们显示器的刷新策略是行刷新,而普通文件是全缓冲。
在这里插入图片描述

所以我们就知道了这样的原因:由于策略发生改变,fork后,语言层的缓冲区会写时拷贝,因此多打印一次,而内核的缓冲区再执行刷新操作时不会写时拷贝。

注意的细节:

fork对文件缓冲区的影响:
在这里插入图片描述

刷新操作不会发生写时拷贝。

在这里插入图片描述

今日IO分享完毕~

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux IO 模型是指 Linux 操作系统中的 IO 处理机制。它的目的是解决多个程序同时使用 IO 设备时的资源竞争问题,以及提供一种高效的 IO 处理方式。 Linux IO 模型主要分为三种:阻塞 IO、非阻塞 IOIO 多路复用。 阻塞 IO 指的是当程序进行 IO 操作时,会被挂起直到 IO 操作完成,这种方式简单易用,但是对于高并发环境不太适用。 非阻塞 IO 指的是程序进行 IO 操作时,如果无法立即完成,会立即返回一个错误码,程序可以通过循环不断地进行 IO 操作来实现轮询的效果。非阻塞 IO 可以提高程序的响应速度,但是会增加程序的复杂度。 IO 多路复用指的是程序可以同时监听多个 IO 设备,一旦有 IO 事件发生,就会立即执行相应的操作。IO 多路复用可以提高程序的效率,但是需要程序员手动编写代码来实现。 Linux IO 模型还有其他的实现方式,比如信号驱动 IO 和异步 IO 等。但是这些方式的使用比较复杂,一般不常用。 ### 回答2: Linux中的IO模型是指操作系统在处理输入输出的过程中所遵循的一种方式。它主要包括阻塞IO、非阻塞IO、多路复用IO和异步IO四种模型。 阻塞IO是最简单的IO模型,当一个IO操作发生时,应用程序会被阻塞,直到IO操作完成才能继续执行。这种模型的特点是简单直接,但是当有多个IO操作时会造成线程的阻塞,影响系统的性能。 非阻塞IO是在阻塞IO基础上发展而来的,应用程序在发起一个IO操作后可以继续执行其他任务,不必等待IO操作的完成。但是需要通过轮询来不断地检查IO操作是否完成,效率相对较低。 多路复用IO使用select、poll、epoll等系统调用来监听多个IO事件,当某个IO事件就绪时,应用程序才会进行读写操作,避免了前两种模型的效率问题。多路复用IO模型适用于连接数较多时的场景,如服务器的网络通信。 异步IO是最高效的IO模型,应用程序发起一个IO操作后,立即可以执行其他任务,不需要等待IO操作的完成。当IO操作完成后,操作系统会通知应用程序进行后续处理。异步IO模型常用于高吞吐量、低延迟的应用,如高性能服务器和数据库等。 总之,Linux IO模型提供了多种不同的方式来处理输入输出,每种模型都有其适用的场景和特点。选择合适的IO模型可以提高系统的性能和效率。 ### 回答3: Linux IO模型是指操作系统中用于处理输入输出操作的一种方法或机制。在Linux中,常见的IO模型有阻塞IO、非阻塞IOIO多路复用和异步IO。 阻塞IO是最基本的IO模型,当应用程序发起一个IO请求时,它将一直阻塞等待直到IO操作完成,期间无法做其他任务。虽然简单易用,但是对资源的利用不高。 非阻塞IO在发起一个IO请求后,不会阻塞等待IO操作完成,而是立即返回并继续做其他任务。应用程序需要不断地轮询IO操作状态,直到操作完成。由于需要不断轮询,对CPU的占用较高,但可以提高资源的利用率。 IO多路复用是通过一个线程同时监听多个IO事件,从而实现并发处理多个IO操作。在IO多路复用模型中,应用程序不需要进行轮询,而是通过调用select、poll或epoll等系统调用监听多个文件描述符的IO事件。这样可以在单个线程中处理多个IO操作,提高并发性能。 异步IO模型在发起一个IO请求后,应用程序不需要等待IO操作完成,而是继续做其他任务。当IO操作完成后,操作系统会通知应用程序。异步IO模型需要操作系统的支持,效率较高,但实现较为复杂。 通过选择合适的IO模型,可以根据不同的应用场景来提高IO操作的效率和性能。例如,对于需要同时处理大量连接的服务器应用,IO多路复用是一种常见的选择;而对于需要处理大量IO操作的高性能服务器,则可以考虑使用异步IO模型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值