linux之configfs簡介和程式設計入門
阿新 • • 發佈:2019-01-09
一、什麼是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
config_group作為幕後主使,是不輕易出現在臺前的。所以有了94行的struct config_item來表現為一個目錄。 [cpp] view plain copy
58行為目錄名稱。 63行為目錄下屬性和屬性操作,屬性表現為目錄下的文字檔案。 [cpp] view plain copy
84行為屬性操作方法,操作物件是86行屬性。 85行為目錄操作方法,可以在當前目錄下建立item或group。 86行為當前目錄屬性陣列。 [cpp] view plain copy
屬性非常簡單,有屬性名稱、所屬模組和訪問許可權。
示例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
建立一個結構體包含了configfs子系統,兩個屬性showme, storeme放在了這裡。 雖然註釋裡說明了為什麼把這兩個屬性放這裡,但還是沒太理解,既然屬性description可以放子系統下,為什麼其他兩個屬性不行呢?有誰知道的告知一下。 子系統定義如下: [cpp] view plain copy
142行,定義目錄名稱。 143行,定義屬性和操作。 接著看屬性和操作的定義: [cpp] view plain copy
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
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
接著定義config_item_type, [cpp] view plain copy
298行,定義了子系統根目錄屬性操作,跟示例1類似 300行,定義了子系統根目錄屬性,跟示例1類似 299行,這裡新增加了configfs_group_operations,具體定義在293行,繼續跟進294行函式simple_children_make_item [cpp] view plain copy
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
375行,定義新的config_item_type,其根本區別在377行configfs_group_operations 371行,定義了configfs_group_operations,這裡定義了make_group函式,在子系統下mkdir就會呼叫這個函式。 [cpp] view plain copy
這份程式碼非常眼熟,跟示例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
- 240struct configfs_subsystem {
- 241 struct config_group su_group;
- 242 struct mutex su_mutex;
- 243};
- 89/**
- 90 * group - a group of config_items of a specific type, belonging
- 91 * to a specific subsystem.
- 92 */
- 93struct config_group {
- 94 struct config_item cg_item;
- 95 struct list_head cg_children;
- 96 struct configfs_subsystem *cg_subsys;
- 97 struct config_group **default_groups;
- 98};
config_group作為幕後主使,是不輕易出現在臺前的。所以有了94行的struct config_item來表現為一個目錄。 [cpp] view plain copy
- 56struct config_item {
- 57 char *ci_name;
- 58 char ci_namebuf[CONFIGFS_ITEM_NAME_LEN];
- 59 struct kref ci_kref;
- 60 struct list_head ci_entry;
- 61 struct config_item *ci_parent;
- 62 struct config_group *ci_group;
- 63 struct config_item_type *ci_type;
- 64 struct dentry *ci_dentry;
- 65};
58行為目錄名稱。 63行為目錄下屬性和屬性操作,屬性表現為目錄下的文字檔案。 [cpp] view plain copy
- 82struct config_item_type {
- 83 struct module *ct_owner;
- 84 struct configfs_item_operations *ct_item_ops;
- 85 struct configfs_group_operations *ct_group_ops;
- 86 struct configfs_attribute **ct_attrs;
- 87};
84行為屬性操作方法,操作物件是86行屬性。 85行為目錄操作方法,可以在當前目錄下建立item或group。 86行為當前目錄屬性陣列。 [cpp] view plain copy
- 124struct configfs_attribute {
- 125 const char *ca_name;
- 126 struct module *ca_owner;
- 127 umode_t ca_mode;
- 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
- 37/*
- 38 * 01-childless
- 39 *
- 40 * This first example is a childless subsystem. It cannot create
- 41 * any config_items. It just has attributes.
- 42 *
- 43 * Note that we are enclosing the configfs_subsystem inside a container.
- 44 * This is not necessary if a subsystem has no attributes directly
- 45 * on the subsystem. See the next example, 02-simple-children, for
- 46 * such a subsystem.
- 47 */
- 48
- 49struct childless {
- 50 struct configfs_subsystem subsys;
- 51 int showme;
- 52 int storeme;
- 53};
建立一個結構體包含了configfs子系統,兩個屬性showme, storeme放在了這裡。 雖然註釋裡說明了為什麼把這兩個屬性放這裡,但還是沒太理解,既然屬性description可以放子系統下,為什麼其他兩個屬性不行呢?有誰知道的告知一下。 子系統定義如下: [cpp] view plain copy
- 138static struct childless childless_subsys = {
- 139 .subsys = {
- 140 .su_group = {
- 141 .cg_item = {
- 142 .ci_namebuf = "01-childless",
- 143 .ci_type = &childless_type,
- 144 },
- 145 },
- 146 },
- 147};
142行,定義目錄名稱。 143行,定義屬性和操作。 接著看屬性和操作的定義: [cpp] view plain copy
- 114CHILDLESS_ATTR_RO(showme, childless_showme_read);
- 115CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
- 116 childless_storeme_write);
- 117CHILDLESS_ATTR_RO(description, childless_description_read);
- 118
- 119static struct configfs_attribute *childless_attrs[] = {
- 120 &childless_attr_showme.attr,
- 121 &childless_attr_storeme.attr,
- 122 &childless_attr_description.attr,
- 123 NULL,
- 124};
- 125
- 126CONFIGFS_ATTR_OPS(childless);
- 127static struct configfs_item_operations childless_item_ops = {
- 128 .show_attribute = childless_attr_show,
- 129 .store_attribute = childless_attr_store,
- 130};
- 131
- 132static struct config_item_type childless_type = {
- 133 .ct_item_ops = &childless_item_ops,
- 134 .ct_attrs = childless_attrs,
- 135 .ct_owner = THIS_MODULE,
- 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
- 407static int __init configfs_example_init(void)
- 408{
- 409 int ret;
- 410 int i;
- 411 struct configfs_subsystem *subsys;
- 412
- 413 for (i = 0; example_subsys[i]; i++) {
- 414 subsys = example_subsys[i];
- 415
- 416 config_group_init(&subsys->su_group);
- 417 mutex_init(&subsys->su_mutex);
- 418 ret = configfs_register_subsystem(subsys);
- 419 if (ret) {
- 420 printk(KERN_ERR "Error %d while registering subsystem %s\n",
- 421 ret,
- 422 subsys->su_group.cg_item.ci_namebuf);
- 423 goto out_unregister;
- 424 }
- 425 }
- 426
- 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
- 304static struct configfs_subsystem simple_children_subsys = {
- 305 .su_group = {
- 306 .cg_item = {
- 307 .ci_namebuf = "02-simple-children",
- 308 .ci_type = &simple_children_type,
- 309 },
- 310 },
- 311};
接著定義config_item_type, [cpp] view plain copy
- 289/*
- 290 * Note that, since no extra work is required on ->drop_item(),
- 291 * no ->drop_item() is provided.
- 292 */
- 293static struct configfs_group_operations simple_children_group_ops = {
- 294 .make_item = simple_children_make_item,
- 295};
- 296
- 297static struct config_item_type simple_children_type = {
- 298 .ct_item_ops = &simple_children_item_ops,
- 299 .ct_group_ops = &simple_children_group_ops,
- 300 .ct_attrs = simple_children_attrs,
- 301 .ct_owner = THIS_MODULE,
- 302};
298行,定義了子系統根目錄屬性操作,跟示例1類似 300行,定義了子系統根目錄屬性,跟示例1類似 299行,這裡新增加了configfs_group_operations,具體定義在293行,繼續跟進294行函式simple_children_make_item [cpp] view plain copy
- 232struct simple_children {
- 233 struct config_group group;
- 234};
- 235
- 236static inline struct simple_children *to_simple_children(struct config_item *item)
- 237{
- 238 return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
- 239}
- 240
- 241static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
- 242{
- 243 struct simple_child *simple_child;
- 244
- 245 simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
- 246 if (!simple_child)
- 247 return ERR_PTR(-ENOMEM);
- 248
- 249 config_item_init_type_name(&simple_child->item, name,
- 250 &simple_child_type);
- 251
- 252 simple_child->storeme = 0;
- 253
- 254 return &simple_child->item;
- 255}
- 171static struct configfs_attribute simple_child_attr_storeme = {
- 172 .ca_owner = THIS_MODULE,
- 173 .ca_name = "storeme",
- 174 .ca_mode = S_IRUGO | S_IWUSR,
- 175};
- 176
- 177static struct configfs_attribute *simple_child_attrs[] = {
- 178 &simple_child_attr_storeme,
- 179 NULL,
- 180};
- 219static struct configfs_item_operations simple_child_item_ops = {
- 220 .release = simple_child_release,
- 221 .show_attribute = simple_child_attr_show,
- 222 .store_attribute = simple_child_attr_store,
- 223};
- 224
- 225static struct config_item_type simple_child_type = {
- 226 .ct_item_ops = &simple_child_item_ops,
- 227 .ct_attrs = simple_child_attrs,
- 228 .ct_owner = THIS_MODULE,
- 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
- 382static struct configfs_subsystem group_children_subsys = {
- 383 .su_group = {
- 384 .cg_item = {
- 385 .ci_namebuf = "03-group-children",
- 386 .ci_type = &group_children_type,
- 387 },
- 388 },
- 389};
- 371static struct configfs_group_operations group_children_group_ops = {
- 372 .make_group = group_children_make_group,
- 373};
- 374
- 375static struct config_item_type group_children_type = {
- 376 .ct_item_ops = &group_children_item_ops,
- 377 .ct_group_ops = &group_children_group_ops,
- 378 .ct_attrs = group_children_attrs,
- 379 .ct_owner = THIS_MODULE,
- 380};
375行,定義新的config_item_type,其根本區別在377行configfs_group_operations 371行,定義了configfs_group_operations,這裡定義了make_group函式,在子系統下mkdir就會呼叫這個函式。 [cpp] view plain copy
- 326static struct config_group *group_children_make_group(struct config_group *group, const char *name)
- 327{
- 328 struct simple_children *simple_children;
- 329
- 330 simple_children = kzalloc(sizeof(struct simple_children),
- 331 GFP_KERNEL);
- 332 if (!simple_children)
- 333 return ERR_PTR(-ENOMEM);
- 334
- 335 config_group_init_type_name(&simple_children->group, name,
- 336 &simple_children_type);
- 337
- 338 return &simple_children->group;
- 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