linux源碼文件名,Linux中文件名解析處理源碼分析

Linux中文件名解析處理源碼分析

前言

Linux中對一個文件進行操作的時候,一件很重要的事情是對文件名進行解析處理,并且找到對應文件的inode對象,然后創建表示文件的file對象。在此,對文件名解析過程,并且如何找到對應inode的過程進行源碼分析。分析代碼基于Linux-3.2版本。

關鍵函數分析

不管是通過應用層的API函數還是在內核中打開一個文件,最終都需要調用filp_open函數,該函數的主要職責就是解析文件名,找到文件對應的inode對象,然后分配內存創建file對象,最后執行該文件對應的file->open函數。

filp_open的核心處理函數是path_openat,該函數分析如下:

static struct file *path_openat(int dfd, const char *pathname,

struct nameidata *nd, const struct open_flags *op, int flags)

{

struct file *base = NULL;

struct file *filp;

struct path path;

int error;

/* 創建一個file對象 */

filp = get_empty_filp();

if (!filp)

return ERR_PTR(-ENFILE);

.filp->f_flags = op->open_flag;

nd->intent.open.file = filp;

nd->intent.open.flags = open_to_namei_flags(op->open_flag);

nd->intent.open.create_mode = op->mode;

/* 初始化檢索的起始目錄,判斷起始目錄是根目錄還是當前目錄,并且初始化nd->inode對象,為link_path_walk函數的解析處理做準備。 */

error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);

if (unlikely(error))

goto out_filp;

.current->total_link_count = 0;

/* 關鍵的字符串解析處理函數,其核心思想是分級解析字符串,通過字符串對應的目錄項找到下一級目錄的inode節點。該函數的具體分析如下。 */

error = link_path_walk(pathname, nd);

if (unlikely(error))

goto out_filp;

/* do_last函數創建或者獲取文件對應的inode對象,并且初始化file對象,至此一個表示打開文件的內存對象filp誕生 */

filp = do_last(nd, &path, op, pathname);

while (unlikely(!filp)) { /* trailing symlink */

struct path link = path;

void *cookie;

if (!(nd->flags & LOOKUP_FOLLOW)) {

path_put_conditional(&path, nd);

path_put(&nd->path);

filp = ERR_PTR(-ELOOP);

break;

}

nd->flags |= LOOKUP_PARENT;

nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);

error = follow_link(&link, nd, &cookie);

if (unlikely(error))

filp = ERR_PTR(error);

else

filp = do_last(nd, &path, op, pathname);

put_link(nd, &link, cookie);

}

out:

if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))

path_put(&nd->root);

if (base)

fput(base);

release_open_intent(nd);

return filp;

.out_filp:

filp = ERR_PTR(error);

goto out;

}

link_path_walk函數完成了基本的名字解析功能,是名字字符串解析處理實現的核心。該函數的實現基于分級解析處理的思想。例如,當需要解析“/dev/mapper/map0”字符串時,其首先需要判斷從何處開始解析?根目錄還是當前目錄?案例是從根目錄開始解析,那么獲取根目錄的dentry對象并開始分析后繼字符串。以’/’字符為界按序提取字符串,首先我們可以提取”dev”字符串,并且計算該字符串的hash值,通過該hash值查找detry下的inode hash表,就可以得到/dev/目錄的inode對象。依次類推,最后解析得到”/dev/mapper/”目錄的inode對象以及文件名”map0”。至此,link_path_walk函數的使命完成,最后可以通過do_last函數獲取或者創建文件inode。link_path_walk函數分析如下:

static int link_path_walk(const char *name, struct nameidata *nd)

{

struct path next;

int err;

/* 移除’/’字符 */

while (*name=='/')

name++;

/* 如果解析已經完成,直接返回 */

if (!*name)

return 0;

./* At this point we know we have a real path component. */

for(;;) {

unsigned long hash;

struct qstr this;

unsigned int c;

int type;

/* inode訪問的permission檢查 */

err = may_lookup(nd);

if (err)

break;

.this.name = name;

c = *(const unsigned char *)name;

/* 初始化hash值 */

hash = init_name_hash();

do {

name++;

/* 累計計算名字字符串的hash值 */

hash = partial_name_hash(c, hash);

c = *(const unsigned char *)name;

/* 如果遇到’/’字符,結束一次hash計算統計 */

} while (c && (c != '/'));

/* 得到字符串長度和hash結果 */

this.len = name - (const char *) this.name;

this.hash = end_name_hash(hash);

.type = LAST_NORM;

/* LAST_DOT和LAST_DOTDOT情形判斷 */

if (this.name[0] == '.') switch (this.len) {

case 2: /* LAST_DOTDOT是上級目錄 */

if (this.name[1] == '.') {

type = LAST_DOTDOT;

nd->flags |= LOOKUP_JUMPED;

}

break;

case 1: /* LAST_DOT是當前目錄 */

type = LAST_DOT;

}

if (likely(type == LAST_NORM)) {

/* LAST_NORM標記說明是需要通過本地目錄進行字符串解析 */

struct dentry *parent = nd->path.dentry;

nd->flags &= ~LOOKUP_JUMPED;

if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {

/* 如果該標記有效,需要重新計算hash值 */

err = parent->d_op->d_hash(parent, nd->inode,

&this);

if (err <0)

break;

}

}

/* 如果字符串已經解析完畢,直接跳轉到last_component */

/* remove trailing slashes? */

if (!c)

goto last_component;

while (*++name == '/');

if (!*name)

goto last_component;

/* 通過walk_component函數找到解析字符串對應的inode,并且將nd->inode改稱最新inode,準備繼續解析后面的字符串信息。因為目錄項所管理的inode在系統中通過hash表進行維護,因此,通過hash值可以很容易的找到inode。如果內存中還不存在inode對象,對于ext3文件系統會通過ext3_lookup函數從磁盤上獲取inode的元數據信息,并且構造目錄項中所有的inode對象。 */

err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);

if (err <0)

return err;

.if (err) {

err = nested_symlink(&next, nd);

if (err)

return err;

}

if (can_lookup(nd->inode))

continue;

/* 字符串還沒有解析完畢,但是當前的inode已經繼續不允許解析處理了,所以,返回錯誤碼 */

err = -ENOTDIR;

break;

/* here ends the main loop */

.last_component:

/* 最后一個字符串不需要解析處理,需要由do_last函數來處理,此處結束解析,正確返回 */

nd->last = this;

nd->last_type = type;

return 0;

}

terminate_walk(nd);

return err;

}

小結

文件名解析處理是文件系統的必備功能,通過文件名的解析索引到表示文件的inode內存對象,并且創建文件對象file。在文件名解析的過程中,首先需要確定的是檢索起始點,然后通過hash table查找目錄項以及檢索文件。在查找的過程中,需要考慮文件訪問的權限以及符號連接等問題。總體來說這些代碼難度不是很大,但是需要有一個整體的思路,就可以更好的理解分析代碼了,這里只是對名字解析過程中的幾個關鍵函數進行拋磚引玉式的分析。不正之處,敬請指出。

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

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

相關文章

帝國cms linux偽靜態規則,帝國cms7.2偽靜態規則怎么寫

一、在linux主機下實現偽靜態確認虛擬主機是否支持rewrite偽靜態.htaccess文件。添加.htaccess 文件&#xff0c;把htaccess 文件放在網站根目錄。二、在win主機下實現偽靜態確認虛擬主機是否支持rewrite偽靜態httpd.ini文件。添加httpd.ini文件&#xff0c;把httpd.ini文件放入…

linux core 永久生效,【調試】Core Dump是什么?Linux下如何正確永久開啟?

內容簡介【調試】Core Dump是什么&#xff1f;Linux下如何正確永久開啟&#xff1f;Core Dump是什么&#xff1f;Linux下如何正確永久開啟&#xff1f;Core Dump是什么&#xff1f;Core Dump乍聽之下很抽象。當程序運行的過程中異常終止或崩潰&#xff0c;操作系統會將程序當時…

linux故障排查書籍,Linux系統故障排查和修復技巧.docx

fsck -y /cievZhdab(fsck為文件系統檢測修復命令&#xff0c;“-y”設定檢測到錯誤自動修復&#xff0c;Zdev/hda6 為發生錯誤的硬盤分區&#xff0c;請依據具體情況更改此參數) 系統修復完成后&#xff0c;用命令“reboot&#xff0c;重新啟動即可? 案例三、GRUB選項設置錯誤…

用于用戶C語言標識符,下列可用于C語言用戶標識符的一組是( )

摘要&#xff1a;下列不屬于骨肉瘤患者常見護理問題()于C語言用戶組Since people send nonverbal signals through multiple channels simultaneously, it is impossible to increase our nonverbal communication competence by becoming more aware of how it operates in sp…

c語言編程常見問題解答,C語言編程常見問題解答之常用函數的包含文件

函數 包含 類別 功能_atold math.h 數學子程序 把字符串轉換為浮點數_beginthread process.h 進程控制子程序 啟動執行一個新線程_bios_disk bios.h 接口子程序 輸出BIOS磁…

c語言猜四位數游戲猜10次,C語言猜數字游戲--隨機生成4個不相同的數字從小到大排序,用戶開始游戲,如果用戶猜對數字和數字對應的位置,界面回饋A,如果數字正確位置不正確,則回饋B...

1.看程序運行截圖吧&#xff01;&#xff01;由于博主本人較笨&#xff0c;就不動畫演示了&#xff0c;如果動畫的話可能將是一個漫長的過程&#xff01;猜數字游戲.png2.游戲題目隨機生成4個不相同的數字從小到大排序&#xff0c;用戶開始游戲&#xff0c;如果用戶猜對數字和數…

雙端堆c語言,數據結構——雙端堆(C語言)

定義雙端堆&#xff1a;是一棵完全二叉樹&#xff0c;該完全二叉樹要么為空&#xff0c;要么同時滿足下列性質&#xff1a;(1) 根節點不包含元素&#xff1b;(2) 左子樹是一個最小堆&#xff1b;(3) 右子樹是一個最大堆&#xff1b;(4) 如果右子樹不空&#xff0c;令i是左子樹中…

C語言和我的世界指令哪個難,我的世界難度有什么區別 難度選擇指令介紹

我的世界中的難度(Difficulty)可以在Minecraft的選項菜單內切換。更改這個選項將直接影響到游戲本身。選項中并沒有設定影響攻擊性生物的可生成數量&#xff0c;包括和平模式。目前游戲共有和平、簡單、普通和困難4種難度。我的世界難度區別和平&#xff1a;會生成攻擊性生物&a…

w ndows10即將停止更新,微軟開始警告Windows 10 v1909用戶即將停止更新服務

如果您仍在運行Windows 10版本1909&#xff0c;版本1903或更早版本&#xff0c;則可能已經在系統任務欄中注意到一條新消息&#xff1a;Windows 10版本即將終止服務。根據Windows 10 May 2020 Update或2020年10月Update。為了將用戶升級到最新版本的Windows 10&#xff0c;“您…

篩法求素數c 語言,位篩法求素數,有段代碼看不懂,有大佬可以來說一下

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓就是BITArray[ (i -3)/ CHAR_BIT ]其中i從0開始&#xff0c;那下標不就為負了&#xff1f;而指向的又是哪個數據&#xff1f;下面是完整代碼。#include #include #include #include #include #include#include int main( ){unsigne…

c語言中日期間的天數怎么計算,關于計算兩個日期間天數的代碼,大家來看看...

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓這是原貼:http://post.baidu.com/f?kz100411727這是原碼:#include "stdio.h"main(){long int i,a[2],b[2],c[2],x[12]{0,31,59,90,120,151,181,212,243,273,304,334},y,z[2];scanf("%ld-%ld-%ld %ld-%ld-%ld"…

linux nf conntrack,Linux基于mark的策略路由以及nf_conntrack RELATED

談到什么是意義&#xff0c;話題總顯得很大&#xff0c;近日每晚都和老城里的朋友聊老城的文化&#xff0c;老城的老房子&#xff0c;老城的叫賣聲&#xff0c;老城的方言…進行了很多的思考&#xff0c;也挺充實。至于技術方面&#xff0c;也有跟朋友以及前同事聊過&#xff0…

android 根據資源名稱,如何在Android中按名稱訪問可繪制資源

你可以做這樣的事情。public static Drawable getDrawable(String name) {Context context YourApplication.getContext();int resourceId context.getResources().getIdentifier(name, "drawable", YourApplication.getContext().getPackageName());return contex…

Android10不能用谷歌,谷歌真的很嚴格,一大波老APP將不能在安卓10.0運行

蘋果iOS的一大優點就是軟件生態&#xff0c;第三方APP都會主動適配新的iOS系統以及手機。雖然說Android的開放性是也是一大優點&#xff0c;但是第三方軟件參差不齊的優化適配水平也讓安卓的用戶非常頭疼。不過谷歌每年都在致力于讓Android的軟件生態更好。根據XDA的報道&#…

android 回歸測試,android測試:monkey使用方法

android測試&#xff1a;monkey使用方法Android Sdk給我們提供了Monkey和Monkeyrunner這兩個自動化測試工具。一、什么是MonkeyMonkey是一個命令行工具&#xff0c;可以運行在模擬器里或實際設備中。它向系統發送偽隨機的用戶事件流&#xff0c;實現對正在開發的應用程序進行壓…

c語言編程季節輸出春夏秋冬,c語言編程題:?用枚類型定義春、夏、秋、冬四個季節...

滿意答案bcabcdefg2013.07.28采納率&#xff1a;49% 等級&#xff1a;12已幫助&#xff1a;5373人#includeenum season{spring 1,summer,autumn,winter,};season GetSeasonByMonth(char month){if(month < 3 && month>1)return spring;else if(month < 6 …

android fragment addtobackstack,Android Fragment Back Stack的問題

我對android片段Backstack的工作方式遇到了一個很大的問題&#xff0c;對于提供的任何幫助將不勝感激。假設您有3個片段[1] [2] [3]我希望用戶能夠導航[1] > [2] > [3]但在返回的途中(按返回按鈕)[3] > [1]。就像我想象的那樣&#xff0c;這可以通過addToBackStack(..…

華為升級harmonyos的機型名單,華為鴻蒙 OS 2.0 系統適配名單已出,四月推送,天璣機型暫時無緣...

原標題&#xff1a;華為鴻蒙 OS 2.0 系統適配名單已出&#xff0c;四月推送&#xff0c;天璣機型暫時無緣華為官方在 2020 年發布了旗下自研系統“HarmonyOS 2.0”版本&#xff0c;發布會現場展示了 HarmonyOS 2.0 開發者 Beta 版本&#xff0c;并開啟開發者 Beta 的公測。此外…

android如何實現QQ信息通知,android NotificationListenerService監聽通知欄(qq 微信 短信)...

【實例簡介】android NotificationListenerService 監聽通知欄&#xff0c;android NotificationListenerService 監聽通知欄 android NotificationListenerService 監聽通知欄【實例截圖】【核心代碼】NLsevice└── NLsevice├── AndroidManifest.xml├── bin│ ├──…

rsync android app,如何rsync到android

問題描述如何連接到我的Android設備以rsync音樂(或其他東西)&#xff1f;最佳解決思路實際上在MTP /usb上使用rsync這比每個人都說的容易&#xff0c;首先注意到當GVFS安裝MTP掛載時&#xff0c;它將在下面可用。您可以通過在圖形file-browser(thunar /nautilus /etc)中打開手機…