久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

【轉(zhuǎn)】Linux那些事兒之我是Sysfs(12)舉例三:sysfs讀入文件夾內(nèi)容 - wi...

 蝸牛an 2010-12-10

【轉(zhuǎn)】Linux那些事兒之我是Sysfs(12)舉例三:sysfs讀入文件夾內(nèi)容

linux kernel 2009-07-14 16:33:26 閱讀77 評論0   字號: 訂閱

上 回我們說到,如何創(chuàng)建文件夾和文件,。我們發(fā)現(xiàn),,在sysfs中,inode并不那么重要。這是因為我們所要讀寫的信息已經(jīng)就在內(nèi)存中,,并且已經(jīng)形成了層次結(jié)構(gòu),。我們只需有dentry,,就可以dentry->fsdata,就能找到我們讀些信息的來源 ---  sysfs_dirent結(jié)構(gòu),。這也是我覺得有必要研究 sysfs的原因之一,,因為它簡單,而且不涉及具體的硬件驅(qū)動,,但是從這個過程中,,我們可以把文件系統(tǒng)中的一些基本數(shù)據(jù)結(jié)構(gòu)搞清楚。接下來,,我以讀取 sysfs文件和文件夾的內(nèi)容為例子,,講講文件讀的流程。那么關(guān)于寫,,還有關(guān)于symblink的東西完全可以以此類推了,。

我們新建文件夾時,設(shè)置了
 inode->i_op = &sysfs_dir_inode_operations;
 inode->i_fop = &sysfs_dir_operations;

struct file_operations sysfs_dir_operations = {
        .open = sysfs_dir_open,
        .release = sysfs_dir_close,
        .llseek = sysfs_dir_lseek,
        .read = generic_read_dir,
        .readdir = sysfs_readdir,
};

用一個簡短的程序來做實驗,。

#include<sys/types.h>
#include
<dirent.h>
#include
<unistd.h>
int main()...{
              DIR 
* dir;
              
struct dirent *ptr;
              dir 
= opendir("/sys/bus/");
              
while((ptr = readdir(dir))!=NULL)...{
                            printf(
"d_name :%s ",ptr->d_name);
              }

              closedir(dir);
              
return -1;
}

在用戶空間,,用gcc編譯執(zhí)行即可。我們來看看它究竟做了什么,。

(1)sysfs_dir_open()

這 是個用戶空間的程序,。opendir()是glibc的函數(shù),glibc也就是著名的標準c庫,。至于opendir ()是如何與sysfs dir open ()接上頭的,,那還得去看glibc的代碼。我就不想分析了...glibc可以從gnu的網(wǎng)站上自己下載源代碼,,編譯,。再用gdb調(diào)試,就可以看得跟清楚,。
函數(shù)流程如下:
opendir("/sys/bus/") -> /*用戶空間*/
-> 系統(tǒng)調(diào)用->
sys_open() -> filp_open()-> dentry_open() -> sysfs_dir_open()/*內(nèi)核空間*/

static int sysfs_dir_open(struct inode *inode, struct file *file)
...{
            
struct dentry * dentry = file->f_dentry;
            
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
            down(
&dentry->d_inode->i_sem);
            file
->private_data = sysfs_new_dirent(parent_sd, NULL);
            up(
&dentry->d_inode->i_sem);
            
return file->private_data ? 0 : -ENOMEM;
}

內(nèi)核空間:新建一個dirent結(jié)構(gòu),,連入父輩的dentry中,,并將它地址保存在file->private_data中。這個dirent的具體作用待會會講,。
用戶空間:新建了一個DIR結(jié)構(gòu),,DIR結(jié)構(gòu)如下。

#define __dirstream DIR
struct __dirstream
{
             int fd; /* File descriptor. */
             char *data; /* Directory block. */
             size_t allocation; /* Space allocated for the block. */
             size_t size; /* Total valid data in the block. */
             size_t offset; /* Current offset into the block. */
             off_t filepos; /* Position of next entry to read. */
             __libc_lock_define (, lock) /* Mutex lock for this structure. */
};

(2)sysfs_readdir()

流程如下:


readdir(dir) -> getdents() ->/*用戶空間*/
-> 系統(tǒng)調(diào)用->
sys32 readdir() -> vfs readdir() -> sysfs readdir()/*內(nèi)核空間*/

readdir(dir)這個函數(shù)有點復(fù)雜,,雖然在main函數(shù)里的while循環(huán)中,,readdir被執(zhí)行了多次,我們看看glibc里面的代碼

readdir(dir)...{
                ......
                
if (dirp->offset >= dirp->size)...{
                ......
                getdents()
                ......
                }

......
}

實 際上,,getdents() -> ... -> sysfs_readdir()只被調(diào)用了兩次,,getdents()一次就把所有的內(nèi)容都讀完,存在DIR結(jié)構(gòu)當中,,readdir()只是從DIR結(jié)構(gòu)當中每次取出一個,。DIR(dirstream)結(jié)構(gòu)就是一個流。而回調(diào)函數(shù)filldir的作用就是往這個流中填充數(shù)據(jù),。第二次調(diào)用getdents ()是用戶把DIR里面的內(nèi)容讀完了,,所以它又調(diào)用getdents()但是這次getdents()回返回NULL。

static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
...{
             
struct dentry *dentry = filp->f_dentry;
             
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
             
struct sysfs_dirent *cursor = filp->private_data;
             
struct list_head *p, *= &cursor->s_sibling;
             ino_t ino;
             
int i = filp->f_pos;
             
switch (i) ...{
                          
case 0:
                          ino 
= dentry->d_inode->i_ino;
                          
if (filldir(dirent, "."1, i, ino, DT_DIR) < 0)
                                       
break;
                          filp
->f_pos++;
                          i
++;
                          
/**//* fallthrough */
                          
case 1:
                          ino 
= parent_ino(dentry);
                          
if (filldir(dirent, ".."2, i, ino, DT_DIR) < 0)
                                       
break;
                          filp
->f_pos++;
                          i
++;
                          
/**//* fallthrough */
                          
default:
                          
if (filp->f_pos == 2...{
                                       list_del(q);
                                       list_add(q, 
&parent_sd->s_children);
                          }

                          
for (p=q->next; p!= &parent_sd->s_children; p=p->next) ...{
                                       
struct sysfs_dirent *next;
                                       
const char * name;
                                       
int len;
                                       next 
= list_entry(p, struct sysfs_dirent, s_sibling);
                                       
if (!next->s_element)
                                                    
continue;
                                       name 
= sysfs_get_name(next);
                                       len 
= strlen(name);
                                       
if (next->s_dentry)
                                                    ino 
= next->s_dentry->d_inode->i_ino;
                                       
else
                                                    ino 
= iunique(sysfs_sb, 2);
                                       
if (filldir(dirent, name, len, filp->f_pos, ino,dt_type(next)) < 0)
                                                    
return 0;
                                       list_del(q);
                                       list_add(q, p);
                                       p 
= q;
                                       filp
->f_pos++;
                          }

             }

return 0;
}

看sysfs_readdir ()其實很簡單,,它就是從我們調(diào)用sysfs_dir_open()時新建的一個sysfs_dirent結(jié)構(gòu)開始,,便利當前dentry-> dirent下的所有子sysfs_dirent結(jié)構(gòu)。讀出名字,,再回調(diào)函數(shù)filldir()將文件名,,文件類型等信息,按照一定的格式寫入某個緩沖區(qū),。

一個典型的filldir()就是filldir64(),,它的作用的按一定格式向緩沖區(qū)寫數(shù)據(jù),再把數(shù)據(jù)復(fù)制到用戶空間去,。

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多