日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux vfs open函数,Linux VFS中open系统调用实现原理

發布時間:2023/12/1 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux vfs open函数,Linux VFS中open系统调用实现原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用戶空間的函數在內核里面的入口函數是sys_open

通過grep open /usr/include/asm/unistd_64.h查找到的

#define __NR_open2

__SYSCALL(__NR_open, sys_open)

觀察unistd_64.h,我們可以猜測用戶空間open函數最終調用的系統調用號是2來發起的sys_open系統調用(畢竟glibc一般的做法都會做,用戶空間的函數名字和內核空間中調用的很像,如果需要得到非常準確的,請查看glibc源碼找到對應的系統調用號,再和內核里面的系統調用號去一一對比)。這里我們不糾結。

函數內容

通過前面的我們得知,sys_open實際就是下面這個函數(fs/open.c中)

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)

{

long ret;

if (force_o_largefile())

flags |= O_LARGEFILE;

ret = do_sys_open(AT_FDCWD, filename, flags, mode);

/* avoid REGPARM breakage on x86: */

asmlinkage_protect(3, ret, filename, flags, mode);

return ret;

}

其中先調用force_o_largefile()來判斷是否需要設置大文件標識,然后調用do_sys_open來完成具體的工作。其中

force_o_largefile()

在IA64系統中arch/ia64/include/asm/fcntl.h,定義如下

#define _ASM_IA64_FCNTL_H

#define force_o_largefile()(personality(current->personality) != PER_LINUX32)

#include

#endif /* _ASM_IA64_FCNTL_H */

而其余的在include/linux/fcntl.h中

#ifndef force_o_largefile

#define force_o_largefile() (BITS_PER_LONG != 32)

#endif

所以,在非32位的OS上,force_o_largefile()都為true,而32位的OS則為false

另外,我們可以查看我們的OS位數:

# grep CONFIG_64BIT /boot/config-2.6.32-220.el6.x86_64

CONFIG_64BIT=y //64位

#ifdef CONFIG_64BIT

#define BITS_PER_LONG 64

#else

#define BITS_PER_LONG 32

#endif /* CONFIG_64BIT */

所以:只有在32位的OS上此處才為false(這里不考慮IA64架構,我們考慮的是x86架構),所以64位的系統上flags會自動加上O_LARGEFILE,32位的則沒有,所以文件最大大小受索引節點中表示文件大小的32位的i_size的影響,只能訪問2的32次方字節,即4GB(實際高位一般不用,所以通常只有2G)。加上O_LAGEFILE之后啟用索引節點的i_dir_acl字段也可以一起表示文件的大小了,這樣位數就變成了64位,2的64位就4GB*4GB,單個文件這么大已經很大了16T了

我們重點來看do_Sys_open函數do_sys_open(AT_FDCWD, filename, flags, mode)

函數原型long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)。

這個函數這里(我們講述最主要的內容)執行過程

fd(int型)

(1)在當前進程打開的文件位圖表中,找到第一個為0的位,返回這個位在位圖表里面的下標,這個下標就是將用分配的未使用的文件描述符fd

(2)把當前進程的文件表擴展一個文件(即嘗試添加一個struct file到當前

進程的文件列表中),進程task_struct->files_struct->fd_array[NR_OPEN_DEFAULT]是一個struct file 數組,而NR_OPEN_DEFAULT在64位系統中等于64(因為一般進程打開的文件數大多都用這個數組就可以直接放下了),如果擴展操作導致當前進程的這個存放struct file的數組放不下了,如要裝第65個struct flie結構體,那么將重新分配一片內存區專門用來存放struct file結構體,并且這個內存區的大小為128個struct file結構體,然后將當前進程的task_struct->files_struct->fdtable->fd指針指向這片內存的首地址,然后把之前數組里面的內容復制到這片內存區里面來。下次添加如果超過了128個了,則分配256個大小直到256個也裝滿,超過256則分配512,依次類推,總是2的冪次方,且會把之前的復制到新分配的內存里面去

注意:這里只是更新了進程的這個file table,新的進程描述符對應的struct file還沒有生成進去。

(3)設置進程的文件位圖中新分配的這個文件描述符位為(1)中找到的下標,并更新下一次該分配的進程描述符起點

struct file結構體

Struct file =kmem_cache_zalloc(filp_cachep, GFP_KERNEL);

pathname查找或建立對應的dentry

并設置此dentry對應的inode。內核做這個事情借助于一個nameidata數據結構

(1)如果pathname中第一個字符是“/”,那么說明使用絕對路徑,設置nameidata為更目錄對應的dentry和當前目錄的inode,mount點等

(2)如果不是“/”,則使用相對路徑,設置nameidata為當前目錄對應的dentry,inode,mount點等

(3)一層一層往下查找,直到找到最終的那個文件或者目錄分量,注意:如”/usr/bin/make”,先找“/”(這是3.1就做了的),再找“/”下面的usr,再找bin,最后找make。

這里細說一下第一層怎么在“/“下面找到”usr“的:

第一層查找先找“/”下面的usr對應的dentry,內核通過“/”對應的dentry和”usr”字符串兩個參數進行hash運算獲取一個dentry的鏈表

然后逐個看這個鏈表里面有沒有parent dentry為“/”對應的dentry的,以及dentry對應的名字的hash值是否與“usr”對應的hash值相同

前面條件都滿足這里再看一下parent dentry是否有DCACHE_OP_COMPARE標識,如果有此標識且文件系統實現了dentry->dentry_operations->d_compare函數,那么就調用文件系統的這個函數來判斷

如果條件都符合,那么說明內存中usr對應的這個dentry是存在的,如果這個dentry->d_flags中包含DCACHE_OP_REVALIDATE,那么就會調用此dentry->dentry_operatoin->d_revalidate來進行一次核對(網絡文件系統此函數都實現了,以便于遠程的便跟,在這里會得到更新)

如果最終usr對應的dentry不存在,那么內核就在內存中直接分配一個dentry結構體并且把dentry的name和“usr”對應起來,并且設置這個dentry的parent為“/”對應的dentry,然后還要調用”/”對應的dentry->d_inode這個inode的inode_operation->lookup(“/”的inode,新建的dentry,flags),如果返回了新的dentry,那么就把dentry結構體指針指向新返回的dentry,否則還是返回剛剛新創建的那個dentry。(一般的文件系統都實現了inode_operation->lookup,我猜他們會在這個函數里面如果/usr存在則把dentry對應的inode給設置好。。如果/usr不存在則返回一個NULL之類的,以一個錯誤跳出整個路徑執行)

到這里,無論是dentry已經存在于內存中找到的,還是新創建的dentry,總之,對應于“usr”結構的dentry在內存中已經存在了。然后調用follow_managed()函數找到“usr”最新的vfsmount(這里有一點點麻煩,后續會專門講,這里只需要指定如果”/dev/sda”mount 到了/mnt,/dev/sdb 也mount到了/mnt,那么這里返回的是最新的這條/dev/sdb mount到/mnt這個vfsmount)。

然后把這個已經找到的或創建的dentry(已經存在于內存中的dentry已經有了inode和它綁定,新建立的dentry也通過inode_operation->lookup建立起來了inode和dentry的聯系(此函數會在操作真正的磁盤介質吧inode讀出來))和這個最新的vfsmount存到struct path中

然后把這個含有dentry,vfsmount的path結構體存入nameidata數據結構中,到這里,“usr“對應的dentry,inode,vfsmount都準備好了,且存到了nameidata中了

(4)接著(3)里面,一層一層的往下找,依次會找到usr,bin,最后到了”make”

這里就不調用一層一層往下找的函數了,進入另外一個函數do_last()函數來

處理。在dolast,在dolast里面如果此dentry不存在則創建它,如果有O_CREATE

標識則創建這個文件的inode(這里會調用vfs_create函數,繼續調用dentry->inode_operation->create來建立inode,文件系統實現的此函數會操作正在的磁盤介質去創建inode),并且建立inode和dentry的聯系,并且建立”make”對應的vfsmount為最新的mount結構,至此,“/usr/bin/make”中最后一個分量“make”的dentry,inode,vfsmount都存到nameidata中去了。

接著還會把2中分配的file結構體的path(包含dentry和vfsmount)的dentry分量設置為nameidata的這個dentry(dentry結構體中已經有inode的指針),vfsmount也設置為nameidata的vfsmount,并且設置file結構體的file->f_mapppin為nameidata中dentry的inode的i_mapping.并且設置file->f_pos指針為0。

至此,make對應的新分配的這個struct file結構體中的dentry,inode,vfsmount都為nameidata中的了,并且struct file映射到內存的address_space也設置為了inode對應的address_space,struct file的當前位置指針設置為了0,“make”分量的這個struct file結構體準備好了。

接著還會把這個struct file結構體加入其inode對應的super_block超級塊的s_files鏈表中,即struct file結構體會加入其自身inode所在超級塊的所有文件鏈表中。

并且如果自身inode的file_operations不為空則還會設置這個struct file的file_operation等于inode的這個file_operations,即公用inode的file的操作方法。如果inode的file_operations沒有實現,則設置為空。

設置此文件標識符為FILE_OPENED.

fd到這個struct file結構體的聯系

調用fd_install(fd,f)來把1中分配的文件描述符和3中的struct file建立聯系。

過程簡單描述一下,先獲取當前進程的fdtable(簡單可理解為進程的關聯的所有文件數組)的所有文件數組fdtable=current->files->fdt,(current為當前進程task_struct),設置fdtable->fd[fd]=file,(下標fd即新分配的文件描述符,file即為3中創建的struct file結構體)。

這樣,進程和文件描述符,struct file,dentry,inode,vfsmount就全部關聯起來了。

附圖片:完整的內核調用我畫的visio學習圖,歡迎糾正理解,圖片需要放很大才能看清。。

。。汗。。圖片有4M多,上傳不了。。

參考:kernel 3.6.7源碼

總結

以上是生活随笔為你收集整理的linux vfs open函数,Linux VFS中open系统调用实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 午夜视频在线播放 | 99国产精品一区二区 | 国产av无码专区亚洲av毛片搜 | 精品日韩在线播放 | 一区二区三区不卡在线 | 91口爆一区二区三区在线 | 国产亚洲精品久久久久久久久动漫 | 日韩少妇一区二区三区 | 成人午夜视频在线免费观看 | 国产精品视频一区二区三区在3 | 人妻丰满熟妇av无码区免 | 日本韩国中文字幕 | 日本黄色免费大片 | 香蕉视频在线观看视频 | 亚洲区偷拍| 国产美女一级片 | 国产人妻精品一区二区三区不卡 | 久久青青草原 | 亚洲精品人 | 精品亚洲国产成人av制服丝袜 | 人妻激情偷乱视频一区二区三区 | 97人妻精品一区二区三区软件 | 在线免费观看你懂的 | 免费黄色片视频 | 99久久婷婷国产综合精品草原 | 亚洲精品一区二区三区四区乱码 | 91香蕉嫩草| 蜜臀av在线观看 | 色天使亚洲 | 日韩视频在线观看免费视频 | 午夜黄网| 欧色图| 国产伦精品一区二区三区网站 | 一级艳片新婚之夜 | 日日摸夜夜添狠狠添欧美 | 久久久久国产精品夜夜夜夜夜 | 日韩中文字幕一区二区 | 欧美8888| 久久尹人 | 午夜一区不卡 | 制服丝袜av一区二区三区下载 | 永久免费无码av网站在线观看 | 玖玖爱在线观看 | 成人午夜精品一区二区三区 | 黄色录象片| 一区二区三区国产 | 成人免费黄色片 | 欧美性色黄大片手机版 | 三级国产视频 | 国产视频一区二区在线 | 五月六月丁香 | 欧美三级在线观看视频 | 日本中文在线观看 | 99热免费精品 | 青草操| 逼逼av | 日韩高清在线播放 | 一级片自拍 | 粗大的内捧猛烈进出在线视频 | 天天天天操 | 99热这里只有精 | 成人六区 | 奇米影视第4色 | 美女激情网| 自拍偷拍欧美视频 | 亚洲综合二区 | 无码精品一区二区三区在线 | 国产精品无码一区二区三区在线看 | 日韩精品电影在线观看 | 国产亚洲三级 | 国产美女特级嫩嫩嫩bbb | 欧美四区 | 日韩中文字幕在线播放 | 在线观看亚洲一区二区 | 成人动漫一区二区三区 | 国产精品伦子伦免费视频 | 天天尻逼 | 免费黄色小视频网站 | 初音未来打屁股 | 久久久久在线视频 | 99自拍视频| 欧洲美女粗暴牲交免费观看 | 操皮视频 | 亚洲国产综合视频 | 手机在线永久免费观看av片 | 白丝av| 天天视频色 | 亚洲一区影院 | 免费成人深夜夜国外 | 一区二区三区日本视频 | 午夜激情网址 | 99热| 亚洲一区二区中文 | 欧美亚洲一级 | 免费人成又黄又爽又色 | 麻豆久久久9性大片 | 亚洲综合首页 | 久久综合99 | 国产网站免费在线观看 |