0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux里面最大的套路是“一切都是文件”?

Linux阅码场 来源:Linux阅码场 作者:宋宝华 2021-04-04 17:20 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

当一个女生让你替她抓100只萤火虫,她一定不是为了折磨你,而是因为她爱上了你。当你们之间经历了无数的恩恩怨怨和彼此伤害,她再次让你替她抓100只萤火虫,那一定是因为她还爱着你。

为什么?因为这就是套路,是在下偶尔瞟一眼古装肥皂剧总结出来的套路。

Linux里面最大的套路,就是“一切都是文件”。爱一个人,就为她捉萤火虫;做一件事,就让它成为一个“文件”。

为什么自古深情留不住,唯有“文件”得人心呢?因为文件在用户态最直观的形式是随着一次open,获得一个fd,有了这个fd,长城内外,你基本可以为所欲为:

在本进程内,fd的最直观操作是open、close、mmap、ioctl、poll这些。mmap让你具备把fd透射到内存的能力,所以你可以通过指针访问文件的内容。再者,这个mmap,如果底层透射的是framebuffer、V4L2、DRM等,则让我们具备了从用户态操作底层显存、多媒体数据等的能力;比如,无论是V4L2还是DRM,都支持把底层的dma_buf导出为fd。poll则提供给用户阻塞等待某事件发生的能力。至于ioctl,就更加不用说了,你可以透过ioctl灵活地为fd添加控制命令。

在跨进程的情况下,Linux支持fd的跨进程socket传输,从而可以实现共享内存、dma_buf跨进程共享等。比如一个进程可以通过send_fd可以把fd发送出去:

c77a48b4-8cdd-11eb-8b86-12bb97331649.png

而另外一个进程可以通过recv_fd把fd收过来:

c7fd6e10-8cdd-11eb-8b86-12bb97331649.png

这种fd在长城内外可以互访,fd最终可以指向dma_buf同时可以被mmap,而dma_buf又最终可以被显卡、显示控制器、video decoder/encoder等设备访问的能力,让fd打通了设备、CPU和跨进程的障碍,从此可以横着走。

c8a1bc0e-8cdd-11eb-8b86-12bb97331649.png

我们在《宋宝华:世上最好的共享内存(Linux共享内存最透彻的一篇)》一文中已经详细阐述过这个过程,这里我们就不再赘述了。本文的重点在于匿名inode。

02

inode源头file活水

我们把文件想象成一个object,那么inode描述的是本源,和最终的object一一对应;dentry是inode的一个路径马甲,比如我们可以通过"ln"命令为同一个inode创建很多的硬链接马甲;而file则是活水,进程对object的一次“open”,获得一个file,导致用户态得到一个"fd"的句柄来操作这个object。

经典的inode、dentry、file谁都不缺席的模型是这样的:

c923ab6a-8cdd-11eb-8b86-12bb97331649.png

上图中,我们有一个inode,这个inode有2个dentry,进程A、B open的是第一个dentry;而进程C、D open的是第二个dentry。变了的是file和fd,不变的是inode,中间的dentry马甲没那么重要。

但是在inode、dentry、file这个经典铁三角中,从来都是可以有一个缺席者的,那就是dentry,因为,有时候用户态想获得长城内外行走的便利,但是却不想这个inode在文件系统里面留下一个路径的痕迹。简单来说,我希望有个fd,但是这个fd,你在从"/"往下面搜索的任何一条路径下,你都找不到它,它根本在根文件系统以下不存在路径,它是无名氏,它没有马甲,它是个传说。

比如,近期名震江湖的剑客usefaultfd允许我们在用户空间处理page fault,我们是通过userfaultfd这个系统调用先获得一个fd,之后就可以对它进行各种ioctl了:

c955e08a-8cdd-11eb-8b86-12bb97331649.png

我们透过userfaultfd系统获得了一个fd,它在/xxx/yyy/zzz这样的文件系统下没有路径。这种情况下的fd,对应着的是一个没有名字的匿名inode,你显然没有办法像fd = open ("xxx", ..)那样来得到匿名inode的fd,因为"xxx"是一个路径,而匿名inode没有xxx,所以你是直接透过syscall userfaultfd这样的系统调用,来获得anon_inode在你的进程里面对应的fd的:

c992adda-8cdd-11eb-8b86-12bb97331649.png

人过留名,雁过留声;杀人者,打虎武松也。但是anon inode不吃这一套,它是一个绝顶的轻功高手,它给与的,是透过fd长城内外行走的能力,但是,在文件系统里面却从未来过。这是用户真实的需求,如果这种需求一定要透过一个dentry的open才能实现,这未免有点画蛇添足了。

03

匿名inode的内核实例

我们接下来可以随便打开个anon inode的实例来看看它是怎么工作的了。首先userfaultd是一个系统调用:

c9af1254-8cdd-11eb-8b86-12bb97331649.png

这个代码里面比较核心的是就是,它通过:

anon_inode_getfd_secure()

生成一个匿名inode,并获得一个句柄fd。重点别忘记了,这种“文件”也是可以有file_operations的,比如上面anon_inode_getfd_secure()参数中的userfaultfd_fops:

ca50fb3c-8cdd-11eb-8b86-12bb97331649.png

这样,我们就可以在file_operations的ioctl,poll,read等callback里面实现自己特别的“文件”逻辑,这是我们自由发挥的舞台。

说起anon_inode_getfd_secure(),它再往底层走一级是__anon_inode_getfd():

caaeae4e-8cdd-11eb-8b86-12bb97331649.png

进而再走一级是__anon_inode_getfile():

cad2b118-8cdd-11eb-8b86-12bb97331649.png

所以本质上,是先造一个anon_inode,然后再在这个anon_inode上面造一个pseudo的file,最后通过fd_install(fd, file),把fd和file缠在一起。再次强调,用户有了这个fd就可以为所欲为;而内核本身,则是通过file_operations的不同实现来为所欲为的。

anon_inode之上添加一个系统调用,造一种特殊的fd,让用户去poll,去ioctl,把想象空间拉大了。这种实现方法,如此拉风灵活,以至于它本身也成为了一种套路。比如内核里面fs目录下的:

cb1f06a8-8cdd-11eb-8b86-12bb97331649.png

eventfd,eventpoll,fscontext,io_uring,fanotify,inotify,signalfd,timerfd.......

正所谓, 待到秋来九月八,我花开后百花杀。冲天香阵透长安,满城尽带黄金甲。文件,哪怕最终是匿名的,都以冲天的香阵,弥漫整个Linux的世界。

04

用户使用匿名inode

到了要说再见的时刻了,用户可见的就是fd,通过fd来使用匿名inode。下面我们来制造一个page fault的例子,让用户态来处理它,这个例子直接简化自userfaultfd的man page。我们在主线程中,通过mmap申请一页内存,然后通过userfaultfd的ioctl告诉内核这页的开始地址和长度,以及通过UFFDIO_REGISTER告诉内核这页的page fault想用户空间处理:

cb9e5016-8cdd-11eb-8b86-12bb97331649.png

然后我们在pthread_create()创建的fault_handler_thread线程中,poll userfaultfd等待事件,之后把一页全是0x66的内容拷贝到page fault发生的那一页:

cbcb0f52-8cdd-11eb-8b86-12bb97331649.png

我们运行这个程序得到的输出如下:

cbf2495a-8cdd-11eb-8b86-12bb97331649.png

我们主线程在执行addr[0]=0x5A5A5A5A的时候,触发了page fault。在fault线程里面,page fault发生后,poll阻塞返回,之后用户通过read()读到了一个uffd_msg的结构体,里面的成员包含了page fault的地址。之后,我们通过UFFDIO_COPY这个ioctl,把内容为0x66的页面拷贝给page fault的页面。

所以,最终主线程在执行printf打印的时候,addr[0]里面读到了5A5A5A5A,剩下的addr[1]里面读到了66666666。看到page fault由用户态灵活这么灵活自如地处理,我的小伙伴们都吓尿了。

可以看出来:

poll()在等什么,完全被定制化了;

read()能读什么,完全被定制化了;

ioctl()能控制什么,完全被定制化了。

我们通过“文件”这个不变的“静”,制造了poll、read、ioctl的灵动自如。兵法有云,以不变应万变,以万变应不变。

原文标题:宋宝华:论一切都是文件之匿名inode

文章出处:【微信公众号:Linuxer】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11893

    浏览量

    220211
  • 文件
    +关注

    关注

    1

    文章

    602

    浏览量

    26237
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    做试验变压器耐压试验,为何一切顺利却数据不合格?

    现场准备工作一切就绪,被试的开关柜或变压器绝缘电阻测试完美,试验变压器接入也正确,升压过程平稳无异常,保护未动作,大家都以为试验即将圆满通过。然而,当电压升至规程要求的数值时,监视仪上显示的泄漏
    的头像 发表于 06-02 16:21 77次阅读
    做试验变压器耐压试验,为何<b class='flag-5'>一切</b>顺利却数据不合格?

    文搞懂Linux文件权限

    Linux个多用户操作系统,文件权限管理是系统安全的基石。正确的权限设置可以防止未授权访问、限制用户操作范围、保护敏感数据。无论是最简单的个人 VPS 还是大型企业服务器,权限管理都是
    的头像 发表于 05-30 13:55 154次阅读

    零基础玩转Linux+Ubuntu实战视频课程

    把它当成“命令记忆库”,要把它当成“场从自动挡汽车换到手动挡汽车的驾驶培训”。 这篇文章的核心价值,不在于教你背下多少条指令,而在于向你揭示 Linux 底层最核心的哲学:“一切文件
    发表于 04-18 16:16

    在 4GB 型号上检测到的内存大小错误为 8GB,怎么解决?

    - 看起来内存检测有问题 - 至少如果其他人也是如此。所有这一切都是完整的 69 图像。 在 /boot/boot/extlinux/extlinux.conf 中添加 mem=4000M 是种解决方法,可避免在系统尝试访问内存的不存在部分时崩溃
    发表于 03-24 06:17

    Linux文件删除的底层原理和恢复方法

    rm -rf 大概是 Linux 世界里杀伤力最大的命令,没有之。手抖、路径错、通配符
    的头像 发表于 02-11 09:14 1266次阅读

    VisionFive 2 固件构建错误 tmp 文件未找到怎么解决?

    所以我直在按照官方指南构建最新的固件,opensbi,uboot,凡是你能想到的 现在一切都正常,直到您创建实际的 fw_payload.img 的步骤,我收到以下错误
    发表于 02-09 08:13

    飞凌嵌入式ElfBoard-Linux系统中的文件分类

    从本质上讲,Linux系统就是由文件组成的,一切文件linux系统设计的核心理念,接下来介绍一下文件
    发表于 12-09 08:59

    别再装系统了!Linux 镜像到底是什么?篇讲到你怀疑人生

    多小、环境多复杂,如何快速安装、部署和维护 Linux 系统,都是开发者和运维人员必须掌握的核心技能。 这时,“Linux 镜像文件”就显得尤为重要。它就像
    的头像 发表于 12-03 16:12 1163次阅读
    别再装系统了!<b class='flag-5'>Linux</b> 镜像到底是什么?<b class='flag-5'>一</b>篇讲到你怀疑人生

    存储失忆症的AI守护官

    未来的数据失火可以防患于未然,这一切都有赖于这个叫AI的记忆守护官
    的头像 发表于 11-25 17:12 6970次阅读
    存储失忆症的AI守护官

    Linux新手通关!5分钟掌握文件/目录管理,告别“找不到北”

    文件夹时明明点了操作,打开却空无物… 其实 Linux 的文件 / 目录管理有 “固定套路”,学会 8 个核心命令,再记住 3 个避坑技巧
    的头像 发表于 11-17 10:42 783次阅读
    <b class='flag-5'>Linux</b>新手通关!5分钟掌握<b class='flag-5'>文件</b>/目录管理,告别“找不到北”

    新手小白必看!关于A100云主机租用,你想知道的一切都在这!

    “我想租台A100云主机来跑我的模型,但完全不知道从何下手。”——这是我们听到最多的来自AI新手的声音。A100,这个听起来就“高大上”的名词,背后其实是套清晰、可操作的流程。今天,我们就用
    的头像 发表于 10-31 19:24 2189次阅读
    新手小白必看!关于A100云主机租用,你想知道的<b class='flag-5'>一切都</b>在这!

    硬件工程师:一切都要从误判说起

    行业资讯
    扬兴科技
    发布于 :2025年09月09日 18:06:12

    Linux三大主流文件系统解析

    还在为选择哪个文件系统而纠结?作为名摸爬滚打多年的运维老鸟,我将用最接地气的方式,带你彻底搞懂 Linux 三大主流文件系统的奥秘。
    的头像 发表于 08-05 17:37 1949次阅读

    文掌握Linux命令

    作为名运维工程师,熟练掌握Linux命令是基本功中的基本功。无论是日常工作中的系统维护,还是面试时的技术考核,Linux命令都是绕不开的核心技能。本文将从实战角度出发,系统梳理运维工
    的头像 发表于 07-22 15:23 833次阅读

    Linux系统目录结构全面剖析

    Linux文件系统采用层次化的目录结构,这种设计遵循了Unix哲学中的"一切文件"原则。理解Linux目录层次架构对于系统管理员、运维工程
    的头像 发表于 07-21 17:33 1199次阅读