Linux“一切皆文件“設計哲學 與 Linux文件抽象層:struct file與file_operations的架構解析

????????在Linux系統中,“一切皆文件”(Everything is a file)是一個核心設計哲學,它抽象了系統資源的訪問方式,使得幾乎所有硬件設備、進程、網絡連接等都可以通過統一的文件接口(如open()read()write()close()等系統調用)進行操作。

目錄

一、在Linux系統中,"文件"的概念比Windows更為廣泛

二、Linux中的文件

1、普通文件(Regular Files)

2、目錄(Directories)

3、設備文件(Device Files)

4、命名管道(Named Pipes, FIFO)

5、套接字(Sockets)

6、符號鏈接(Symbolic Links)

7、偽文件系統(ProcFS, SysFS, etc.)

8、標準輸入/輸出/錯誤(stdin, stdout, stderr)

9、例外情況

三、這一設計的主要優勢在于

為什么這樣設計?

四、補充說明


一、在Linux系統中,"文件"的概念比Windows更為廣泛

  1. Windows中的文件在Linux中同樣被視為文件
  2. Windows中非文件對象(如進程、磁盤、顯示器、鍵盤等硬件設備)在Linux中也被抽象為文件
  3. 管道同樣被視為文件
  4. 后續將學習到的網絡編程中的套接字(socket)也采用文件接口

二、Linux中的文件

1、普通文件(Regular Files)

  • 包括文本文件、二進制文件等,存儲在磁盤或其他存儲設備中。

  • 例如:/home/user/document.txt

2、目錄(Directories)

  • 目錄本質上是包含其他文件列表的特殊文件。

  • 例如:/etc/?目錄中保存了系統配置文件列表。

3、設備文件(Device Files)

Linux將硬件設備抽象為文件,分為兩類:

  • 塊設備(Block Devices):以固定大小的數據塊訪問(如磁盤)。

    • 例如:/dev/sda(第一塊硬盤)。

  • 字符設備(Character Devices):以字符流形式訪問(如鍵盤、鼠標)。

    • 例如:/dev/tty(終端設備)。

示例操作:

# 向磁盤設備寫入數據(需謹慎!)
dd if=file.img of=/dev/sdb# 從鼠標設備讀取輸入(需權限)
cat /dev/input/mouse0

4、命名管道(Named Pipes, FIFO)

  • 用于進程間通信(IPC)的特殊文件,數據先進先出。

  • 示例:

    mkfifo /tmp/my_pipe
    echo "Hello" > /tmp/my_pipe &  # 寫入端
    cat < /tmp/my_pipe            # 讀取端

5、套接字(Sockets)

  • 用于網絡或本地進程間通信的文件。

  • 例如:/var/run/docker.sock?是Docker守護進程的通信套接字。

6、符號鏈接(Symbolic Links)

  • 指向其他文件的快捷方式。

  • 例如:/bin/sh?可能是指向?/bin/bash?的符號鏈接。

7、偽文件系統(ProcFS, SysFS, etc.)

  • /proc:動態反映進程和內核狀態的文件(如/proc/cpuinfo/proc/1234/為PID 1234的進程信息)。

  • /sys:暴露內核設備和驅動的配置(如調節CPU頻率)。

示例:

# 查看CPU信息
cat /proc/cpuinfo# 修改系統參數(如最大進程數)
echo 10000 > /proc/sys/kernel/pid_max

8、標準輸入/輸出/錯誤(stdin, stdout, stderr)

  • 在Linux中,這些標準流也通過文件描述符訪問:

    • 0:stdin(如鍵盤輸入)。

    • 1:stdout(如終端輸出)。

    • 2:stderr(如錯誤輸出)。

重定向示例:

ls /nonexistent 2> /dev/null  # 將錯誤輸出重定向到“黑洞”設備

9、例外情況

并非所有資源都是文件,例如:

  • 線程調度、內存分配等底層操作仍需通過系統調用(如mmap())。

  • 某些現代內核特性(如cgroups)可能不完全遵循此規則。


、這一設計的主要優勢在于

  • 開發者僅需掌握一套API和開發工具即可調用系統大部分資源
  • 幾乎所有讀取操作(讀取文件、系統狀態、管道等)都可通過read函數實現
  • 幾乎所有寫入操作(修改文件、系統參數、管道等)都可通過write函數完成

為什么這樣設計?

  • 統一性:所有資源通過文件接口操作,簡化編程模型。

  • 抽象性:用戶無需關心底層細節(如硬件差異)。

  • 靈活性:文件權限(如chmod)、重定向(如>)等機制可通用。


四、補充說明

????????當打開文件時,系統會創建對應的file結構體進行管理。該結構體定義于: /usr/src/kernels/3.10.0-1160.71.1.el7.x86_64/include/linux/fs.h 以下展示該結構體的相關部分內容:

struct file {...struct inode *f_inode;     /* Cached inode pointer */const struct file_operations *f_op;...atomic_long_t f_count;     /* Reference count for open files */unsigned int f_flags;      /* File access flags (read/write permissions) */fmode_t f_mode;            /* File access mode (defined in headers) */loff_t f_pos;              /* Current read/write position */...
} __attribute__((aligned(4))); /* Force 4-byte alignment */

????????值得注意的是,struct file 中的 f_op 指針指向一個 file_operations 結構體,該結構體除 struct module* owner 成員外,其余均為函數指針。這兩個結構體均定義于 fs.h 頭文件中:

struct file_operations {struct module *owner;           // 指向所屬模塊的指針loff_t (*llseek)(struct file *, loff_t, int);  // 修改文件當前讀寫位置,返回新位置ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);  // 從設備讀取數據,NULL返回-EINVALssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);  // 向設備寫入數據,NULL返回-EINVALssize_t (*aio_read)(struct kiocb *, const struct iovec *, unsigned long, loff_t);  // 初始化異步讀操作ssize_t (*aio_write)(struct kiocb *, const struct iovec *, unsigned long, loff_t);  // 初始化異步寫操作int (*readdir)(struct file *, void *, filldir_t);  // 僅對文件系統有用,設備文件應為NULLunsigned int (*poll)(struct file *, struct poll_table_struct *);  // 輪詢設備狀態int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);  // 設備控制接口long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);  // 無鎖版ioctllong (*compat_ioctl)(struct file *, unsigned int, unsigned long);  // 兼容版ioctlint (*mmap)(struct file *, struct vm_area_struct *);  // 將設備內存映射到進程地址空間,NULL返回-ENODEVint (*open)(struct inode *, struct file *);  // 打開文件int (*flush)(struct file *, fl_owner_t id);  // 進程關閉文件描述符時調用int (*release)(struct inode *, struct file *);  // 文件結構釋放時調用int (*fsync)(struct file *, struct dentry *, int datasync);  // 刷新掛起數據int (*aio_fsync)(struct kiocb *, int datasync);  // 異步刷新int (*fasync)(int, struct file *, int);  // 異步通知int (*lock)(struct file *, int, struct file_lock *);  // 文件鎖定(設備驅動很少實現)ssize_t (*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int);  // 發送頁面unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);  // 獲取未映射區域int (*check_flags)(int);  // 檢查標志int (*flock)(struct file *, int, struct file_lock *);  // 文件鎖定ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  // 管道寫入ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);  // 管道讀取int (*setlease)(struct file *, long, struct file_lock **);  // 設置租約
};

? ? file_operation 是連接系統調用與驅動程序的核心數據結構,其每個成員都對應著一個特定的系統調用。當系統調用執行時,會讀取 file_operation 中對應的函數指針,并將控制權轉交給該函數,從而完成 Linux 設備驅動程序的調用流程。

為幫助理解,我們用一張圖來總結上述內容:

????????圖中的外設設備雖然各自擁有獨立的讀寫操作方式,但通過 struct file 結構中 file_operation 的函數回調機制,開發者僅需使用 file 接口就能訪問 Linux 系統中的絕大多數資源。這正是"Linux下一切皆文件"理念的核心體現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89578.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89578.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89578.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

藍橋杯零基礎到獲獎-第3章 C++ 變量和常量

藍橋杯零基礎到獲獎-第3章 C 變量和常量 文章目錄一、變量和常量1.變量的創建2.變量初始化3.變量的分類4.常量4.1 字?常量4.2 #define定義常量4.3 const 定義常量4.4 練習練習1&#xff1a;買票https://www.nowcoder.com/practice/0ad8f1c0d7b84c6d8c560298f91d5e66練習2&…

物理AI是什么技術?

當英偉達CEO黃仁勛在鏈博會上明確提出“物理AI將是AI的下一浪潮”時&#xff0c;這個看似陌生的概念瞬間引發了科技圈的廣泛關注。究竟什么是物理AI&#xff1f;它與我們熟悉的人工智能有何不同&#xff1f;又將如何重塑我們與物理世界的交互方式&#xff1f; 物理AI&#xff1…

GRIB數據處理相關指令

GRIB 數據格式簡介 GRIB(General Regularly distributed Information in Binary form)&#xff0c;是由世界氣象組織&#xff08;WMO&#xff09;設計和維護的一種用于存儲和傳輸網格數據的標準數據格式&#xff0c;它是一種自描述的二進制壓縮格式&#xff0c;通常具有擴展名…

微服務學習(六)之分布式事務

微服務學習&#xff08;六&#xff09;之分布式事務一、認識Seata二、部署TC服務1、準備數據庫表2、準備配置文件3、docker部署三、微服務集成seata1、引入依賴2、改造配置3、添加數據庫表4、測試四、XA模式1、兩階段提交2、seata的XA模型3、優缺點4、實現步驟五、AT模式1、Sea…

Go實現用戶登錄小程序

寫一個用戶登錄注冊的小程序 運行程序&#xff0c;給出提示1. 注冊輸入用戶名、密碼、年齡、性別 {"用戶名": "root", "passwd": "123456", "age": 18, "sex": "男"}注冊前要判斷是否存在此用戶2. 登錄…

鴻蒙藍牙通信

https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-bluetooth-low-energy 藍牙權限 module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.ACCESS_BLUETOOTH","reason": "…

Java:Map

文章目錄Map常用方法Map遍歷的三種方法先獲取Map集合的全部鍵&#xff0c;再通過遍歷來找值Entry對象forEach結合lambda表達式Map 案例分析需求我的代碼&#xff08;不好&#xff09;老師的代碼&#xff08;好&#xff09;好在哪里另外集合分為Collection和MapMap常用方法 代碼…

fastjson2 下劃線字段轉駝峰對象

在對接第三方或查詢數據庫時&#xff0c;返回的字段是下劃線分隔的&#xff0c;而在業務中需要轉成java對象&#xff0c;java對象的字段是駝峰的&#xff0c;使用fastjson2時&#xff0c;有兩種方法可以實現&#xff1a; 比如數據格式是&#xff1a; {"item_id": &q…

【硬件】藍牙音頻協議

1. 無線音頻傳輸的工作原理 在無線傳輸的過程中&#xff0c;音源設備首先將MP3、FLAC等音頻文件還原為PCM格式。通過藍牙音頻編碼轉為藍牙無線傳輸的文件&#xff0c;發送到音頻設備段。將藍牙無線傳輸的文件再次還原為PCM格式&#xff0c;之后轉為模擬信號并放大&#xff0c;通…

【宇樹科技:未來1-3年,機器人可流水線打螺絲】

在第三屆中國國際供應鏈促進博覽會上&#xff0c;宇樹科技工作人員表示&#xff0c;未來1到3年內&#xff0c;機器人產品有望從單一工業化產品&#xff0c;發展至復合化工業場景&#xff0c;如機器人搬完箱子后&#xff0c;換個 “手” 就能在流水線上打螺絲。在3到10年內&…

Spring AI 1.0版本 + 千問大模型之 文本記憶對話

上篇文章&#xff0c;主要是簡單講解了一下文本對話的功能。由于模型不具備上下文記憶功能&#xff0c;只能一問一答。因此我們需要實現記憶對話功能&#xff0c;這樣大模型回答信息才能夠更加準確。 1、pom依賴 項目構建就不詳細說了&#xff0c;大家可以參考上篇 文本對話 文…

測試學習之——Pytest Day2

一、Pytest配置框架Pytest的配置旨在改變其默認行為&#xff0c;以適應不同的測試需求和項目結構。理解其配置層級和常用參數&#xff0c;是高效使用Pytest的基礎。1. 配置的意義與層級配置的本質在于提供一種機制&#xff0c;允許用戶根據項目特點、團隊規范或特定測試場景&am…

Go-Redis × RediSearch 全流程實踐

1. 連接 Redis ctx : context.Background()rdb : redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,Protocol: 2, // 推薦 RESP2// UnstableResp3: true, // 若要體驗 RESP3 Raw* })2. 準備示例數據 u…

深入理解指針(指針篇2)

在指針篇1我們已經了解了整型指針&#xff0c;當然還有很多其他類型的指針&#xff0c;像字符指針、數組指針、函數指針等&#xff0c;他們都有他們的特別之處&#xff0c;讓我們接著學習。1. 指針類型介紹和應用1.1 字符指針變量字符指針變量類型為char*&#xff0c;一般這樣使…

Python+Selenium自動化爬取攜程動態加載游記

1. 引言 在旅游行業數據分析、輿情監測或競品研究中&#xff0c;獲取攜程等平臺的游記數據具有重要價值。然而&#xff0c;攜程的游記頁面通常采用動態加載&#xff08;Ajax、JavaScript渲染&#xff09;&#xff0c;傳統的**<font style"color:rgb(64, 64, 64);backg…

ESP8266服務器建立TCP連接失敗AT+CIPSTART=“TCP“,“192.168.124.1“,8080 ERROR CLOSED

1.檢查服務器端口8081是否開啟監聽2.檢查路由項是否被防火墻攔截方法 1&#xff1a;使用 netsh查看防火墻規則?netsh advfirewall firewall show rule nameall dirout | findstr "8081"如果無輸出&#xff0c;說明防火墻未針對該端口設置規則&#xff08;可能默認攔…

Linux 內存管理(2):了解內存回收機制

目錄一、透明大頁1.1 原理1.2 透明大頁的三大優勢1.3 透明大頁控制接口詳解1.4 使用場景與最佳實踐1.5 問題排查與監控1.6 與傳統大頁的對比二、Linux伙伴系統水位機制詳解2.1 三種核心水位詳解2.2 水位在伙伴系統中的實現2.3 水位觸發機制的實際行為2.4 水位關鍵操作接口2.5 水…

前端學習7:CSS過渡與動畫--補間動畫 (Transition) vs 關鍵幀動畫 (Animation)

一、補間動畫&#xff08;Tween Animation&#xff09;vs 關鍵幀動畫&#xff08;Keyframe Animation&#xff09;概念對比表&#xff1a;補間動畫 (Transition)關鍵幀動畫 (Animation)定義元素從初始狀態到結束狀態的過渡效果通過定義多個關鍵幀控制動畫的中間狀態觸發方式需要…

PyTorch 損失函數詳解:從理論到實踐

目錄 一、損失函數的基本概念 二、常用損失函數及實現 1. 均方誤差損失&#xff08;MSELoss&#xff09; 2. 平均絕對誤差損失&#xff08;L1Loss/MAELoss&#xff09; 3. 交叉熵損失&#xff08;CrossEntropyLoss&#xff09; 4. 二元交叉熵損失&#xff08;BCELoss&…

MinIO深度解析:從核心特性到Spring Boot實戰集成

在當今數據爆炸的時代&#xff0c;海量非結構化數據的存儲與管理成為企業級應用的關鍵挑戰。傳統文件系統在TB級數據面前捉襟見肘&#xff0c;而昂貴的云存儲服務又讓中小企業望而卻步。MinIO作為一款開源高性能對象存儲解決方案&#xff0c;正以其獨特的技術優勢成為開發者的首…