在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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
    +關注

    關注

    87

    文章

    11345

    瀏覽量

    210417
  • 文件
    +關注

    關注

    1

    文章

    570

    瀏覽量

    24823
收藏 人收藏

    評論

    相關推薦

    CES 2025 “AI+一切”成為關鍵趨勢

    一年一度的全球最大科技界盛會 2025 CES(國際消費電子展)以“Dive in”為主題,強調人類與創新技術的結合,探索如何“潛入”未來,吸引了來自全球的4500多家企業參加,其中有1/3左右
    的頭像 發表于 01-15 10:32 ?210次閱讀

    DAC7564修改成4通輸出的時候就沒有反應,為什么?

    基準輸出2.497V看著一切都是正常,但是我修改成4通輸出的時候 就沒有反應,檢查基準輸出 為2.667V通道也沒有了輸出,是不是就是壞了?還有疑問項目中需要用到5片(20通道模擬電壓輸出) 可否將所有的REF腳接在起, 防
    發表于 01-01 07:13

    用DAC39J84EVM做個任意波形發生器,給80M方波的數據用示波器看到的波形占空比是相反的?為什么?

    試圖用DAC39J84EVM做個任意波形發生器,在產生方波的時候出現了問題。 當我給30M方波數據的時候,一切都很正常,但是給80M方波的數據的時候,用示波器看到的波形占空比是相反的,我給的25
    發表于 12-30 07:55

    Linux文件查找

    …] [options] [expression] [action] 查找 地區 妹紙 18-25歲 約? 是linux里面個實時查找工具,通過制定路徑完成
    的頭像 發表于 12-03 17:09 ?352次閱讀

    Linux lsof命令的基本用法

    linux 系統中,一切文件。通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件。所以 lsof 命令不僅可以查看進程打開的文件
    的頭像 發表于 10-23 11:52 ?431次閱讀
    <b class='flag-5'>Linux</b> lsof命令的基本用法

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-Linux C接口編程入門之文件I/O

    一切文件"Linux一切文件"是Linux操作系統中的
    發表于 10-10 09:11

    飛凌嵌入式ElfBoard ELF 1板卡-Linux C接口編程入門之文件I/O

    一切文件"Linux一切文件"是Linux操作系統中的
    發表于 10-09 15:38

    Linux應用層控制外設的兩種不同的方式

    眾所周知,linux一切文件,那么應用層如何控制硬件層,同樣是通過 文件I/O的方式來實現的,那么應用層控制硬件層通常有兩種方式。
    的頭像 發表于 10-05 19:03 ?706次閱讀
    <b class='flag-5'>Linux</b>應用層控制外設的兩種不同的方式

    Linux文件系統的掛載過程

    Linux文件系統(rootfs)是Linux系統中所有其他文件系統和目錄的起點,它是內核啟動時掛載的第
    的頭像 發表于 10-05 16:50 ?518次閱讀

    如何構建Linux文件系統

    構建Linux文件系統是個涉及多個步驟和概念的過程,它對于Linux系統的啟動和運行至關重要。
    的頭像 發表于 10-05 16:47 ?352次閱讀

    HDMI一切四方案DP一切四最新方案

    HDMI4方案該方案目前是采用的深圳市芯視音科技最新研發的CV1021E基礎開發的有需要可有聯系賴工拿資料
    的頭像 發表于 08-23 16:00 ?451次閱讀
    HDMI<b class='flag-5'>一切</b>四方案DP<b class='flag-5'>一切</b>四最新方案

    如何使用云服務器刷寫自定義固件?

    AT 固件。 我們希望使用我們的自定義固件重新刷新此固件。 我們想這樣做,因為我們將制造數百個這樣的模塊,我們希望一切都是自動化的,而無需改變IO引腳。 所以我們不打算用串行端口刷寫它,因為它需要改變接線
    發表于 07-15 08:23

    基本電子元件的內在之美

    作者所寫,這些元件的一切都是為了滿足特定技術需求而刻意設計的,但這種設計產生了“意外之美:那些意外涌現的事物美學”。從本包羅電子大千世界的書中,我們發現那些未曾花太多時間思考的事物(即無源元件
    發表于 07-11 16:49

    配置塊使用PSoC64 MCU的定制電路板報錯的原因?

    我正在嘗試配置塊使用 PSoC64 MCU 的定制電路板。 我直在按照 AN239061 指南進行操作,一切都很順利,直到我嘗試配置電路板時才發現以下錯誤: \'檢測到的設備與正在使用的配置
    發表于 05-31 07:58

    AI造夢師,大模型正在孵化下個黃金職業

    AI電影造夢師這個領域,一切都將是新的
    的頭像 發表于 05-28 09:20 ?1768次閱讀
    AI造夢師,大模型正在孵化下<b class='flag-5'>一</b>個黃金職業
    主站蜘蛛池模板: 台湾毛片 | 色综合天天综合中文网 | 狂捣猛撞侍卫攻双性王爷受 | 特级毛片免费视频播放 | 性欧美videofree另类超大 | 国产性大片黄在线观看在线放 | 一级毛片免费全部播放 | 无人码一区二区三区视频 | 久久精品亚洲一级毛片 | 性 色 黄 一级 | 大伊人网 | 天堂网2018| 午夜精品久久久久久久久 | 男人j进女人j视频 | 亚洲电影免费 | 久久久久久毛片免费播放 | www.亚洲视频.com| 亚洲欧美网 | 123综合网在线 | 亚洲xx站| 亚洲午夜网 | 男女爱爱免费视频 | 高清激情小视频在线观看 | 91视频三级| 免费黄色在线视频 | 好男人社区在线观看www | www.天天射 | 天堂网资源www | 免费观看视频在线观看 | 视频在线观看免费视频 | 亚洲一区高清 | 日韩三级小视频 | 久久久久四虎国产精品 | 视频在线观看一区二区三区 | 男女无遮挡一进一出性视频 | 色中文字幕 | 色综合色综合色综合色综合 | 欧美人与动性xxxxbbbb | 天天搞天天爽 | 精品卡1卡2卡三卡免费视频 | 黄色aaa大片 |