http://blog.csdn.net/dndxhej/article/details/7434615 對sysfs和設備模型有瞭解的都會知道sysfs實際是為了將設備模型導出到用戶空間的一個記憶體文件系統。 設備模型的關鍵結構體kobject會組成設備模型的樹形結構,而sysfs的關鍵結構體sys ...
http://blog.csdn.net/dndxhej/article/details/7434615
對sysfs和設備模型有瞭解的都會知道sysfs實際是為了將設備模型導出到用戶空間的一個記憶體文件系統。
設備模型的關鍵結構體kobject會組成設備模型的樹形結構,而sysfs的關鍵結構體sysfs_dirent也是類似的樹形的結構,vfs中的dentry同樣是類似的樹形結構。
sysfs目錄文件的創建都是由設備模型的上層構件(bus device driver class)在註冊的時候調用它們內含的kobject(設備模型的底層基石)的添加註冊操作,而kobject的操作就調用sysfs文件系統的具體操作。
這些結構體是有聯繫的,但這一次我們先不過度關註他們的聯繫,僅僅對sysfs下目錄和文件的創建做個分析:
kobject結構體:
1 struct kobject { 2 const char *name; 3 struct list_head entry; 4 struct kobject *parent; 5 struct kset *kset; 6 struct kobj_type *ktype; 7 struct sysfs_dirent *sd; 8 struct kref kref; 9 unsigned int state_initialized:1; 10 unsigned int state_in_sysfs:1; 11 unsigned int state_add_uevent_sent:1; 12 unsigned int state_remove_uevent_sent:1; 13 unsigned int uevent_suppress:1; 14 };
sysfs_dirent結構中的union有四項:目錄(s_dir)、鏈接文件(s_symlink),屬性文件(s_attr)和二進位屬性文件(s_bin_attr)。
struct sysfs_dirent { atomic_t s_count; atomic_t s_active; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif struct sysfs_dirent *s_parent; struct sysfs_dirent *s_sibling; const char *s_name; union { struct sysfs_elem_dir s_dir; struct sysfs_elem_symlink s_symlink; struct sysfs_elem_attr s_attr; struct sysfs_elem_bin_attr s_bin_attr; }; unsigned int s_flags; unsigned short s_mode; ino_t s_ino; struct sysfs_inode_attrs *s_iattr; };
我們vfs中有inode和entry兩種關鍵的對象,在很多文件系統的設計中,都會有類似omfs_inode和omfs_extent_entry等等結構體來抽象表明具體文件系統的節點和目錄項。
而在sysfs中,不管是目錄還是文件,都用同一個結構體sysfs_dirent來表示,這個結構體可以說是inode和dentry的綜合,因為有:
1 unsignedint s_flags; 2 unsignedshort s_mode; 3 ino_t s_ino;
等類似於inode的內容,也有:
1 structsysfs_dirent *s_parent; 2 structsysfs_dirent *s_sibling; 3 constchar *s_name;
等類似於dentry的內容。
總的來說,sysfs_dirent結構體是sysfs和kobject建立連接的橋梁。
我們知道,kobject對應於sysfs下的一個目錄:
1 structsysfs_elem_dir { 2 structkobject *kobj; 3 /*children list starts here and goes through sd->s_sibling */ 4 structsysfs_dirent *children; 5 };
上面的結構體緊密的將kobject和sysfs_dirent聯繫起來。kobject代表目錄,而對於代表目錄的sysfs_dirent,內嵌的sysfs_elem_dir有kobject的指針,所以kobject和sysfs_dirent是你中有我,我中有你。
不過對於文件就不一樣了,因為文件也有自己的sysfs_dirent,而文件並沒有自己的kobject。
在普通的文件系統中,比如omfs中,建立一個目錄的話,首先會從物理存儲介質(磁碟)中讀取相關信息填充omfs下的omfs_inode結構體,然後會建立vfs層的inode和dentry等結構體。
而在sysfs中,在建立目錄和文件時,只會通過sysfs_dirent結構體來建立目錄文件的層次結構,而看不到vfs中的dentry、inode。既然是linux下的文件系統,不管多麼特殊,肯定要有inode和dentry的,sysfs文件系統也不例外,只不過sysfs將建立inode和dentry的操作推到sysfs_lookup函數中來做,在sysfs_lookup中還會建立dentry與sysfs_dirtnt的關係。dentry->d_fsdata= sysfs_get(sd);
其實這個關係,在sysfs_fill_super就有體現:root->d_fsdata= &sysfs_root;
1 struct sysfs_dirent sysfs_root = { 2 .s_name = "", 3 .s_count = ATOMIC_INIT(1), 4 .s_flags = SYSFS_DIR, 5 .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 6 .s_ino = 1, 7 };
這個sysfs_root就是sysfs_dirent層次結構中的根。
下麵是sysfs創建目錄的過程,註意的是這個過程只能通過kobject的操作來實現,在/sys下用mkdir是沒作用的:
1 int sysfs_create_dir(struct kobject * kobj) 2 { 3 struct sysfs_dirent *parent_sd, *sd; 4 int error = 0; 5 6 BUG_ON(!kobj); 7 8 if (kobj->parent) 9 parent_sd = kobj->parent->sd; 10 else 11 parent_sd = &sysfs_root; 12 13 error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); 14 if (!error) 15 kobj->sd = sd; 16 return error; 17 }
1 static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, 2 const char *name, struct sysfs_dirent **p_sd) 3 { 4 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 5 struct sysfs_addrm_cxt acxt; 6 struct sysfs_dirent *sd; 7 int rc; 8 9 /* allocate */ 10 sd = sysfs_new_dirent(name, mode, SYSFS_DIR); //初始化sysfs_dirent結構體 11 if (!sd) 12 return -ENOMEM; 13 sd->s_dir.kobj = kobj; //sysfs_dirent與kobject的聯繫建立 14 15 /* link in */ 16 sysfs_addrm_start(&acxt, parent_sd); 17 rc = sysfs_add_one(&acxt, sd); 18 sysfs_addrm_finish(&acxt); 19 20 if (rc == 0) 21 *p_sd = sd; 22 else 23 sysfs_put(sd); 24 return rc; 25 }
在sysfs_add_one是層次關係的建立:
1 int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) 2 { 3 struct sysfs_inode_attrs *ps_iattr; 4 5 if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) 6 return -EEXIST; 7 8 sd->s_parent = sysfs_get(acxt->parent_sd); //建立上下層次間的父子關係 9 10 sysfs_link_sibling(sd); //建立同一層次的兄弟關係 11 12 /* Update timestamps on the parent */ 13 ps_iattr = acxt->parent_sd->s_iattr; 14 if (ps_iattr) { 15 struct iattr *ps_iattrs = &ps_iattr->ia_iattr; 16 ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; 17 } 18 19 return 0; 20 }
在sysfs_link_sibling中關鍵代碼:
1 for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { 2 if (sd->s_ino < (*pos)->s_ino) 3 break; 4 }
根據s_ino從小到大的順序組成一個鏈。附上一個圖,這個關係就一目瞭然:
從這個圖可以很清楚的看到sysfs中sysfs_dirent架成的樹形結構(註意他們的s_ino排列),這個結構和kobject,dentry的樹形結構幾乎一致,因為他們是有聯繫的,後面我們會一步步理清他們的聯繫,到時侯就明白sysfs是如何將設備模型(kobject)倒成文件系統的。