搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
Gausst松鼠会
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
Mybatis sql 控制台格式化
2
Linux常用命令汇总及示例_linux命令常用且举例
3
C语言之练手题
4
2020年4月编程语言排行榜:Java依旧占据首位!Kotlin一蹶不振_安卓编程语言排名
5
Ue4----渲染流程_ue4插件影片渲染流程
6
ROS2(Cpp或Python)机器学习路径选择三维模拟平衡车及YOLOv8视觉消息
7
【文本分类】利用bert-base-chinese训练自己的模型完成中文文本分类任务(pytorch实现)_/data/learn_project/backup_data/bert_chinese
8
Springboot3整合myBatisplus报错:Bean named ‘ddlApplicationRunner‘ is expected to be of type ‘org.sprin_bean named 'ddlapplicationrunner' is expected to b
9
干货:如何让GPT写长文?(突破上下文长度最大限制)_gpt 上下文限制
10
Android应用配置文件详解(AndroidManifest.xml)(上)_androidmanifest queries 配置
当前位置:
article
> 正文
read()/write()的生命旅程-系列_libc read
作者:Gausst松鼠会 | 2024-03-17 14:03:48
赞
踩
libc read
http://blog.sina.com.cn/s/blog_a558c25a0102v7nj.html
read()/write()是libc最常用的库函数,那么在application调用了read()/write()之后,发生了哪些事情,数据经过了怎样的流程才从media上读出到用户的buffer里,或是从用户buffer被写到media上的呢?本文将通过以下章节详细阐述整个过程。
第一章:文件系统基础
整个文件系统Overview
从libc到SYSCALL
VFS的分发
重要概念:file, inode, page cache, file mapping, address space
第二章:read()
read():从file operation到page cache
read():从page cache到bio
重要概念:page cache, buffer head和bio
第三章:write()
write():从file operation到page cache
write():从page cache到writeback queue
第四章:writeback:
writeback的init, register
从writeback queue到bio
第五章:从bio到media
block layer的核心:request queue
bio进入request queue
ioscheduler
request的接力
第一章:文件系统基础
1. 整个文件系统Overview
下图显示了Linux中文件系统涉及的所有模块,我们会在之后的章节了一个一个描述他们的职责和关系。
2. 从libc到SYSCALL
这一部分比较简单,libc调用了Kernel的SYSCALL read()/write():
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count)。
SYSCALL_DEFINE3(open,
const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return
do_sys_open
(AT_FDCWD, filename, flags, mode);
}
本文之后的read()/write()均是指kernel的SYSCALL read()/write。
3. VFS的分发
VFS的全称是 Virtual File System,即虚拟文件系统。他是位于各种实际的文件系统如ext2, ext3, nfs和用户层之间的接口,他的存在意义是:
对用户层而言:VFS屏蔽了各种实际文件系统的差异点,为用户层提供了一套统一的接口来进行文件操作,用户不必关心实际的文件系统是什么。
这套统一接口就是文件操作相关的一系列SYSCALL,如open(), read(), write(), seek()等。
对于各种实际文件系统而言:VFS提供了一套统一接口,只要实现了这套接口,就能为用户提供这种文件系统的支持。实际的文件系统不需要关心用户会进行怎样的操作。这套接口就是各种文件系统注册到VFS的file_operations结构。下面是ext2的file_operations:
const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl,
#endif
.mmap = generic_file_mmap,
.open = dquot_file_open,
.release = ext2_release_file,
.fsync = ext2_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
在 发生SYSCALL read()/write()后,VFS会根据fd来判断该文件是哪种文件系统的文件,并调用相应的file_operations.read()来处理
。fd属于什么文件系统的对应关系是在read()/write()之前的open()时就已经建立的。下图表明了VFS的作用(假设APP要read/write的文件在ext2文件系统上)。
4. 重要概念:file, inode, page cache, address space
在讲解read()/write()的详细流程前,必须先理解文件系统的几个重要概念,否则后面的都是天书。
file:
是进程里一个打开的文件,它的有效范围就是打开它的进程。
如通过open()获得一个fd,这个fd只在这个进程里代表这个文件,对于其他进程这个fd无意义
。文件系统中的一个文件abc.txt,如果在process 1中fd1=open()一次,在proces 2中也fd2=open()一次,fd1和fd2是完全独立的,虽然他们打开的是media上的同一个文件。
inode:
inode是kernel为每一个文件(目录也是文件)建立的数据结构。inode和media上实际的文件一一对应。前面提到的fd1和fd2打开的是同一个文件,所以他们指向一个inode。也就是说一个文件在许多进程中被打开,每个进程有自己的file, 但是这些file都指向同一个inode。这种指向是通过file->f_mapping->host来实现的。
page cache:
为了加快文件读写的速度,kernel会把最近访问的inode(也就是文件)的数据缓存在内存里,我们知道linux的内存管理的是以页为单位的,这些inode数据的缓存就叫做page cache。 注意是inode的数据不是inode本身。inode->i_mapping->page_tree指向了一个inode的被kernel缓存的所有page cache的tree。
file mapping:
文件被load到page cache里之后page还是物理地址,通过mmap2()或kmap()可以将page map到虚拟地址上,这样用户或kernel就可以读写page cache里的内容了。这个过程叫做file mapping。mmap2()是系统调用,将文件load到page cache并map到user space。kmap()是kernel里的函数,将page映射到kernel space。
address space:
这是一个比较难理解的概念。抽象的说
struct address_space是用来描述kernel里某一实体的物理缓存page
,以及这些page对应的虚拟地址映射的关系的。在文件系统这个实体就是inode,所以address_space->host != NULL,必须指向一个inode。在其他一个场合address_space->host可以为NULL。inode->i_mapping指向它的address space。每个进程里的file也有一个file->f_mapping,其实file->f_mapping在open()的时候就已经file->f_mapping=inode->i_mapping了。所以,所有同一个inode的file会共享address space。
一个inode的所有已经被缓存的page都在inode->i_mapping->page_tree里。这些page被map到所有进程的虚拟地址空间的描述即很多个vm_area_struct都在inode->mapping->i_mmap和inode->mapping->nonlinear里。注意:一个inode的page可以被不同的进程map,如Preocess 1和Process 2都map了file这个文件的page,因为每个进程的虚拟地址是独立的,所以在inode->mapping->i_mmap里有2个vm_area_struct分别描述在Process 1和Process 2里的map关系。
struct address_space里还有一个重要的成员struct address_space_operations *a_ops。address_space_operations定义了page cache的一系列操作,如.readpage(), .writepage()等。对于像linux这样支持page cache的文件系统,page cache的操作至关重要。
因为所有的文件读写都要通过page cache
,对文件的读写最后都要转化为page cache的读写。address_space_operations里的这些函数指针是每个特定的文件系统,如ext2, ext3等必须要实现的。在后面我们将详细阐述。
下面这张图显示了file, inode, page cache, file mapping,address space之间的关系。
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/256411
推荐阅读
article
MySql
事务
隔离
级别:读未
提交
(
Read
un
committed
)、读已
提交
(
Read
commi...
一、
MySql
事务
隔离
级别
隔离
级别 脏读 不可重复读 幻读 读未
提交
(
Read
un
committed
) ...
赞
踩
article
MySQL
事务
隔离级别----
Read
committed
(读已提交)_
mysql
数据库
使用
read
...
根据实际需求,通过设置
数据库
的
事务
隔离级别可以解决多个
事务
并发情况下出现的脏读、不可重复读和幻读问题,
数据库
事务
隔离级别...
赞
踩
article
MYSQL--未
提交
(
read
un
committed
)、读已
提交
(
read
committed
)和...
(1)读未
提交
(
read
um
committed
):允许一个事务可以看到其他事务未
提交
的修改。(2)读已
提交
(
read
...
赞
踩
article
read
un
commit
,
read
commit
,
repeatable
read
,
共享锁VS...
一般大家都对事务的四种隔离模式比较熟悉,从松到严依次是:- 读取未提交(Read un
commit
ted):处于此模式下...
赞
踩
article
mysql
的读已
提交
和可重复读(
Read
Committed
和
Repeatable
Read
隔离级别...
共享锁和排他锁READ-COMMITTED读已
提交
REPEATABLE-READ可重复读_读已
提交
读已
提交
...
赞
踩
article
关于
MySQL
事务
隔离
级别
Read
committed
(读以
提交
)会
出现
隔离
机制失效_读已
提交
会...
上完了
MySQL
课程 的
事务
隔离
机制后,在课后测试
Read
committed
(读以
提交
)
出现
的问题,很有意思的一个现...
赞
踩
article
Maven "
Unable
to
read
local
copy
of
metadata
" prob...
我安装了ubuntu之后,编译maven工程报错,大概内容是"can't
read
[mvn_
local
_rep]/or...
赞
踩
article
py
t
hon 使用
opencv
读取图片,解决
cv2
.
error
:
OpenCV
(4.1.0) C:\...
完整代码如下:# -*- coding: u
t
f-8 -*-# @Time : 2019/5/27 19:24# @Au...
赞
踩
article
Android平台中调用串口功能时报错:
java
.
io
.IOExcept
io
n:
read
fail...
Android平台中调用串口功能时返回错误:
java
.
io
.IOExcept
io
n:
read
failed
: EBA...
赞
踩
article
[
RK3288
]
串口
开发之运行
app
权限不够报错闪退(基于
android
8.1使用
android
s...
接着上一章运行
app
遇到的问题[
RK3288
]
串口
JNI开发之so库的生成(
串口
C源代码)(基于
android
8.1使用...
赞
踩
article
ubuntu16.04.2安装完后重启报错[sda]
Assuming
drive
cache
: w...
原因:检测主机的物理连接线,发生问题时“已连接”未勾选,重启的时候找不到iso文件解决办法:勾选“已连接”,重启机器成功...
赞
踩
article
Xcode
l
oc
a
liz
a
tion f
a
iled to re
a
d
a
strings
file问...
有可能是你的L
oc
a
liz
a
ble.
strings
格式写的有问题 ,检查所有的L
oc
a
liz
a
ble.
strings
文件...
赞
踩
article
Rus
t
初识_rus
t
c
couldn
'
t
read
./
hello
.rs:...
Rus
t
初识
Rus
t
是一门系统级编程语言,被设计为保证内存和线程安全,并防止段错误。作为系统级编程语言,它的基本理念...
赞
踩
article
解决
Android
Studio
Gradle
'app'project refresh faile...
报错信息:Error:Could
not
read
cache
value
from
'/Users/luochuan/...
赞
踩
article
关于
android
studio
Error:Could not
read
cache
value
...
android
studio
的错误_
could
not
read
cache
value
from
'c:\users...
赞
踩
article
【Linux】
文件
操作
(
open
/
read
/
write
/
close
)、系统调用与库
函数
的区别_wri...
一、
文件
描述符概念:
文件
描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开
文件
...
赞
踩
article
C语言中的I/O
系统
调用
(
Create
,
Open
,
Close
, Read, Write)_
系统
调...
文章目录重要术语I/O
系统
调用
1.
Create
2.
open
3. close4. read5. write参考文档重要...
赞
踩
article
文件
I/O操作
open
()
,
close
()
,
read
()和
write
()函数详解_
open
()创建新...
1.
open
()函数功能描述:用于打开或创建
文件
,在打开或创建
文件
时可以指定
文件
的属性及用户的权限等各种
参数
。所需头文...
赞
踩
article
linux
C库函数---
write
_
linux
c
write
...
文章目录1、头文件2、函数原型3、返回值4、举例1、头文件#in
c
lude
2、函数原型ssize_t...
赞
踩
article
c
语言
write
函数
,
write
- C
语言
库
函数
手册...
write
功能: 写到一文件中用法: int
write
(inthandel, void *buf, int nbyte...
赞
踩
相关标签
Mysql
事务
事务隔离
mysql
数据库
java
maven
Glassfish
Ubuntu
Apache
HTML
opencv 读取图片
android
android-studio
shell
串口通信
rust
android studio
gradle
库函数与系统调用函数
文件操作