1 Linux Device models
The Linux 2.5 kernel introduces a new device model designed to manage all devices on the computer in a unified way.
It contains the following infrastructure:
Type |
Description |
Equipment devices |
The device is the most basic type in this model and is organized hierarchically by the connection of the device itself |
Device driver Device Drivers |
Installing multiple identical devices in one system requires only one driver support |
Bus Type Types |
Manage all devices connected to this bus at the entire bus level |
Equipment Category Device Classes |
This is the hierarchy tree of the organization according to the function, such as USB interface and PS/2 interface mouse are input devices, will appear under/sys/class/input/ |
Linux through the above model to achieve the unified management of equipment, so that the driver and equipment automatically match. 2 Sysfs File System
SYSFS is a virtual file system based on memory, which provides directory, attribute file, link file, etc., so that user space can easily access kernel device information.
In the internal implementation, SYSFS the KOBJECT data structure as the smallest granularity, and then encapsulated into the Kset, subsystem, Bus_type, class and other models to organize the topological relations among the devices. 2.1sysfs Top level directory
The top-level directory structure of the/sys is as follows:
Sub-directory under/sys |
What is included |
/sys/devices |
This is the kernel of all devices in the system hierarchical expression model, but also/sys file system Management equipment, the most important directory structure, the following will be its internal structure for further analysis; |
/sys/dev |
This directory maintains a symbolic link file that links the primary and secondary numbers (Major:minor) of the character devices and block devices to the real device (/sys/devices), which is first introduced in the kernel 2.6.26; |
/sys/bus |
This is the kernel device by bus type layered directory structure, all the devices in the devices are connected to a certain bus, where each of the specific bus can find the symbolic link for each specific device, it is also a part of the Linux Unified device model; |
/sys/class |
This is a device model that is categorized according to the capabilities of the device, such as all input devices of the system appearing under/sys/class/input, regardless of which bus they are connected to the system. It is also part of the Linux Unified device model; |
/sys/block |
Here are all the current block devices in the system, according to the function to place under the/sys/class would be more appropriate, but only due to historical factors remain in the/sys/block, but from the beginning of 2.6.22 has been marked as obsolete, only in the open Config_sysfs_ Deprecated configuration will have the existence of this directory, and in the 2.6.26 kernel has been formally moved to the/sys/class/block, the old interface/sys/block for backward compatibility retention exists, but the content has changed to point to them in the/sys/ The symbolic link file of the real device in devices/; |
/sys/firmware |
Here is the system loading firmware mechanism of the user space interface, about the firmware is dedicated to the firmware loading of a set of APIs, in appendix LDD3 book on the kernel support firmware loading mechanism of a more detailed description; |
/sys/fs |
This is designed to describe all file systems in the system, including the file system itself and the mount points that are stored by file system classification, but at present only a few file systems such as FUSE,GFS2 support the Sysfs interface, and some traditional virtual file system (VFS) hierarchy control parameters are still sysctl (/ PROC/SYS/FS) in the interface; |
/sys/kernel |
Here is the location of all adjustable parameters of the kernel, currently only uevent_helper, kexec_loaded, MM, and a new type of slab splitter are used, and other kernel adjustable parameters are still located in Sysctl (/proc/sys/kernel ) interface; |
/sys/module |
There is information about all the modules in the system, whether they are compiled inline (inlined) into a kernel image file (Vmlinuz) or compiled into an external module (KO file), which can appear in/sys/module: Compiled into an external module (KO file) the corresponding/sys/module/<module_name>/appears after loading, and in this directory there are some properties files and property directories to represent some information about this external module, such as version number, loading state, The driver provided by the program, etc.; A module compiled inline will have a corresponding/sys/module/<module_name> when it has a module parameter that is not a 0 attribute, and the available parameters for these modules appear in the/sys/modules/<modname>/ In Parameters/<param_name>, such as/sys/module/printk/parameters/time the read-write parameter controls whether the inline module PRINTK the time prefix when printing kernel messages; All inline module parameters can also be written in the form "<module_name>.<param_name>=<value>" on the kernel boot parameters, such as when the kernel is started with the parameter "printk.time=1" and "" Sys/module/printk/parameters/time "Write 1 the same effect; Inline modules that do not have a non-0 attribute parameter do not appear here. |
/sys/power |
Here is the power option in the system, there are several properties files in this directory can be used to control the power state of the entire machine, such as can write control commands to the machine shutdown, restart and so on. |
/sys/slab (corresponding to the 2.6.23 kernel, moved to/sys/kernel/slab after 2.6.24) |
The implementation of the slab memory allocator can be selected from 2.6.23, and the new Slub (unqueued slab allocator) is set to the default value, and if this option is compiled,/sys will appear under/sys/slab, with every Kmem_cache The adjustable parameters of the structure body. Corresponding to the old slab memory allocator under the/proc/slabinfo dynamic adjustment interface, the new/sys/kernel/slab/<slab_name> interface of the various information and adjustable items appear more clearly. |
analysis of initialization of 2.2 SYSFS
First look at the Sysfs_init function in fs/sysfs/mount.c
int __init sysfs_init (void)
{
int err =-ENOMEM;
/* Create cache
/Sysfs_dir_cachep = Kmem_cache_create ("Sysfs_dir_cache",
sizeof (struct sysfs_dirent),
0, 0, NULL);
if (!sysfs_dir_cachep)
goto out;
/* Initialize SYSFS BDI device information *
/err = Sysfs_inode_init ();
if (err)
goto Out_err;
/* Registration SYSFS File System * *
err = Register_filesystem (&sysfs_fs_type);
if (!err) {
sysfs_mnt = Kern_mount (&sysfs_fs_type);
if (Is_err (sysfs_mnt)) {
printk (kern_err "Sysfs:could not mount!\n");
Err = Ptr_err (sysfs_mnt);
Sysfs_mnt = NULL;
Unregister_filesystem (&sysfs_fs_type);
Goto out_err;
}
} else
goto Out_err;
Out: Return
err;
Out_err:
Kmem_cache_destroy (SYSFS_DIR_CACHEP);
Sysfs_dir_cachep = NULL;
Goto out;
Sysfs_dir_cachep is a cache in which the object memory that will be used in the SYSFS is opened in this cache.
The Sysfs_inode_init function initializes the Backing_dev_info object, which describes the information about the disk block device and does not delve into it.
The Register_filesystem function registers the Sysfs file system with the system, where Sysfs_fs_type is a File_system_type object that describes the Sysfs file system information:
struct file_system_type {* * name/const char *name;
/* Specify some features of the file system */int fs_flags; /* File system load function */struct Dentry * (*mount) (struct file_system_type *, int, const char *, void
*);
void (*KILL_SB) (struct super_block *);
/* Pointer to module, owner is null*/struct module *owner If it is not registered as a module;
/* All file_system through the next pointer to form a linked list, such as Ext2, Ext3, Proc, and so on * * struct file_system_type * NEXT;
/*superblock Chain list * * struct list_head fs_supers;
struct Lock_class_key s_lock_key;
struct Lock_class_key s_umount_key;
struct Lock_class_key s_vfs_rename_key;
struct Lock_class_key i_lock_key;
struct Lock_class_key i_mutex_key;
struct Lock_class_key i_mutex_dir_key;
struct Lock_class_key i_alloc_sem_key;
};
/*sysfs file_system*/static struct File_system_type sysfs_fs_type = {. Name = "Sysfs",. Mount = Sysfs_mount, . KILL_SB = SYSFS_KILL_SB,};
It should be noted that the system links all the File_system_type through the next pointer to the linked list.
Sysfs_fs_type also defines its mout member function as Sysfs_mount.
The implementation of the Register_filesystem function is as follows:
/** * Register_filesystem-register A new filesystem * @fs: The file system structure * * Adds the file system passed To the list of file systems the kernel * are aware of for mount and other syscalls.
Returns 0 on success, * or a negative errno code on error. * * The &struct File_system_type This is passed are linked into the kernel * structures and must no be freed until T
He file system has been * unregistered.
* * int Register_filesystem (struct File_system_type * fs) {int res = 0;
struct File_system_type * * p;
Bug_on (STRCHR (Fs->name, '. '));
if (Fs->next) return-ebusy;
Init_list_head (&fs->fs_supers);
Write_lock (&file_systems_lock); /* All filesystem through next to form a linked list, find the name in the list of Fs->name Filestem if found, then return the Filestem address;
M (Fs->name, strlen (fs->name));
if (*p) res =-ebusy;
else *p = fs;/* link to the tail of the chain/Write_unlock (&file_systems_lock); Return rEs
}
Register_filesystem finds the file system named Fs->name in the file system list by calling Find_filesystem, and returns the File_system_type address if found. If it is not found, it returns the next pointer address at the end of the chain and links the current file_system_type to the end of the list, thus completing the registration of the Sysfs file system.
The following is a specific implementation of the Find_filesystem function:
static struct File_system_type **find_filesystem (const char *name, unsigned len)
{struct File_system_type
;
* * Through the next member Traversal File_systems list/for
(p=&file_systems; *p p=& (*p)->next)
if (strlen (*p)-> Name = = = Len &&
strncmp ((*p)->name, name, len) = = 0) break
;
return p;
Back to Sysfs_fs_type's Sysfs_mount function, as the name suggests, it completes the Sysfs file system loading, the following is the specific implementation:
static struct Dentry *sysfs_mount (struct file_system_type *fs_type, int flags, const CHA
R *dev_name, void *data) {struct Sysfs_super_info *info;
Enum Kobj_ns_type type;
struct Super_block *sb;
int error;
info = kzalloc (sizeof (*info), Gfp_kernel);
if (!info) return err_ptr (-ENOMEM);
for (type = Kobj_ns_type_none type < kobj_ns_types type++) Info->ns[type] = kobj_ns_grab_current (type);
/* Create superblock*/SB = Sget (Fs_type, Sysfs_test_super, Sysfs_set_super, info);
if (Is_err (SB) | | | sb->s_fs_info!= info) free_sysfs_super_info (info);
if (Is_err (SB)) return Err_cast (SB);
if (!sb->s_root) {sb->s_flags = flags;
/* Set Superblock, initialize Inode and dentry*/error = Sysfs_fill_super (SB, data, Flags & ms_silent? 1:0);
if (Error) {deactivate_locked_super (SB);
return err_ptr (Error); } sb->s_flags|= ms_active;
Return Dget (Sb->s_root); }
The Mount function first creates the Supserblock through the Sget function, then invokes Sysfs_fill_super to initialize the inode and dentry information, which is the specific implementation of the Sysfs_fill_super:
static int sysfs_fill_super (struct super_block *sb, void *data, int silent) {struct inode *inode;
struct Dentry *root;
Sb->s_blocksize = page_cache_size;
Sb->s_blocksize_bits = Page_cache_shift;
Sb->s_magic = Sysfs_magic;
/* Set Superblock action function for sysfs_ops*/sb->s_op = &sysfs_ops;
Sb->s_time_gran = 1;
/* Get root inode, initialize and unlock it/mutex_lock (&sysfs_mutex);
/* Create and initialize inode*/Inode = Sysfs_get_inode (SB, &sysfs_root);
Mutex_unlock (&sysfs_mutex);
if (!inode) {pr_debug ("sysfs:could not get root inode\n");
Return-enomem;
}/* Instantiate and link root dentry */* Create Dentry and associate to inode*/root = D_alloc_root (inode);
if (!root) {pr_debug ("%s:could not get root dentry!\n", __func__);
Iput (Inode);
Return-enomem;
/*dentry Association to sysfs_root*/root->d_fsdata = &sysfs_root; /*superblock Association to dentry*/sb->s_root = root;
return 0; }
In a file system, an Inode (an index entry) is used to describe the index information of a file on a physical storage medium, Dentry (a directory entry) to describe a file's logical information, such as a filename.
Sysfs_fill_super first invokes Sysfs_get_inode to create and initialize the Inode, and then creates dentry through the D_alloc_root function, where the inode and Dentry are created for the root node.
The following is the process of creating an inode:
/**
* sysfs_get_inode-get inode for sysfs_dirent
* @sb: Super blocks
* @sd: Sysfs_dirent to Allocate inode for
*
* get inode for @sd. If such inode doesn ' t exist, a new inode
* is allocated and basics are. New Inode is
* returned locked.
*
* locking:
* Kernel thread context (may sleep).
*
* RETURNS:
* Pointer to allocated inode on success, NULL on failure.
* * struct inode * sysfs_get_inode (struct super_block *sb, struct sysfs_dirent *sd)
{
struct inode *inode;
/* Find the Inode from the Superblock, then create a new inode and return to the
inode = iget_locked (SB, Sd->s_ino);
if (Inode && (Inode->i_state & i_new))
Sysfs_init_inode (SD, inode);/* Initialize inode*/return
inode ;
The Sysfs_get_inode function calls Sysfs_init_inode to initialize the inode in detail as follows:
static void Sysfs_init_inode (struct sysfs_dirent *sd, struct inode *inode) {struct bin_attribute;
Inode->i_private = Sysfs_get (SD);
Inode->i_mapping->a_ops = &sysfs_aops;
Inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
Inode->i_op = &sysfs_inode_operations;
Set_default_inode_attr (Inode, Sd->s_mode);
Sysfs_refresh_inode (SD, Inode); 2) The attribute file corresponds to the Kobject 3) bin file corresponds to the Kobject bin_attribute 4) Link file corresponding to the */switch (Sysfs_type (SD)) {case SYSF
S_dir:inode->i_op = &sysfs_dir_inode_operations;
INODE->I_FOP = &sysfs_dir_operations;
Break
Case sysfs_kobj_attr:inode->i_size = page_size;
INODE->I_FOP = &sysfs_file_operations;
Break Case sysfs_kobj_bin_attr:bin_attr = Sd->s_bin_attr.bin_attr;
Inode->i_size = bin_attr->size;
INODE->I_FOP = &bin_fops;
Break
Case SYSFS_KOBJ_LINK:INODE->I_OP = &sysfs_symlink_inode_operations;
Break
Default:bug ();
} unlock_new_inode (Inode);
}
This specifies the Inode action function for the different sysfs_dirent types. The Sysfs file types have the following:
Catalog Files
Properties File
bin file
Linked Files
The correspondence of these files with Kobject is as follows (Kobject will be covered in more detail in the next chapter):
1) directory corresponds to Kobject
2 attribute file corresponding to Kobject
3) Bin file corresponds to Kobject bin_attribute
4) Link file corresponds to Kobject sysfs_elem_bin_attr
Reference article: Accessing the Linux kernel using the/sys file system