1. 程式人生 > >linux之configfs簡介和程式設計入門

linux之configfs簡介和程式設計入門

一、什麼是configfs 是一種基於ram的檔案系統 二、configfs有什麼用處 在使用者空間配置核心物件 三、configfs VS ioctl configfs可直接察看,通過使用者態目錄檔案訪問介面,適用於核心物件有眾多複雜的配置。 四、configs VS sysfs configfs可以在使用者態建立和刪除核心物件。 五、什麼時候用configfs 當核心需要很多引數需要配置時;當需要動態建立核心物件並且核心物件需要修改配置時; 不想寫使用者態程式和ioctl時,寫shell指令碼就可以直接配置configfs。 六、怎麼知道系統上是否已經安裝了configfs,安裝在哪個目錄 執行如下命令,可以看到安裝目錄為/sys/kernel/config cat /proc/mounts | grep configfs  configfs /sys/kernel/config configfs rw,relatime 0 0 七、configfs組織結構是怎麼樣的 頂層結構是struct configfs_subsystem,為configfs子系統結構,接著是struct config_group,是configfs目錄和屬性的容器,struct config_item是configfs目錄,代表可配置的核心物件,struct configfs_attribute是目錄下面的屬性。 八、程式碼示例(來自核心目錄Documentation\filesystems\configfs) 介紹程式碼之前,先過一下基本的資料結構: [cpp]
view plain copy
  1. 240struct configfs_subsystem {  
  2. 241     struct config_group     su_group;  
  3. 242     struct mutex          su_mutex;  
  4. 243};  
configfs子系統,config_group是抽象容器,之所以叫容器,是因為容器中可以包括config_item,還可以遞迴包含config_group。struct mutex是用於子系統訪問控制的。 [cpp] view plain copy
  1. 89/** 
  2. 90 *     group - a group of config_items of a specific type, belonging
     
  3. 91 *     to a specific subsystem. 
  4. 92 */  
  5. 93struct config_group {  
  6. 94     struct config_item          cg_item;  
  7. 95     struct list_head          cg_children;  
  8. 96     struct configfs_subsystem      *cg_subsys;  
  9. 97     struct config_group          **default_groups;  
  10. 98};  

config_group作為幕後主使,是不輕易出現在臺前的。所以有了94行的struct config_item來表現為一個目錄。 [cpp] view plain copy
  1. 56struct config_item {  
  2. 57     char               *ci_name;  
  3. 58     char               ci_namebuf[CONFIGFS_ITEM_NAME_LEN];  
  4. 59     struct kref          ci_kref;  
  5. 60     struct list_head     ci_entry;  
  6. 61     struct config_item     *ci_parent;  
  7. 62     struct config_group     *ci_group;  
  8. 63     struct config_item_type     *ci_type;  
  9. 64     struct dentry          *ci_dentry;  
  10. 65};  

58行為目錄名稱。 63行為目錄下屬性和屬性操作,屬性表現為目錄下的文字檔案。 [cpp] view plain copy
  1. 82struct config_item_type {  
  2. 83     struct module                    *ct_owner;  
  3. 84     struct configfs_item_operations          *ct_item_ops;  
  4. 85     struct configfs_group_operations     *ct_group_ops;  
  5. 86     struct configfs_attribute          **ct_attrs;  
  6. 87};  

84行為屬性操作方法,操作物件是86行屬性。 85行為目錄操作方法,可以在當前目錄下建立item或group。 86行為當前目錄屬性陣列。 [cpp] view plain copy
  1. 124struct configfs_attribute {  
  2. 125     const char          *ca_name;  
  3. 126     struct module           *ca_owner;  
  4. 127     umode_t               ca_mode;  
  5. 128};  

屬性非常簡單,有屬性名稱、所屬模組和訪問許可權。
示例1:建立一個最簡單的configfs目錄和可讀寫的屬性 建立目錄01-childless,下面有三個屬性,其中屬性storeme為可寫。 # ll /sys/kernel/config/01-childless/
-r--r--r--. 1 root root 4096 Sep 27 05:16 description
-r--r--r--. 1 root root 4096 Sep 27 05:16 showme
-rw-r--r--. 1 root root 4096 Sep 27 05:16 storeme
[cpp] view plain copy
  1. 37/* 
  2. 38 * 01-childless 
  3. 39 * 
  4. 40 * This first example is a childless subsystem.  It cannot create 
  5. 41 * any config_items.  It just has attributes. 
  6. 42 * 
  7. 43 * Note that we are enclosing the configfs_subsystem inside a container. 
  8. 44 * This is not necessary if a subsystem has no attributes directly 
  9. 45 * on the subsystem.  See the next example, 02-simple-children, for 
  10. 46 * such a subsystem. 
  11. 47 */  
  12. 48  
  13. 49struct childless {  
  14. 50     struct configfs_subsystem subsys;  
  15. 51     int showme;  
  16. 52     int storeme;  
  17. 53};  

建立一個結構體包含了configfs子系統,兩個屬性showme, storeme放在了這裡。 雖然註釋裡說明了為什麼把這兩個屬性放這裡,但還是沒太理解,既然屬性description可以放子系統下,為什麼其他兩個屬性不行呢?有誰知道的告知一下。 子系統定義如下: [cpp] view plain copy
  1. 138static struct childless childless_subsys = {  
  2. 139     .subsys = {  
  3. 140          .su_group = {  
  4. 141               .cg_item = {  
  5. 142                    .ci_namebuf = "01-childless",  
  6. 143                    .ci_type = &childless_type,  
  7. 144               },  
  8. 145          },  
  9. 146     },  
  10. 147};  

142行,定義目錄名稱。 143行,定義屬性和操作。 接著看屬性和操作的定義: [cpp] view plain copy
  1. 114CHILDLESS_ATTR_RO(showme, childless_showme_read);  
  2. 115CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,  
  3. 116            childless_storeme_write);  
  4. 117CHILDLESS_ATTR_RO(description, childless_description_read);  
  5. 118  
  6. 119static struct configfs_attribute *childless_attrs[] = {  
  7. 120     &childless_attr_showme.attr,  
  8. 121     &childless_attr_storeme.attr,  
  9. 122     &childless_attr_description.attr,  
  10. 123     NULL,  
  11. 124};  
  12. 125  
  13. 126CONFIGFS_ATTR_OPS(childless);  
  14. 127static struct configfs_item_operations childless_item_ops = {  
  15. 128     .show_attribute          = childless_attr_show,  
  16. 129     .store_attribute     = childless_attr_store,  
  17. 130};  
  18. 131  
  19. 132static struct config_item_type childless_type = {  
  20. 133     .ct_item_ops     = &childless_item_ops,  
  21. 134     .ct_attrs     = childless_attrs,  
  22. 135     .ct_owner     = THIS_MODULE,  
  23. 136};  

133行,屬性操作定義在128行和129行,這兩個函式又是由126行巨集定義的。126行巨集依賴一個函式to_##_item,其中_item是巨集的傳入引數,這個函式的作用是從struct config_item轉換到第49行的結構,然後作為函式show_attribute和store_attribute的傳入引數。 134行,關聯了屬性陣列,屬性陣列在119行定義,第120-122行屬性又分別在114-117行定義。 一切準備就緒之後,在模組初始化地方呼叫子系統註冊函式之後,就可以在/sys/kernel/config/下看到建立了子系統了。 [cpp] view plain copy
  1. 407static int __init configfs_example_init(void)  
  2. 408{  
  3. 409     int ret;  
  4. 410     int i;  
  5. 411     struct configfs_subsystem *subsys;  
  6. 412  
  7. 413     for (i = 0; example_subsys[i]; i++) {  
  8. 414          subsys = example_subsys[i];  
  9. 415  
  10. 416          config_group_init(&subsys->su_group);  
  11. 417          mutex_init(&subsys->su_mutex);  
  12. 418          ret = configfs_register_subsystem(subsys);  
  13. 419          if (ret) {  
  14. 420               printk(KERN_ERR "Error %d while registering subsystem %s\n",  
  15. 421                      ret,  
  16. 422                      subsys->su_group.cg_item.ci_namebuf);  
  17. 423               goto out_unregister;  
  18. 424          }  
  19. 425     }  
  20. 426  
  21. 427     return 0;  

416-417行,初始化子系統。 418行,註冊子系統。 這裡做個小結: 1、建立子系統struct configfs_subsystem 2、建立子系統下config_item_type,對應位置configfs_subsystem->config_group->config_item->config_item_type 3、建立config_item_type對應的屬性陣列和操作,操作主要是show_attribute和store_attribute 4、註冊子系統configfs_register_subsystem
示例2:建立一個configfs目錄,使用者空間可建立目錄(新的核心物件) 首先是定義configfs子系統, [cpp] view plain copy
  1. 304static struct configfs_subsystem simple_children_subsys = {  
  2. 305     .su_group = {  
  3. 306          .cg_item = {  
  4. 307               .ci_namebuf = "02-simple-children",  
  5. 308               .ci_type = &simple_children_type,  
  6. 309          },  
  7. 310     },  
  8. 311};  

接著定義config_item_type, [cpp] view plain copy
  1. 289/* 
  2. 290 * Note that, since no extra work is required on ->drop_item(), 
  3. 291 * no ->drop_item() is provided. 
  4. 292 */  
  5. 293static struct configfs_group_operations simple_children_group_ops = {  
  6. 294     .make_item     = simple_children_make_item,  
  7. 295};  
  8. 296  
  9. 297static struct config_item_type simple_children_type = {  
  10. 298     .ct_item_ops     = &simple_children_item_ops,  
  11. 299     .ct_group_ops     = &simple_children_group_ops,  
  12. 300     .ct_attrs     = simple_children_attrs,  
  13. 301     .ct_owner     = THIS_MODULE,  
  14. 302};  

298行,定義了子系統根目錄屬性操作,跟示例1類似 300行,定義了子系統根目錄屬性,跟示例1類似 299行,這裡新增加了configfs_group_operations,具體定義在293行,繼續跟進294行函式simple_children_make_item [cpp] view plain copy
  1. 232struct simple_children {  
  2. 233     struct config_group group;  
  3. 234};  
  4. 235  
  5. 236static inline struct simple_children *to_simple_children(struct config_item *item)  
  6. 237{  
  7. 238     return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;  
  8. 239}  
  9. 240  
  10. 241static struct config_item *simple_children_make_item(struct config_group *group, const char *name)  
  11. 242{  
  12. 243     struct simple_child *simple_child;  
  13. 244  
  14. 245     simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);  
  15. 246     if (!simple_child)  
  16. 247          return ERR_PTR(-ENOMEM);  
  17. 248  
  18. 249     config_item_init_type_name(&simple_child->item, name,  
  19. 250                       &simple_child_type);  
  20. 251  
  21. 252     simple_child->storeme = 0;  
  22. 253  
  23. 254     return &simple_child->item;  
  24. 255}  
241行,定義了configfs_group_operations->make_item操作,返回值是新建立的struct config_item,傳入引數是struct config_group,即是指定config_group下建立config_item項,這就意味著在該子系統(i.e /sys/kernel/config/02-simple-children)下執行命令mkdir,最終會執行到這個函式。 那執行mkdir 之後,會生成一個怎樣的新目錄呢? 249行,當呼叫mkdir時,這時就呼叫config_item_init_type_name初始化這個config_item,接著看250行的simple_child_type到底定義了怎麼一個item型別? [cpp] view plain copy
  1. 171static struct configfs_attribute simple_child_attr_storeme = {  
  2. 172     .ca_owner = THIS_MODULE,  
  3. 173     .ca_name = "storeme",  
  4. 174     .ca_mode = S_IRUGO | S_IWUSR,  
  5. 175};  
  6. 176  
  7. 177static struct configfs_attribute *simple_child_attrs[] = {  
  8. 178     &simple_child_attr_storeme,  
  9. 179     NULL,  
  10. 180};  
  11. 219static struct configfs_item_operations simple_child_item_ops = {  
  12. 220     .release          = simple_child_release,  
  13. 221     .show_attribute          = simple_child_attr_show,  
  14. 222     .store_attribute     = simple_child_attr_store,  
  15. 223};  
  16. 224  
  17. 225static struct config_item_type simple_child_type = {  
  18. 226     .ct_item_ops     = &simple_child_item_ops,  
  19. 227     .ct_attrs     = simple_child_attrs,  
  20. 228     .ct_owner     = THIS_MODULE,  
  21. 229};  

225行,定義了config_item_type。 227行,先看屬性,simple_child_attrs定義在177行,只有一個屬性,這個屬性定義在171行,仔細看一下這個屬性,有可讀寫的。 所以經過mkdir之後,該目錄下就自動生成一個名字為storeme的屬性,其對應的操作定義在219行。具體如下: # cd /sys/kernel/config/02-simple-children/
# ls
description # mkdir test # ll
-r--r--r--. 1 root root 4096 Sep 28 21:24 description
drwxr-xr-x. 2 root root    0 Sep 28 21:24 test
# tree
.
|-- description
`-- test
    `-- storeme
1 directory, 2 files
# cat test/storeme 
0
# echo 1 > test/storeme 
# cat test/storeme 
1

示例3:建立group 之前我們講過,config_group是可以巢狀的,那麼現在就來看一下巢狀之後是什麼樣的: # cd /sys/kernel/config/03-group-children/
# ls
description  # mkdir test # mkdir test/test1 # mkdir test/test2 # mkdir test/test3 # tree
.
|-- description
`-- test
    |-- description
    |-- test1
    |   `-- storeme
    |-- test2
    |   `-- storeme
    `-- test3
        `-- storeme
看出與示例2的區別了嗎? 首先看子系統定義 [cpp] view plain copy
  1. 382static struct configfs_subsystem group_children_subsys = {  
  2. 383     .su_group = {  
  3. 384          .cg_item = {  
  4. 385               .ci_namebuf = "03-group-children",  
  5. 386               .ci_type = &group_children_type,  
  6. 387          },  
  7. 388     },  
  8. 389};  
386行,config_item_type與之前的不一樣,跟過去看看 [cpp] view plain copy
  1. 371static struct configfs_group_operations group_children_group_ops = {  
  2. 372     .make_group     = group_children_make_group,  
  3. 373};  
  4. 374  
  5. 375static struct config_item_type group_children_type = {  
  6. 376     .ct_item_ops     = &group_children_item_ops,  
  7. 377     .ct_group_ops     = &group_children_group_ops,  
  8. 378     .ct_attrs     = group_children_attrs,  
  9. 379     .ct_owner     = THIS_MODULE,  
  10. 380};  

375行,定義新的config_item_type,其根本區別在377行configfs_group_operations 371行,定義了configfs_group_operations,這裡定義了make_group函式,在子系統下mkdir就會呼叫這個函式。 [cpp] view plain copy
  1. 326static struct config_group *group_children_make_group(struct config_group *group, const char *name)  
  2. 327{  
  3. 328     struct simple_children *simple_children;  
  4. 329  
  5. 330     simple_children = kzalloc(sizeof(struct simple_children),  
  6. 331                      GFP_KERNEL);  
  7. 332     if (!simple_children)  
  8. 333          return ERR_PTR(-ENOMEM);  
  9. 334  
  10. 335     config_group_init_type_name(&simple_children->group, name,  
  11. 336                        &simple_children_type);  
  12. 337  
  13. 338     return &simple_children->group;  
  14. 339}  

這份程式碼非常眼熟,跟示例2中建立config_item太像了,只不過把所有物件由config_item改為config_group型別的。 336行,simple_children_type正是示例2中對應的config_item_type。 所以這裡的建立步驟首先是建立一個為config_group的目錄,再在這個目錄下建立config_item的目錄。 到這裡為止,簡單地瞭解了一下configfs的實現原理,在某些應用中不失為一種很好的手段。 轉載請注原出處:http://blog.csdn.net/liumangxiong