日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

對(duì)proc文件系統(tǒng)的分析(三)

 幸福的樂土 2012-01-05
作者:

zmwillow
(journeyman)不知正確與否。

這樣是表示對(duì)作者的尊重。

如果有不對(duì),請(qǐng)通知我,我將即時(shí)更改.

 
五) 對(duì)proc文件的管理
前面我們提過,相對(duì)于其他邏輯文件系統(tǒng)的具體文件組織形式(比如ext2文件系統(tǒng)的 inode),proc文件系統(tǒng)也有自己的組織結(jié)構(gòu),那就是proc_dir_entry結(jié)構(gòu),所有屬于proc文件系統(tǒng)的文件,都對(duì)應(yīng)一個(gè) proc_dir_entry結(jié)構(gòu),并且在VFS需要讀取proc文件的時(shí)候,把這個(gè)結(jié)構(gòu)和VFS的inode建立鏈接(即由 inode->u.generic_ip指向該prc_dir_entry結(jié)構(gòu))。
因此,proc文件系統(tǒng)實(shí)現(xiàn)了一套對(duì)proc_dir_entry結(jié)構(gòu)的管理,下面我們就此進(jìn)行一個(gè)分析。
1 proc_dir_entry結(jié)構(gòu)
首先我們看一下proc_dir_entry結(jié)構(gòu),這個(gè)結(jié)構(gòu)在proc_fs.h中定義:
struct proc_dir_entry {
unsigned short low_ino;
unsigned short namelen;
const char *name;
mode_t mode;
nlink_t nlink;
uid_t uid;
gid_t gid;
unsigned long size;
struct inode_operations * proc_iops;
struct file_operations * proc_fops;
get_info_t *get_info;
struct module *owner;
struct proc_dir_entry *next, *parent, *subdir;
void *data;
read_proc_t *read_proc;
write_proc_t *write_proc;
atomic_t count; /* use count */
int deleted; /* delete flag */
kdev_t rdev;
};
在這個(gè)結(jié)構(gòu)中,描述了一個(gè)proc文件的全部信息,每一個(gè)proc文件正是使用proc_dir_entry結(jié)構(gòu)來表示的。下面我們看一下它最重要的幾個(gè)域:
low_ino:這是用來唯一標(biāo)志proc_dir_entry結(jié)構(gòu)的節(jié)點(diǎn)號(hào),也就是proc文件系統(tǒng)內(nèi)的索引節(jié)點(diǎn)的標(biāo)號(hào),除了根結(jié)點(diǎn),其他的節(jié)點(diǎn)號(hào)都是在創(chuàng)建proc_dir_entry的時(shí)候,由make_inode_number()動(dòng)態(tài)創(chuàng)建的。
name:即這個(gè)proc文件的名字。
mode: 該proc文件的模式由兩部分用位或運(yùn)算組成,第一部分是文件的類型,可以參考include/linux/stat.h中的定義,比如,S_IFREG 表示普通文件,而S_IFDIR表示目錄文件。第二部分是該文件的權(quán)限,同樣可以參考include/linux/stat.h中的定義,比 如,S_IRUSR表示該文件能夠被擁有者讀,S_IROTH 表示該文件可以被其他人讀取。但真正的權(quán)限檢查,我們可以放到后面提到的inode_operations結(jié)構(gòu)中。
size:即我們使用“l(fā)s”命令時(shí),所顯示出的文件大小。
proc_iops: 這是一個(gè)inode_operations結(jié)構(gòu),其中設(shè)置了針對(duì)這個(gè)proc索引節(jié)點(diǎn)的操作函數(shù),這樣,我們就可以針對(duì)不同類型的proc文件,提供不同 的方法,以完成不同的工作。比如我們上面提到的對(duì)proc文件的權(quán)限檢查,就可以放在這個(gè)結(jié)構(gòu)中。
proc_fops:這是一個(gè)file_operations結(jié)構(gòu),其中放置了針對(duì)這個(gè)proc文件的操作函數(shù),我們可以把對(duì)proc文件的讀寫操作,放在這個(gè)結(jié)構(gòu)中,用以實(shí)現(xiàn)對(duì)/proc目錄中的文件的讀,寫功能。
get_info:當(dāng)用戶向proc文件讀取的數(shù)據(jù)小于一個(gè)頁面大小時(shí),可以使用這個(gè)函數(shù)向用戶返回?cái)?shù)據(jù)。
struct proc_dir_entry *next, *parent, *subdir:使用這些鏈表,在內(nèi)存中,proc_dir_entry結(jié)構(gòu)就以樹的形式鏈接在一起。
read_proc_t *read_proc 和write_proc_t *write_proc:這兩個(gè)函數(shù)提供了對(duì)proc文件進(jìn)行操作的簡單接口。我們知道,對(duì)于proc文件,我們可以從中讀取核心數(shù)據(jù),還可以向其中寫入 數(shù)據(jù),因此,對(duì)于一些功能比較簡單的proc文件,我們只要實(shí)現(xiàn)這兩個(gè)函數(shù)(或其中之一)即可,而不用設(shè)置inode_operations結(jié)構(gòu),這樣, 整個(gè)操作比較簡單。實(shí)際上,我們會(huì)在后面的分析中看到,在注冊(cè)proc文件的時(shí)候,會(huì)自動(dòng)為proc_fops設(shè)置一個(gè)缺省的 file_operations結(jié)構(gòu),如果我們只實(shí)現(xiàn)了上面提到的兩個(gè)讀寫操作,而沒有設(shè)置自己file_operations結(jié)構(gòu),那么,會(huì)由缺省的 inode_operations結(jié)構(gòu)中的讀寫函數(shù)檢查調(diào)用這兩個(gè)函數(shù)。
atomic_t count:該結(jié)構(gòu)的使用計(jì)數(shù)。當(dāng)一個(gè)proc_dir_entry結(jié)構(gòu)的count減為零時(shí),會(huì)釋放該結(jié)構(gòu),這種結(jié)果就像把一個(gè)ext2文件系統(tǒng)的文件從磁盤上刪除掉一樣。
int deleted:這是一個(gè)刪除標(biāo)志,當(dāng)我們調(diào)用remove_proc_entry函數(shù)要?jiǎng)h除一個(gè)proc_dir_entry時(shí),如果發(fā)現(xiàn)該結(jié)構(gòu)還在使用,就會(huì)設(shè)置該標(biāo)志并且推出。
2 建立proc文件
在了解了proc_dir_entry結(jié)構(gòu)之后,我們來看一看proc文件系統(tǒng)是如何管理自己的文件結(jié)構(gòu)的。
首先我們看一看它是如何創(chuàng)建proc文件的,參考文件fs/proc/generic.c,其中,有一個(gè)函數(shù)create_proc_entry,由它創(chuàng)建并注冊(cè)proc文件,下面我們看一下它的源碼:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
{
struct proc_dir_entry *ent = NULL;
const char *fn = name;
int len;

if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
goto out;
len = strlen(fn);

ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
if (!ent)
goto out;
memset(ent, 0, sizeof(struct proc_dir_entry));
memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
ent->name = ((char *) ent) + sizeof(*ent);
ent->namelen = len;

if (S_ISDIR(mode)) {
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO | S_IXUGO;
ent->proc_fops = &proc_dir_operations;
ent->proc_iops = &proc_dir_inode_operations;
ent->nlink = 2;
} else {
if ((mode & S_IFMT) == 0)
mode |= S_IFREG;
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO;
ent->nlink = 1;
}
ent->mode = mode;

proc_register(parent, ent); /* link ent to parent */

out:
return ent;
}
我 們看到,首先,該函數(shù)會(huì)做一些必要的檢查,比如要確保它的父節(jié)點(diǎn)必須存在等等。其次會(huì)創(chuàng)建一個(gè)proc_dir_entry結(jié)構(gòu),并且為該文件的名字也分 配空間,并用->name指向它。再次,會(huì)根據(jù)該文件的類型,設(shè)置適當(dāng)?shù)哪J胶玩溄訑?shù)。最后,會(huì)調(diào)用proc_register(parent, ent)函數(shù),將這個(gè)結(jié)構(gòu)鏈接到proc文件樹中。
下面我們看一下它的實(shí)現(xiàn)代碼:
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
int i;
i = make_inode_number();
if (i < 0)
return -EAGAIN;
dp->low_ino = i;
dp->next = dir->subdir;
dp->parent = dir;
dir->subdir = dp;
if (S_ISDIR(dp->mode)) {
if (dp->proc_iops == NULL) {
dp->proc_fops = &proc_dir_operations;
dp->proc_iops = &proc_dir_inode_operations;
}
dir->nlink++;
} else if (S_ISLNK(dp->mode)) {
if (dp->proc_iops == NULL)
dp->proc_iops = &proc_link_inode_operations;
} else if (S_ISREG(dp->mode)) {
if (dp->proc_fops == NULL)
dp->proc_fops = &proc_file_operations;
}
return 0;
}
這 個(gè)函數(shù)主要完成三部分的工作,第一,使用make_inode_number()函數(shù)動(dòng)態(tài)的到一個(gè)節(jié)點(diǎn)號(hào),并且設(shè)置low_ino。第二步,將這個(gè) proc_dir_entry結(jié)構(gòu)鏈接到它的父節(jié)點(diǎn)上。第三步,根據(jù)文件類型的不同,設(shè)置不同的(索引節(jié)點(diǎn)和文件)缺省操作函數(shù)集。
這樣,一個(gè)proc文件就注冊(cè)成功了。
3 刪除proc文件
在同一源文件中,提供了刪除proc_dir_entry結(jié)構(gòu)的函數(shù),即remove_proc_entry,下面我們分析一下它的實(shí)現(xiàn)過程。
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
struct proc_dir_entry **p;
struct proc_dir_entry *de;
const char *fn = name;
int len;

if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
goto out;
len = strlen(fn);
for (p = &parent->subdir; *p; p=&(*p)->next ) {
if (!proc_match(len, fn, *p))
continue;
de = *p;
*p = de->next;
de->next = NULL;
if (S_ISDIR(de->mode))
parent->nlink--;
clear_bit(de->low_ino-PROC_DYNAMIC_FIRST,
(void *) proc_alloc_map);
proc_kill_inodes(de);
de->nlink = 0;
if (!atomic_read(&de->count))
free_proc_entry(de);
else {
de->deleted = 1;
printk("remove_proc_entry: %s/%s busy, count=%d\n",
parent->name, de->name, atomic_read(&de->count));
}
break;
}
out:
return;
}
該函數(shù)在參數(shù)parent的所有孩子中查找指定的名字,如果找到匹配的節(jié)點(diǎn),即proc_match(len, fn, *p),那么,就將該結(jié)構(gòu)從樹結(jié)構(gòu)中去掉。然后,如果刪除的proc_dir_entry是目錄結(jié)構(gòu),那么,就減少其父節(jié)點(diǎn)的鏈接數(shù)。
然后,調(diào)用clear_bit(de->low_ino-PROC_DYNAMIC_FIRST, (void *) proc_alloc_map)函數(shù),清除該節(jié)點(diǎn)號(hào)。
最后,將該結(jié)構(gòu)的鏈接數(shù)置零,并調(diào)用atomic_read(&de->count)來檢查它的引用計(jì)數(shù),如果是零,那么就使用函數(shù)free_proc_entry釋放該節(jié)點(diǎn),否則,就將它的刪除標(biāo)記位置一,在以后適當(dāng)?shù)貦C(jī)會(huì)中,再將其釋放。
4 其他管理函數(shù)
除此之外,我們看到還有一些函數(shù),可以方便我們管理和使用proc文件系統(tǒng),我們簡單地介紹一下:
struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)函數(shù),這個(gè)函數(shù)用來在proc文件系統(tǒng)中注冊(cè)一個(gè)子目錄,根據(jù)它的參數(shù),我們就可以看出它的功能。在這個(gè)函數(shù)里,將動(dòng)態(tài)分配一個(gè) proc_dir_entry結(jié)構(gòu)以及它的名字,然后,設(shè)置目錄文件的缺省操作(proc_iops以及proc_fops)以及nlink值,最后,調(diào) 用proc_register函數(shù)將其注冊(cè)。
struct proc_dir_entry *proc_mknod(const char *name, mode_t mode, struct proc_dir_entry *parent, kdev_t rdev)函數(shù),用來在proc文件系統(tǒng)中建立一個(gè)設(shè)備文件,因此,在創(chuàng)建proc_dir_entry結(jié)構(gòu)后,沒有設(shè)置缺省操作,而是使用 ->rdev = rdev指定了設(shè)備。最后,調(diào)用proc_register函數(shù)將其注冊(cè)。
struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest)函數(shù),該函數(shù)創(chuàng)建了一個(gè)鏈接文件,使用->mode = S_IFLNK|S_IRUGO|S_IWUGO|S_IXUGO來標(biāo)志,它和其他文件的建立很相似,只是,它將鏈接的目標(biāo)文件名放在了 ->data域中。最后,它同樣調(diào)用proc_register函數(shù)將該結(jié)構(gòu)注冊(cè)。

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多