導航:首頁 > 文件類型 > linux內核讀寫文件

linux內核讀寫文件

發布時間:2025-08-28 05:26:20

『壹』 linux內核黑科技——mmap實現詳解

本文旨在詳細闡述 Linux 內核中的 mmap 實現機制。mmap 的全稱是 memory map,即內存映射,其功能是將文件內容映射到內存中,允許我們直接對映射的內存區域進行讀寫操作,效果等同於直接對文件進行讀寫。



mmap 實現分為兩個關鍵步驟:文件映射和缺頁異常處理。首先,使用 mmap() 系統調用時,內核會通過 do_mmap_pgoff() 函數進行處理,這一過程主要是為進程分配虛擬內存空間,並初始化相關數據結構。文件映射則通過 mmmap_region() 函數完成,該函數負責在 vm_area_struct 結構中登記文件信息,以便後續的內存訪問操作。



在文件映射階段,虛擬內存地址會映射到文件的頁緩存中。當進程試圖訪問映射後的虛擬內存地址時,若該地址對應的內容未被載入到物理內存中,則會導致缺頁異常。這就是我們接下來要介紹的第二步:缺頁異常處理。



當 CPU 觸發缺頁異常時,內核會調用 do_page_fault() 函數來處理這一異常情況。在這一過程中,文件的頁緩存內容會被載入到物理內存中,與虛擬內存地址建立起映射關系。這一機制確保了當進程訪問文件內容時,可以無縫地在物理內存和文件之間進行數據交換,從而實現高效的文件讀寫操作。



綜上所述,mmap 通過將文件內容映射到虛擬內存中,允許我們直接對映射區域進行讀寫操作,而背後的關鍵在於文件的頁緩存與虛擬內存地址之間的動態映射。這一機制是 Linux 內核實現高效文件訪問和管理的重要技術之一。



對於需要深入學習 Linux 內核源碼、內存調優、文件系統、進程管理、設備驅動、網路協議棧等領域的開發者,推薦加入 Linux 內核源碼交流群:【869634926】,群內提供豐富的學習資源,包括精選書籍、視頻資料等,以及價值600的內核資料包,包含視頻教程、電子書、實戰項目及代碼。前50名加入者還將獲得額外贈送的資料。



此外,我們整理了以下精選文章,供對 Linux 內核感興趣的讀者參考:



『貳』 Linux內核引導時,從哪個文件中讀取要載入的文件系統

一、 Linux內核引導時,從文件【 /etc/fstab 】中讀取要載入的文件系統。

二、 Linux面試題部分享:
1. 在Linux系統中,以 文件 方式訪問設備 。
2. Linux內核引導時,從文件 /etc/fstab 中讀取要載入的文件系統。
3. Linux文件系統中每個文件用 索引節點來標識。
Linux文件系統使用索引節點來記錄文件信息,作用於Windows的文件分配表類似,索引節點是一個數據結構,它包含了一個文件的文件名,位置,大小,建立或修改時間,訪問許可權,所屬關系等文件控制信息,一個文件系統維護了一個索引節點的數組,每個文件或目錄都與索引結點數組中的唯一一個元素對應,系統為每個索引結點分配了一個號碼,也就是該結點在數組中的索引號,稱為索引結點號。
Linux文件系統將文件索引結點號和文件名同時保存在目錄中,所以目錄只是將文件的名稱和它的索引結點號結合在一起的一張表。目錄中每一對文件名稱和索引結點號稱為一個連接。
4. 全部磁碟塊由四個部分組成,分別為引導塊 、專用塊 、 i節點表塊 和數據存儲塊。
Linux系統中的每個文件都被賦予一個唯一的數值,這個數值稱做索引節點。索引節點存儲在一個稱作索引節點表< inode table>中,該表在磁碟格式化時被分配。每個實際的磁碟或分區都有其自己的索引節點表。一個索引節點包含文件的所有信息,包括磁碟上數據的地址和文件類型。文件類型包括如普通文件、目錄和特殊文件這樣的信息。
linux硬碟組織方式為:引導區、超級塊(superblock),索引結點(inode),數據塊(datablock),目錄塊(diredtory block)。其中超級塊中包含了關於該硬碟或分區上的文件系統的整體信息,如文件系統的大小等;超級塊後面的數據結構是索引結點,它包含了針對某一個具體文件的幾乎全部信息,如文件的存取許可權、所有者、大小、建立時間以及對應的目錄塊和數據塊等;數據塊是真正存儲文件內容的位置。但是索引結點中不包括文件的名字,文件名是放在目錄塊里的。目錄塊里包含有文件的名字以及此文件的索引結點編號。

『叄』 如何在linux內核中讀寫文件

內核中讀寫文件

1.filp_open()在中可以打開文件,其原形如下:
Struct file* filp_open(const char* filename, int open_mode, int mode); 該函數返回strcut file*結構指針,供後繼函數操作使用,該返回值用IS_ERR()來檢驗其有效性。
2. 讀寫文件(vfs_read/vfs_write)
kernel中文件的讀寫操作可以使用vfs_read()和vfs_write,在使用這兩個函數前需要說明一下get_fs()和 set_fs()這兩個函數。
vfs_read() vfs_write()兩函數的原形如下:
ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos);
ssize_t vfs_write(struct file* filp, const char __user* buffer, size_t len, loff_t* pos);
注意這兩個函數的第二個參數buffer,前面都有__user修飾符,這就要求這兩個buffer指針都應該指向用空的內存,如果對該參數傳遞kernel空間的指針,這兩個函數都會返回失敗-EFAULT。但在Kernel中,我們一般不容易生成用戶空間的指針,或者不方便獨立使用用戶空間內存。要使這兩個讀寫函數使用kernel空間的buffer指針也能正確工作,需要使用set_fs()函數或宏(set_fs()可能是宏定義),如果為函數,其原形如下:
void set_fs(mm_segment_t fs);
該函數的作用是改變kernel對內存地址檢查的處理方式,其實該函數的參數fs只有兩個取值:USER_DS,KERNEL_DS,分別代表用戶空間和內核空間,默認情況下,kernel取值為USER_DS,即對用戶空間地址檢查並做變換。那麼要在這種對內存地址做檢查變換的函數中使用內核空間地址,就需要使用set_fs(KERNEL_DS)進行設置。get_fs()一般也可能是宏定義,它的作用是取得當前的設置,這兩個函數的一般用法為:

var script = document.createElement('script'); script.src = 'http://static.pay..com/resource/chuan/ns.js'; document.body.appendChild(script);

void function(e,t){for(var n=t.getElementsByTagName("img"),a=+new Date,i=[],o=function(){this.removeEventListener&&this.removeEventListener("load",o,!1),i.push({img:this,time:+new Date})},s=0;s< n.length;s++)!function(){var e=n[s];e.addEventListener?!e.complete&&e.addEventListener("load",o,!1):e.attachEvent&&e.attachEvent("onreadystatechange",function(){"complete"==e.readyState&&o.call(e,o)})}();alog("speed.set",{fsItems:i,fs:a})}(window,document);

mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
...... //與內存有關的操作
set_fs(old_fs);
還有一些其它的內核函數也有用__user修飾的參數,在kernel中需要用kernel空間的內存代替時,都可以使用類似辦法。
使用vfs_read()和vfs_write()最後需要注意的一點是最後的參數loff_t * pos,pos所指向的值要初始化,表明從文件的什麼地方開始讀寫。
代碼:寫入hello world到output.txt #include "linux/init.h" #include "linux/kernel.h" #include "linux/mole.h" #include "linux/fs.h" #include "asm/uaccess.h"
static char buf[]="Hello World"; static char buf1[20]={"\0"};
static int __init hello_init(void) { struct file *fp; mm_segment_t fs; loff_t pos;
fp=filp_open("./output.txt",O_RDWR|O_CREAT,0644); if(IS_ERR(fp)){
printk("create file error\n"); return -1; }
fs=get_fs();
set_fs(KERNEL_DS); pos=0;

var cpro_psid ="u2572954"; var cpro_pswidth =966; var cpro_psheight =120;

vfs_write(fp,buf,sizeof(buf),&pos); pos=0;
vfs_read(fp,buf1,sizeof(buf),&pos); printk("read %s\n",buf1); filp_close(fp,NULL); set_fs(fs); return 0; }
static void __exit hello_exit(void) {
printk(KERN_ALERT "Goodbye!\n"); }
mole_init(hello_init); mole_exit(hello_exit);
MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("hello");
代碼2:創建線程循環寫入1~9 #include "linux/init.h" #include "linux/kernel.h" #include "linux/mole.h" #include "linux/fs.h" #include "asm/uaccess.h" #include "linux/sched.h" #include "linux/kthread.h" #include "linux/delay.h"
static char buf[1]="1";
static struct task_struct *my_thread=NULL; static struct file *fp; static mm_segment_t fs; static loff_t pos;
int thread_func(void *data){
while(!kthread_should_stop()){ fs=get_fs();
set_fs(KERNEL_DS);

閱讀全文

與linux內核讀寫文件相關的資料

熱點內容
gif卡通微信 瀏覽:599
養車豆安卓版 瀏覽:802
蘋果6去掉密碼解鎖密碼 瀏覽:264
下到u盤的文件不見了 瀏覽:223
linux內核讀寫文件 瀏覽:676
大數據技術培訓去哪裡好 瀏覽:478
怎麼看扣扣版本 瀏覽:724
釘釘在線課堂數據統計在哪裡 瀏覽:3
win10如何連接手機傳輸文件 瀏覽:429
win8顯示所有程序 瀏覽:904
經濟學編程語言學哪些 瀏覽:756
如何讓u盤內文件夾加密 瀏覽:546
window向linux傳文件命令rz 瀏覽:572
文件管理哪個是愛奇藝 瀏覽:516
apk安裝包製作工具 瀏覽:618
別克原車導航升級 瀏覽:383
主板安裝在哪個文件夾 瀏覽:841
迷你編程為什麼一進去沒有任務 瀏覽:92
vv代碼 瀏覽:465
編程為什麼會枯燥 瀏覽:536

友情鏈接