Transfer:
https://www.cnblogs.com/sctb/…

1. Compile and run

The code is available from the following link:

https://github.com/torvalds/l…

Write a Makefile:

obj-m += configfs_sample.o
all:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Build and generate kernel modules:

Make ls-l-rwxr --r-- 1 abin abin 10K Oct 27 16:58 configfs_sample.c? -rw-rw-r-- 1 abin abin 13K Oct 29 11:16 configfs_sample.ko -rw-rw-r-- 1 abin abin 603 Oct 29 11:16 configfs_sample.mod.c -rw-rw-r-- 1 abin abin 12K Oct 29 11:16 configfs_sample.mod.o-rw-rw-r -- 1 abin abin 12K Oct 29 11:16 configfs_sample.o -rw-rw-r-- 1 abin abin 166 Oct 29 11:16 Makefile -rw-rw-r-- 1 abin abin 92 Oct 29 11:16 modules.order -rw-rw-r-- 1 abin abin 0 Oct 29 11:16 Module.symvers

Where, configfs_sample.ko enables the compiled kernel module to be loaded using the following command:

sudo modprobe configfs_sample.ko

If the following error occurs:

Modprobe: FATAL: Module configfs_sample.ko not found in directory /lib/modules/4.15.0-117-generic

Copy configfs_sample.ko to /lib/modules/4.15.0-117-generic and try again.

Check to see if the configfs_sample.ko kernel module is mounted:

lsmod  | grep configfs_sample

configfs_sample 16384 0

Check the configfs root directory:

ls -l /sys/kernel/config/
  total 0
  drwxr-xr-x 2 root root 0 Oct 29 11:32 01-childless
  drwxr-xr-x 2 root root 0 Oct 29 11:32 02-simple-children
  drwxr-xr-x 2 root root 0 Oct 29 11:32 03-group-children

To uninstall the module, use the following command:

sudo modprobe -r configfs_sample.ko

2. Code understanding

To understand the code, let’s first clean up the hierarchy in ConfigFS:

Kernel module initialization entry:

module_init(configfs_example_init);

Configfs_example_init (void) function:

/* * Here is the configfs_subsystem array, Subsystem */ static struct configfs_subsystem subsystem subsystem subsystem subsystem subsystem subsystem subsystem */ static struct configfs_subsystem subsystem *example_subsys[] = {&childless_subsys.subsys, subsystem, subsystem &simple_children_subsys, &group_children_subsys, NULL, }; static int __init configfs_example_init(void) { int ret; int i; struct configfs_subsystem *subsys; // ConfigFS subsystem for (I = 0; example_subsys[i]; i++) { subsys = example_subsys[i]; config_group_init(&subsys->su_group); // initialize group mutex_init(&subsys->su_mutex); Subsystem (subsystem); // Initialize Mutex RET = configfs_register_subsystem(Subsys); We subsystem if (RET) {printk(Kern_Err "Error %d while engaging %s\n", RET, subsys->su_group.cg_item.ci_namebuf); goto out_unregister; } } return 0; out_unregister: for (i--; i >= 0; i--) configfs_unregister_subsystem(example_subsys[i]); return ret; }

The main logic of the program is delivered to ConfigFS via struct Configfs_subsystem subsystem. The following three examples are analyzed respectively.

2.1 sample 01 – childless

The contents of the variable childless_subsys:

struct childless { struct configfs_subsystem subsys; int showme; int storeme; }; static struct childless childless_subsys = { .subsys = { .su_group = { .cg_item = { .ci_namebuf = "01-childless", .ci_type = &childless_type; //struct config_item_type;},},},};

The childless_type variable is as follows:

Static const struct config_item_type childless_type = {.ct_attrs = childless_attrs; // CONFIGFS_ATTRIBUT_ATTRIBUT_TYPE = childless_attrs; Not defined for item and group operations. Ct_owner = THIS_MODULE,};

Childless_attrs is an array that ends in NULL. The following attributes are defined, which in configfs are represented as three files:

static struct configfs_attribute *childless_attrs[] = {
  &childless_attr_showme,
  &childless_attr_storeme,
  &childless_attr_description,
  NULL,
};

The childless_attr_showme, childless_attr_storeme, and childless_attr_description properties are created using the following functions:

CONFIGFS_ATTR_RO(childless_, showme); // The childless_showme_show() function is CONFIGFS_ATTR(childless_, storeme); // The childless_storeme_show() and childless_storeme_store() functions are CONFIGFS_ATTR_RO(childless_description); // You need to define the childless_description_show() function

There are three functions to create an attribute, in Linux /configfs.h:

#define CONFIGFS_ATTR(_pfx, _name)            \
static struct configfs_attribute _pfx##attr_##_name = {    \
    .ca_name    = __stringify(_name),        \
    .ca_mode    = S_IRUGO | S_IWUSR,        \
    .ca_owner    = THIS_MODULE,            \
    .show        = _pfx##_name##_show,        \
    .store        = _pfx##_name##_store,        \
}

#define CONFIGFS_ATTR_RO(_pfx, _name)            \
static struct configfs_attribute _pfx##attr_##_name = {    \
    .ca_name    = __stringify(_name),        \
    .ca_mode    = S_IRUGO,            \
    .ca_owner    = THIS_MODULE,            \
    .show        = _pfx##_name##_show,        \
}

#define CONFIGFS_ATTR_WO(_pfx, _name)            \
static struct configfs_attribute _pfx##attr_##_name = {    \
    .ca_name    = __stringify(_name),        \
    .ca_mode    = S_IWUSR,            \
    .ca_owner    = THIS_MODULE,            \
    .store        = _pfx##_name##_store,        \
}

As you can see, the three macro definition functions can define different structure variables based on the parameters passed in, named _pfx_attr_name, as well as the corresponding show and store function names.

CONFIGFS_ATTR(_pfx, _name) needs to define the show and store functions, the corresponding function names are: _pfx_name_show and _pfx_name_store, respectively;

CONFIGFS_ATTR_RO(_pfx, _name) only needs to define the show function;

CONFIGFS_ATTR_WO(_pfx, _name) only needs to define the store function.

Childless_showme_show (), childless_storeme_show(), childless_storeme_store() and childless_description_show() are defined as follows:

/* * pass item, */ static inline struct childless *to_childless(struct config_item *item) {return item? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL; } //childless_showme_show (struct childless, struct childless);} //childless_showme_show (struct childless, struct childless); Static ssize_t childless_showme_show(struct config_item *item, struct config_item) char *page) { struct childless *childless = to_childless(item); ssize_t pos; pos = sprintf(page, "%d\n", childless->showme); childless->showme++; return pos; } //childless_storeme_show function implementation, Struct childless member storeme static ssize_t childless_storeme_show(struct config_item *item, struct config_item *item) char *page) { return sprintf(page, "%d\n", to_childless(item)->storeme); } //childless_storeme_store, which takes the value entered from the file system, Static ssize_t childless_storeme_store(struct config_item *item, const char *page) size_t count) { struct childless *childless = to_childless(item); unsigned long tmp; char *p = (char *) page; tmp = simple_strtoul(p, &p, 10); // Convert a string to a decimal number of type unsigned long if (! p || (*p && (*p ! = '\n'))) return -EINVAL; if (tmp > INT_MAX) return -ERANGE; childless->storeme = tmp; return count; } //childless_description_show; Static ssize_t childless_description_show(struct config_item *item, char *page) {return sprintf(page, char *page); "[01-childless]\n" "\n" "The childless subsystem is the simplest possible subsystem in\n" "configfs. It does not support  the creation of child config_items.\n" "It only has a few attributes. In fact, it isn't much different\n" "than a directory in /proc.\n"); }

As I understand it, page points to a memory space that receives data from the file system and is responsible for exporting the contents of configfs to the file system.

Showme file running effect:

cat showme
  1
cat showme
  2

Storeme file effect:

cat storeme
  0
echo 1111 > storeme
cat storeme
  1111

2.2 example 02 – simple – the children

simple_children_subsys

struct simple_children {
  struct config_group group;
};

static struct configfs_subsystem simple_children_subsys = {
  .su_group = {
    .cg_item = {
      .ci_namebuf = "02-simple-children",
      .ci_type = &simple_children_type,
    },
  },
};

Simple_children_type content:

static const struct config_item_type simple_children_type = { .ct_item_ops = &simple_children_item_ops, Ct_group_ops = &simple_children_group_ops; ct_attrs = simple_children_attrs; Same as 01. Ct_owner = THIS_MODULE,};

As you can see, in contrast to the 01 example, 02-siimple-chiildren defines not only ct_attrs, but also ct_item_ops and ct_group_ops. Let’s look at the variable assigned to ct_attrs, simple_children_attrs:

Static struct configfs_attribute *simple_children_attrs[] = {&simple_children_attr_description, struct configfs_attribute * simple_children_attr_description, Is represented as file NULL in configfs,};

Simple_children_attrs defines the properties of the object, which are represented as files in configfs. Simple_children_attr_description is created using the macro function:

CONFIGFS_ATTR_RO(simple_children_, description);

The show function is used in the CONFIGFS_ATTR_RO macro function, defined as follows:

static ssize_t simple_children_description_show(struct config_item *item, char *page)
{
  return sprintf(page,
                 "[02-simple-children]\n"
                 "\n"
                 "This subsystem allows the creation of child config_items.  These\n"
                 "items have only one attribute that is readable and writeable.\n");
}

This is the same as the 01 example, with the focus on ct_item_ops and ct_group_ops. Simple_children_item_ops is defined as follows:

Static struct configfs_item_operations simple_children_item_ops = {. Release = simple_children_release, struct configfs_item_operations simple_children_ops = {.

Struct configfs_item_operations (struct configfs_item_operations) struct children_item_ops (struct configfs_item_operations) struct struct configfs_item_operations (struct configfs_item_operations)

static void simple_children_release(struct config_item *item) { kfree(to_simple_children(item)); // Convert item to simple_children struct and free kernel allocated memory}

Simple_children_group_ops is defined as follows:

static struct configfs_group_operations simple_children_group_ops = {
  .make_item    = simple_children_make_item,
};

Simple_children_group_ops is also simple, implementing only the make_item function. Simple_children_make_item is as follows:

/* * pass item, Struct simple_children */ static inline struct simple_children *to_simple_children(struct config_item *item) { return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; } static struct config_item *simple_children_make_item(struct config_group *group, const char *name) { struct simple_child *simple_child; simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); // Allocate memory for simple_child if (! simple_child) return ERR_PTR(-ENOMEM); config_item_init_type_name(&simple_child->item, name, &simple_child_type); Config_item_type = config_item_type; simple_child_type = config_item_type; simple_child->storeme = 0; // set simple_child's storeme to 0 return &simple_child->item; }

Simple_child_type is defined as follows:

struct simple_child {
  struct config_item item;
  int storeme;
};

static const struct config_item_type simple_child_type = {
  .ct_item_ops    = &simple_child_item_ops,
  .ct_attrs    = simple_child_attrs,
  .ct_owner    = THIS_MODULE,
};

As above, ct_attrs and ct_item_ops are defined, but ct_item_ops is not defined. The simple_child_attrs variable is defined as follows:

CONFIGFS_ATTR(simple_child_, storeme);

static struct configfs_attribute *simple_child_attrs[] = {
  &simple_child_attr_storeme,
  NULL,
};

We need to define the show and store functions:

static inline struct simple_child *to_simple_child(struct config_item *item) { return item ? container_of(item, struct simple_child, item) : NULL; } /* * subitem show function, */ static ssize_t simple_child_storeme_show(struct config_item *item, struct config_item *item) char *page) { return sprintf(page, "%d\n", to_simple_child(item)->storeme); } /* * subitem store function, */ static ssize_t simple_child_storeme_store(struct config_item *item, struct config_item *item) const char *page, size_t count) { struct simple_child *simple_child = to_simple_child(item); unsigned long tmp; char *p = (char *) page; tmp = simple_strtoul(p, &p, 10); // Convert the string to a decimal number if (! p || (*p && (*p ! = '\n'))) return -EINVAL; if (tmp > INT_MAX) return -ERANGE; simple_child->storeme = tmp; return count; }

Operation effect:

make child
ls
  child  description
cd child
ls -l
  total 0
  -rw-r--r-- 1 root root 4096 Nov  3 21:57 storeme

The store file in the child folder is created automatically because the make_item function is defined and the simple_child_type variable is used when initializing the item.

cat storeme
  0
echo 2222 > storeme
cat storeme
  2222

2.3 sample 03 – group – children

The GROUP_CHILDREN_SUBSYS variable has the following contents:

static struct configfs_subsystem group_children_subsys = { .su_group = { .cg_item = { .ci_namebuf = "03-group-children",  .ci_type = &group_children_type, }, }, };

GROUP_CHILDREN_TYPE is defined as follows:

static const struct config_item_type group_children_type = {
  .ct_group_ops    = &group_children_group_ops,
  .ct_attrs    = group_children_attrs,
  .ct_owner    = THIS_MODULE,
};

As you can see, in contrast to Example 02, there are no defined operations on Item, only operations on Group. Group_children_attrs: group_children_attrs:

CONFIGFS_ATTR_RO(group_children_, description);

static struct configfs_attribute *group_children_attrs[] = {
  &group_children_attr_description,
  NULL,
};

Similarly, using the CONFIGFS_ATTR_RO macro to define functions requires the show function to be defined first:

static ssize_t group_children_description_show(struct config_item *item, char *page)
{
  return sprintf(page,
                 "[03-group-children]\n"
                 "\n"
                 "This subsystem allows the creation of child config_groups.  These\n"
                 "groups are like the subsystem simple-children.\n");
}

As with Example 01 and 02, here are the main points of Example 03:

static struct config_group *group_children_make_group( struct config_group *group, const char *name) { struct simple_children *simple_children; Struct simple_children = kzalloc(sizeof(struct simple_children), GFP_KERNEL); struct simple_children = kzalloc(struct simple_children), GFP_KERNEL); // Allocate memory if (! simple_children) return ERR_PTR(-ENOMEM); config_group_init_type_name(&simple_children->group, name, &simple_children_type); Return &simple_children->group; return &simple_children->group; }

This code is responsible for creating the group, initialized with the simple_children_type variable, struct config_item_type, which defines the contents of instance 02.

In configfs, each directory created under 03-group-children is equivalent to the 02-simple-children directory created when the kernel module is loaded.

Operation effect:

mkdir group
ls
  description  group
cd group
ls -l
  total 0
  -r--r--r-- 1 root root 4096 Nov  3 22:20 description
cat description [02-simple-children] This subsystem allows the creation of child config_items. These items have only one  attribute that is readable and writeable.

As you can see here, the directory created in Example 03 is equivalent to the 02-simple-children directory, and the following actions have the same effect as the example 02.

mkdir group_child
ls
  description  group_child
cd group_child
ls
  storeme
cat storeme
  0
echo 3333 > storeme
cat storeme
  3333