九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
sysfs文件系統(tǒng)2

  sysfs是一個(gè)基于內(nèi)存的文件系統(tǒng),它的作用是將內(nèi)核信息以文件的方式提供給用戶程序使用。該文件系統(tǒng)的目錄層次結(jié)構(gòu)嚴(yán)格按照內(nèi)核的數(shù)據(jù)結(jié)構(gòu)組織。除了二進(jìn)制文件外(只有特殊場(chǎng)合才使用),sysfs文件內(nèi)容均以ASCII格式保存,且一個(gè)文件只保存一個(gè)數(shù)據(jù),另外,一個(gè)文件不可大于一個(gè)內(nèi)存頁(yè)(通常為4096字節(jié))。

sysfs提供一種機(jī)制,使得可以顯式的描述內(nèi)核對(duì)象、對(duì)象屬性及對(duì)象間關(guān)系。sysfs有兩組接口,一組針對(duì)內(nèi)核,用于將設(shè)備映射到文件系統(tǒng)中,另一組針對(duì)用戶程序,用于讀取或操作這些設(shè)備。表2描述了內(nèi)核中的sysfs要素及其在用戶空間的表現(xiàn):

 

sysfs在內(nèi)核中的組成要素

在用戶空間的顯示

內(nèi)核對(duì)象(kobject)

目錄

對(duì)象屬性(attribute)

文件

對(duì)象關(guān)系(relationship)

鏈接(Symbolic Link)

表2:sysfs內(nèi)部結(jié)構(gòu)與外部表現(xiàn)

 

在Ubuntu或Fedora等Linux系統(tǒng)中,我們可以用ls –F <路徑>命令來(lái)通過(guò)文件后綴查看文件類型?!?”表示文件夾,“@”表示鏈接,沒(méi)有后綴就是文件了。

sysfs目錄結(jié)構(gòu)

/sys 下的子目錄

所包含的內(nèi)容

/sys/devices

這是內(nèi)核對(duì)系統(tǒng)中所有設(shè)備的分層次表達(dá)模型,也是/sys文件系統(tǒng)管理設(shè)備的最重要的目錄結(jié)構(gòu);

/sys/dev

這個(gè)目錄下維護(hù)一個(gè)按字符設(shè)備和塊設(shè)備的主次號(hào)碼(major:minor)鏈接到真實(shí)的設(shè)備(/sys/devices下)的符號(hào)鏈接文件;

/sys/bus

這是內(nèi)核設(shè)備按總線類型分層放置的目錄結(jié)構(gòu), devices 中的所有設(shè)備都是連接于某種總線之下,在這里的每一種具體總線之下可以找到每一個(gè)具體設(shè)備的符號(hào)鏈接,它也是構(gòu)成 Linux 統(tǒng)一設(shè)備模型的一部分;

/sys/class

這是按照設(shè)備功能分類的設(shè)備模型,如系統(tǒng)所有輸入設(shè)備都會(huì)出現(xiàn)在/sys/class/input 之下,而不論它們是以何種總線連接到系統(tǒng)。它也是構(gòu)成Linux 統(tǒng)一設(shè)備模型的一部分;

/sys/kernel

這里是內(nèi)核所有可調(diào)整參數(shù)的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的 slab 分配器等幾項(xiàng)較新的設(shè)計(jì)在使用它,其它內(nèi)核可調(diào)整參數(shù)仍然位于sysctl(/proc/sys/kernel) 接口中;

/sys/module

這里有系統(tǒng)中所有模塊的信息,不論這些模塊是以內(nèi)聯(lián)(inlined)方式編譯到內(nèi)核映像文件(vmlinuz)中還是編譯為外部模塊(ko文件),都可能會(huì)出現(xiàn)在/sys/module 中:

  • 編譯為外部模塊(ko文件)在加載后會(huì)出現(xiàn)對(duì)應(yīng)的/sys/module/<module_name>/,并且在這個(gè)目錄下會(huì)出現(xiàn)一些屬性文件和屬性目錄來(lái)表示此外部模塊的一些信息,如版本號(hào)、加載狀態(tài)、所提供的驅(qū)動(dòng)程序等;
  • 編譯為內(nèi)聯(lián)方式的模塊則只在當(dāng)它有非0屬性的模塊參數(shù)時(shí)會(huì)出現(xiàn)對(duì)應(yīng)的/sys/module/<module_name>,這些模塊的可用參數(shù)會(huì)出現(xiàn)在/sys/modules/<modname>/parameters/<param_name> 中,
    • 如/sys/module/printk/parameters/time這個(gè)可讀寫參數(shù)控制著內(nèi)聯(lián)模塊printk在打印內(nèi)核消息時(shí)是否加上時(shí)間前綴;
    • 所有內(nèi)聯(lián)模塊的參數(shù)也可以由"<module_name>.<param_name>=<value>"的形式寫在內(nèi)核啟動(dòng)參數(shù)上,如啟動(dòng)內(nèi)核時(shí)加上參數(shù)"printk.time=1"與向"/sys/module/printk/parameters/time"寫入1的效果相同;
  • 沒(méi)有非0屬性參數(shù)的內(nèi)聯(lián)模塊不會(huì)出現(xiàn)于此。

/sys/power

這里是系統(tǒng)中電源選項(xiàng),這個(gè)目錄下有幾個(gè)屬性文件可以用于控制整個(gè)機(jī)器的電源狀態(tài),如可以向其中寫入控制命令讓機(jī)器關(guān)機(jī)、重啟等。

表3:sysfs目錄結(jié)構(gòu)

 

深入理解sysfs

sysfs_dirent是組成sysfs單元的基本數(shù)據(jù)結(jié)構(gòu),它是sysfs文件夾或文件在內(nèi)存中的代表。sysfs_dirent只表示文件類型(文件夾/普通文件/二進(jìn)制文件/鏈接文件)及層級(jí)關(guān)系,其它信息都保存在對(duì)應(yīng)的inode中。我們創(chuàng)建或刪除一個(gè)sysfs文件或文件夾事實(shí)上只是對(duì)以sysfs_dirent為節(jié)點(diǎn)的樹(shù)的節(jié)點(diǎn)的添加或刪除。sysfs_dirent數(shù)據(jù)結(jié)構(gòu)如下:

struct sysfs_dirent {

       atomic_t                s_count;

       atomic_t                s_active;

       struct sysfs_dirent  *s_parent;  /* 指向父節(jié)點(diǎn) */

struct sysfs_dirent  *s_sibling;  /* 指向兄弟節(jié)點(diǎn),兄弟節(jié)點(diǎn)是按照inode索引s_ino的大小順序鏈接在一起的。*/

       const char             *s_name;    /* 節(jié)點(diǎn)名稱 */

 

       union {

              struct sysfs_elem_dir            s_dir;      /* 文件夾,s_dir->kobj指向sysfs對(duì)象 */

              struct sysfs_elem_symlink    s_symlink;  /* 鏈接 */

              struct sysfs_elem_attr           s_attr;     /* 普通文件 */

              struct sysfs_elem_bin_attr     s_bin_attr;  /* 二進(jìn)制文件 */

       };

 

       unsigned int           s_flags;

ino_t          s_ino;     /* inode索引,創(chuàng)建節(jié)點(diǎn)時(shí)被動(dòng)態(tài)申請(qǐng),通過(guò)此值和sysfs_dirent地址可以到inode散列表中獲取inode結(jié)構(gòu) */

       umode_t                s_mode;

       struct iattr             *s_iattr;

};

 

inode(index node)中保存了設(shè)備的主從設(shè)備號(hào)、一組文件操作函數(shù)和一組inode操作函數(shù)。文件操作比較常見(jiàn):open、read、write等。inode操作在sysfs文件系統(tǒng)中只針對(duì)文件夾實(shí)現(xiàn)了兩個(gè)函數(shù)一個(gè)是目錄下查找inode函數(shù)(.lookup=sysfs_lookup),該函數(shù)在找不到inode時(shí)會(huì)創(chuàng)建一個(gè),并用sysfs_init_inode為其賦值;另一個(gè)是設(shè)置inode屬性函數(shù)(.setattr=sysfs_setattr),該函數(shù)用于修改用戶的權(quán)限等。inode結(jié)構(gòu)如下:

struct inode {

       struct hlist_node     i_hash;    /* 散列表鏈節(jié) */

       struct list_head       i_list;

       struct list_head       i_sb_list;

       struct list_head       i_dentry;  /* dentry鏈節(jié) */

       unsigned long         i_ino;   /* inode索引 */

       atomic_t             i_count;

       unsigned int           i_nlink;

       uid_t                     i_uid;

       gid_t                     i_gid;

       dev_t                    i_rdev; /* 主從設(shè)備號(hào) */

const struct inode_operations *i_op; /* 一組inode操作函數(shù),可用其中l(wèi)ookup查找目錄下的inode,對(duì)應(yīng)sysfs為sysfs_lookup函數(shù) */

const struct file_operations  *i_fop;    /* 一組文件操作函數(shù),對(duì)于sysfs為sysfs的open/read/write等函數(shù) */

       struct super_block  *i_sb;

       struct list_head       i_devices;

       union {

              struct pipe_inode_info    *i_pipe;

              struct block_device       *i_bdev;

              struct cdev            *i_cdev;

       };

};

 

dentry(directory entry)的中文名稱是目錄項(xiàng),是Linux文件系統(tǒng)中某個(gè)索引節(jié)點(diǎn)(inode)的鏈接。這個(gè)索引節(jié)點(diǎn)可以是文件,也可以是目錄。引入dentry的目的是加快文件的訪問(wèn)。dentry數(shù)據(jù)結(jié)構(gòu)如下:

struct dentry {

       atomic_t d_count;         /* 目錄項(xiàng)對(duì)象使用的計(jì)數(shù)器 */

       unsigned int d_flags;             /* 目錄項(xiàng)標(biāo)志 */

       spinlock_t d_lock;              /* 目錄項(xiàng)自旋鎖 */

       int d_mounted;                     /* 對(duì)于安裝點(diǎn)而言,表示被安裝文件系統(tǒng)根項(xiàng) */

       struct inode *d_inode;           /* 文件索引節(jié)點(diǎn)(inode) */

       /*

        * The next three fields are touched by __d_lookup.  Place them here

        * so they all fit in a cache line.

        */

       struct hlist_node d_hash;       /* lookup hash list */

       struct dentry *d_parent; /* parent directory */

       struct qstr d_name;              /* 文件名 */

 

       /*

        * d_child and d_rcu can share memory

        */

       union {

              struct list_head d_child; /* child of parent list */

             struct rcu_head d_rcu;

       } d_u;

      

       void *d_fsdata;                    /* 與文件系統(tǒng)相關(guān)的數(shù)據(jù),在sysfs中指向sysfs_dirent */

       unsigned char d_iname[DNAME_INLINE_LEN_MIN];      /* 存放短文件名 */

};

 

sysfs_dirent、inode、dentry三者關(guān)系:

圖3-1:sysfs在內(nèi)存中的形態(tài)

 

如上圖sysfs超級(jí)塊sysfs_sb、dentry根目錄root、sysfs_direct根目錄sysfs_root都是在sysfs初始化時(shí)創(chuàng)建。

sysfs_root下的子節(jié)點(diǎn)是添加設(shè)備對(duì)象或?qū)ο髮傩詴r(shí)調(diào)用sysfs_create_dir/ sysfs_create_file創(chuàng)建的,同時(shí)會(huì)申請(qǐng)對(duì)應(yīng)的inode的索引號(hào)s_ino。注意此時(shí)并未創(chuàng)建inode。

inode是在用到的時(shí)候調(diào)用sysfs_get_inode函數(shù)創(chuàng)建并依據(jù)sysfs_sb地址和申請(qǐng)到的s_ino索引計(jì)算散列表位置放入其中。

dentry的子節(jié)點(diǎn)也是需要用的時(shí)候才會(huì)創(chuàng)建。比如open文件時(shí),會(huì)調(diào)用path_walk根據(jù)路徑一層層的查找指定dentry,如果找不到,則創(chuàng)建一個(gè),并調(diào)用父dentry的inode的lookup函數(shù)(sysfs文件系統(tǒng)的為sysfs_lookup)查找對(duì)應(yīng)的子inode填充指定的dentry。

這里有必要介紹一下sysfs_lookup的實(shí)現(xiàn),以保證我們更加清晰地了解這個(gè)過(guò)程,函數(shù)主體如下:

static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)

{

       struct dentry *ret = NULL;

       struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; //獲取父sysfs_direct

       struct sysfs_dirent *sd;

       struct inode *inode;

 

       mutex_lock(&sysfs_mutex);

      

       /* 在父sysfs_direct查找名為dentry->d_name.name的節(jié)點(diǎn) */

       sd = sysfs_find_dirent(parent_sd, dentry->d_name.name);

 

       /* no such entry */

       if (!sd) {

              ret = ERR_PTR(-ENOENT);

              goto out_unlock;

       }

      

       /* 這兒就是通過(guò)sysfs_direct獲取對(duì)應(yīng)的inode,sysfs_get_inode實(shí)現(xiàn)原理上面已經(jīng)介紹過(guò)了 */

       /* attach dentry and inode */

       inode = sysfs_get_inode(sd);

       if (!inode) {

              ret = ERR_PTR(-ENOMEM);

              goto out_unlock;

       }

      

       /* 填充目錄項(xiàng),至此一個(gè)目錄項(xiàng)創(chuàng)建完畢 */

       /* instantiate and hash dentry */

dentry->d_op = &sysfs_dentry_ops;   /* 填充目錄項(xiàng)的操作方法,該方法只提供一釋放inode函數(shù)sysfs_d_iput */

       dentry->d_fsdata = sysfs_get(sd);        //填充sysfs_direct

       d_instantiate(dentry, inode);                 //填充inode

       d_rehash(dentry);                               //將dentry加入hash表

 

 out_unlock:

       mutex_unlock(&sysfs_mutex);

       return ret;

}

sysfs文件open流程

open的主要過(guò)程是通過(guò)指定的路徑找到對(duì)應(yīng)的dentry,并從中獲取inode,然后獲取一個(gè)空的file結(jié)構(gòu),將inode中相關(guān)內(nèi)容賦值給file,這其中包括將inode的fop賦給file的fop。因此接下來(lái)調(diào)用的filp->fop->open其實(shí)就是inode里的fop->open。新的file結(jié)構(gòu)對(duì)應(yīng)一個(gè)文件句柄fd,這會(huì)作為整個(gè)open函數(shù)的返回值。之后的read/write操作就靠這個(gè)fd找到對(duì)應(yīng)的file結(jié)構(gòu)了。

圖3-2是從網(wǎng)上找到的,清晰地描述了file和dentry以及inode之間的關(guān)系:

 

圖3-2:file、dentry、inode關(guān)系

進(jìn)程每打開(kāi)一個(gè)文件,就會(huì)有一個(gè)file結(jié)構(gòu)與之對(duì)應(yīng)。同一個(gè)進(jìn)程可以多次打開(kāi)同一個(gè)文件而得到多個(gè)不同的file結(jié)構(gòu),file結(jié)構(gòu)描述了被打開(kāi)文件的屬性,讀寫的偏移指針等等當(dāng)前信息。

兩個(gè)不同的file結(jié)構(gòu)可以對(duì)應(yīng)同一個(gè)dentry結(jié)構(gòu)。進(jìn)程多次打開(kāi)同一個(gè)文件時(shí),對(duì)應(yīng)的只有一個(gè)dentry結(jié)構(gòu)。dentry結(jié)構(gòu)存儲(chǔ)目錄項(xiàng)和對(duì)應(yīng)文件(inode)的信息。

在存儲(chǔ)介質(zhì)中,每個(gè)文件對(duì)應(yīng)唯一的inode結(jié)點(diǎn),但是,每個(gè)文件又可以有多個(gè)文件名。即可以通過(guò)不同的文件名訪問(wèn)同一個(gè)文件。這里多個(gè)文件名對(duì)應(yīng)一個(gè)文件的關(guān)系在數(shù)據(jù)結(jié)構(gòu)中表示就是dentry和inode的關(guān)系。

inode中不存儲(chǔ)文件的名字,它只存儲(chǔ)節(jié)點(diǎn)號(hào);而dentry則保存有名字和與其對(duì)應(yīng)的節(jié)點(diǎn)號(hào),所以就可以通過(guò)不同的dentry訪問(wèn)同一個(gè)inode。

sysfs文件read/write流程

sysfs與普通文件系統(tǒng)的最大差異是,sysfs不會(huì)申請(qǐng)任何內(nèi)存空間來(lái)保存文件的內(nèi)容。事實(shí)上再不對(duì)文件操作時(shí),文件是不存在的。只有用戶讀或?qū)懳募r(shí),sysfs才會(huì)申請(qǐng)一頁(yè)內(nèi)存(只有一頁(yè)),用于保存將要讀取的文件信息。如果作讀操作,sysfs就會(huì)調(diào)用文件的父對(duì)象(文件夾kobject)的屬性處理函數(shù)kobject->ktype->sysfs_ops->show,然后通過(guò)show函數(shù)來(lái)調(diào)用包含該對(duì)象的外層設(shè)備(或驅(qū)動(dòng)、總線等)的屬性的show函數(shù)來(lái)獲取硬件設(shè)備的對(duì)應(yīng)屬性值,然后將該值拷貝到用戶空間的buff,這樣就完成了讀操作。寫操作也類似,都要進(jìn)行內(nèi)核空間?à用戶空間內(nèi)存的拷貝,以保護(hù)內(nèi)核代碼的安全運(yùn)行。

圖3-1為用戶空間程序讀sysfs文件的處理流程,其他操作類似:

 

圖3-3:用戶空間程序讀sysfs文件的處理流程 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
【轉(zhuǎn)】Linux那些事兒之我是Sysfs(12)舉例三:sysfs讀入文件夾內(nèi)容 - wi...
Linux文件系統(tǒng)之sysfs
從文件 I/O 看 Linux 的虛擬文件系統(tǒng)
從用戶態(tài)的open到內(nèi)核驅(qū)動(dòng)實(shí)現(xiàn)流程
Linux sysfs文件系統(tǒng)實(shí)現(xiàn)之順聊Linux文件系統(tǒng)實(shí)現(xiàn)
1--共享內(nèi)存的實(shí)踐到內(nèi)核--共享內(nèi)存的創(chuàng)建 - 如何從應(yīng)用程序進(jìn)入linux內(nèi)核 - 無(wú)...
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服