sysfs

本文详细解析Linux设备模型的底层结构、设备上层容器总线与设备的实现,以及sysfs文件系统的构成与工作原理,旨在帮助开发者深入理解Linux设备管理与文件系统交互的核心机制。
 
<1> Linux设备底层模型
<2> 设备模型上层容器
<3> sysfs文件系统模型

1. Linux设备底层模型
//sysfs的信息来源是kobject层次结构,读一个sysfs文件就是动态的从kobject结构提取信息生成文件,
//kobject层次结构就是linux的设备模型.
//kobject提供基本的对象管理,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。
struct kobject {
        const char              *name;        //指向对象名称的指针
        struct list_head        entry;        //挂到kset中链表的入口点
        struct kobject          *parent;      //指向父对象的指针
        struct kset             *kset;        //所属kset的指针
        struct kobj_type        *ktype;       //指向其对象类型描述符的指针
        struct sysfs_dirent     *sd;          //sysfs文件系统中与该对象对应的文件节点路径指针
        struct kref             kref;         //对象引用计数
        unsigned int state_initialized:1;
        unsigned int state_in_sysfs:1;
        unsigned int state_add_uevent_sent:1;
        unsigned int state_remove_uevent_sent:1;
        unsigned int uevent_suppress:1;
};

//kset最重要的是建立上层(sub_system)和下层的(kobject)的关联性
//kobject 也会利用它了分辨自已是属于那一个类型,,然后在/sys下建立正确的目录位置
//而kset 的优先权比较高,
//kobject会利用自已的*kset找到自已所属的kset,然后把*ktype指定成该kset的ktype,
//除非沒有定义kset,才会用ktype来建立关系。
//kobject通过kset组织成层次化的结构; kset是具有相同类型的kobject的集合.
struct kset {
	struct list_head list;                    //用于连接该kset中所有kobject的链表头
	spinlock_t list_lock;
	struct kobject kobj;                      //嵌入的kobject
	const struct kset_uevent_ops *uevent_ops; //指向uevent操作表的指针
};

struct kobj_type {
	void (*release)(struct kobject *kobj);    //用于释放kobject占用的资源
	const struct sysfs_ops *sysfs_ops;        //sysfs操作表 
	struct attribute **default_attrs;         //sysfs文件系统缺省属性列表
	const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
	const void *(*namespace)(struct kobject *kobj);
};

//attribute,它以文件的形式输出到sysfs的目录当中,在kobject对应的目录下面,文件名就是name.
//文件读写的方法对应于kobj_type中的sysfs_ops
struct attribute {
	const char		*name;
	umode_t			mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lock_class_key	*key;
	struct lock_class_key	skey;
#endif
};


//包含在kset中的所有kobject被组织成一个双向循环链表,list域正是该链表的头。
//kset数据结构还内嵌了一个kobject对象(由kobj域表示),所有属于这个kset的kobject对象的parent域
//均指向这个内嵌的kobject.
//kset还依赖于kobject维护引用计数: kset的引用计数实际上就是内嵌的kobject对象的引用计数。
@Kobject.c 
EXPORT_SYMBOL(kobject_set_name);
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_add);
EXPORT_SYMBOL(kobject_get);
EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(kobject_del);
EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister);


int kobject_add(struct kobject * kobj);
+-- kobject_add_varg(kobj, parent, fmt, args);
    +-- kobject_add_internal(kobj);
        +-- parent = kobject_get(kobj->parent); //增加父目录各级kobject的引用计数;
        +-- if (kobj->kset) {
                if (!parent)
                    parent = kobject_get(&kobj->kset->kobj);
                kobj_kset_join(kobj);           //挂接该kobject对象到kset的list链中;
                kobj->parent = parent;          //将kobj对象加入Linux设备层次;
            }
           //在其parent指向的目录下创建文件节点(并启动该类型内核对象的hotplug函数?);
        +-- error = create_dir(kobj);          


2. 设备模型上层容器
2.1 总线
/**
 * struct bus_type - The bus type of the device
 *
 * @name:       The name of the bus.
 * @dev_name:   Used for subsystems to enumerate devices like ("foo%u", dev->id).
 * @dev_root:   Default device to use as the parent.
 * @bus_attrs:	Default attributes of the bus.
 * @dev_attrs:	Default attributes of the devices on the bus.
 * @drv_attrs:	Default attributes of the device drivers on the bus.
 * @match:      Called, perhaps multiple times, whenever a new device or driver
 *              is added for this bus. It should return a nonzero value if the
 *              given device can be handled by the given driver.
 * @uevent:     Called when a device is added, removed, or a few other things
 *              that generate uevents to add the environment variables.
 * @probe:      Called when a new device or driver add to this bus, and callback
 *              the specific driver's probe to initial the matched device.
 * @remove:     Called when a device removed from this bus.
 * @shutdown:   Called at shut-down time to quiesce the device.
 * @suspend:    Called when a device on this bus wants to go to sleep mode.
 * @resume:     Called to bring a device on this bus out of sleep mode.
 * @pm:         Power management operations of this bus, callback the specific
 *              device driver's pm-ops.
 * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
 *              driver implementations to a bus and allow the driver to do
 *              bus-specific setup
 * @p:          The private data of the driver core, only the driver core can
 *              touch this.
 *
 * A bus is a channel between the processor and one or more devices. For the
 * purposes of the device model, all devices are connected via a bus, even if
 * it is an internal, virtual, "platform" bus. Buses can plug into each other.
 * A USB controller is usually a PCI device, for example. The device model
 * represents the actual connections between buses and the devices they control.
 * A bus is represented by the bus_type structure. It contains the name, the
 * default attributes, the bus' methods, PM operations, and the driver core's
 * private data.
 */
struct bus_type {
	const char		*name;
	const char		*dev_name;
	struct device		*dev_root;
	struct bus_attribute	*bus_attrs;
	struct device_attribute	*dev_attrs;
	struct driver_attribute	*drv_attrs;

	int (*match)(struct device *dev, struct device_driver *drv);
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
	int (*probe)(struct device *dev);
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;
	struct iommu_ops *iommu_ops;
	struct subsys_private *p;             //bus关联的设备驱动链表都在这里面
};

/**
 * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
 *
 * @subsys - the struct kset that defines this subsystem
 * @devices_kset - the subsystem's 'devices' directory
 * @interfaces - list of subsystem interfaces associated
 * @mutex - protect the devices, and interfaces lists.
 *
 * @drivers_kset - the list of drivers associated
 * @klist_devices - the klist to iterate over the @devices_kset
 * @klist_drivers - the klist to iterate over the @drivers_kset
 * @bus_notifier - the bus notifier list for anything that cares about things
 *                 on this bus.
 * @bus - pointer back to the struct bus_type that this structure is associated
 *        with.
 *
 * @glue_dirs - "glue" directory to put in-between the parent device to
 *              avoid namespace conflicts
 * @class - pointer back to the struct class that this structure is associated
 *          with.
 *
 * This structure is the one that is the actual kobject allowing struct
 * bus_type/class to be statically allocated safely.  Nothing outside of the
 * driver core should ever touch these fields.
 */
struct subsys_private {
	struct kset subsys;
	struct kset *devices_kset;           //devices_kset
	struct list_head interfaces;
	struct mutex mutex;

	struct kset *drivers_kset;           //drivers_kset
	struct klist klist_devices;          //总线上所挂的设备的链表
	struct klist klist_drivers;          //总线上设备对应的驱动的链表
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;

	struct kset glue_dirs;
	struct class *class;
};

2.2 设备
//通常device结构不单独使用,而是内嵌在更大的结构中作为一个子结构使用

/**
 * struct device - The basic device structure
 * @parent:	The device's "parent" device, the device to which it is attached.
 * 		In most cases, a parent device is some sort of bus or host
 * 		controller. If parent is NULL, the device, is a top-level device,
 * 		which is not usually what you want.
 * @p:		Holds the private data of the driver core portions of the device.
 * 		See the comment of the struct device_private for detail.
 * @kobj:	A top-level, abstract class from which other classes are derived.
 * @init_name:	Initial name of the device.
 * @type:	The type of device.
 * 		This identifies the device type and carries type-specific
 * 		information.
 * @mutex:	Mutex to synchronize calls to its driver.
 * @bus:	Type of bus device is on.
 * @driver:	Which driver has allocated this
 * @platform_data: Platform data specific to the device.
 * 		Example: For devices on custom boards, as typical of embedded
 * 		and SOC based hardware, Linux often uses platform_data to point
 * 		to board-specific structures describing devices and how they
 * 		are wired.  That can include what ports are available, chip
 * 		variants, which GPIO pins act in what additional roles, and so
 * 		on.  This shrinks the "Board Support Packages" (BSPs) and
 * 		minimizes board-specific #ifdefs in drivers.
 * @power:	For device power management.
 * 		See Documentation/power/devices.txt for details.
 * @pm_domain:	Provide callbacks that are executed during system suspend,
 * 		hibernation, system resume and during runtime PM transitions
 * 		along with subsystem-level and driver-level callbacks.
 * @numa_node:	NUMA node this device is close to.
 * @dma_mask:	Dma mask (if dma'ble device).
 * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
 * 		hardware supports 64-bit addresses for consistent allocations
 * 		such descriptors.
 * @dma_parms:	A low level driver may set these to teach IOMMU code about
 * 		segment limitations.
 * @dma_pools:	Dma pools (if dma'ble device).
 * @dma_mem:	Internal for coherent mem override.
 * @archdata:	For arch-specific additions.
 * @of_node:	Associated device tree node.
 * @devt:	For creating the sysfs "dev".
 * @id:		device instance
 * @devres_lock: Spinlock to protect the resource of the device.
 * @devres_head: The resources list of the device.
 * @knode_class: The node used to add the device to the class list.
 * @class:	The class of the device.
 * @groups:	Optional attribute groups.
 * @release:	Callback to free the device after all references have
 * 		gone away. This should be set by the allocator of the
 * 		device (i.e. the bus driver that discovered the device).
 *
 * At the lowest level, every device in a Linux system is represented by an
 * instance of struct device. The device structure contains the information
 * that the device model core needs to model the system. Most subsystems,
 * however, track additional information about the devices they host. As a
 * result, it is rare for devices to be represented by bare device structures;
 * instead, that structure, like kobject structures, is usually embedded within
 * a higher-level representation of the device.
 */
struct device {
	struct device             *parent;             

	struct device_private	  *p;         //特定于设备的私有数据

	//内嵌的kobject对象,用于引用计数管理并通过它实现设备层次结构
	struct kobject            kobj;       
	const char                *init_name; /* initial name of the device */
	const struct device_type  *type;

	struct mutex              mutex;	/* mutex to synchronize calls to its driver.*/

	struct bus_type	          *bus;		/* type of bus device is on */
	struct device_driver      *driver;	/* which driver has allocated this device */

	void                      *platform_data;	/* Platform specific data, 
	                                           device core doesn't touch it */
	struct dev_pm_info        power;
	struct dev_pm_domain      *pm_domain;

#ifdef CONFIG_NUMA
	int		numa_node;	     /* NUMA node this device is close to */
#endif
	u64		*dma_mask;	     /* dma mask (if dma'able device) */
	u64		coherent_dma_mask;   /* Like dma_mask, but for alloc_coherent mappings 
	   		                        as not all hardware supports 64 bit addresses  
	   		                        for consistent allocations such descriptors. */

	struct device_dma_parameters *dma_parms;

	struct list_head        dma_pools;        /* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem;         /* internal for coherent mem override */

	/* arch specific additions */
	struct dev_archdata     archdata;

	struct device_node      *of_node;        /* associated device tree node */

	dev_t                   devt;            /* dev_t, creates the sysfs "dev" */
	u32                     id;              /* device instance */

	spinlock_t              devres_lock;
	struct list_head        devres_head;

	struct klist_node       knode_class;
	struct class            *class;
	const struct attribute_group **groups;	/* optional groups */

	void	(*release)(struct device *dev);
};

/*
 * The type of device, "struct device" is embedded in. A class
 * or bus can contain devices of different types
 * like "partitions" and "disks", "mouse" and "event".
 * This identifies the device type and carries type-specific
 * information, equivalent to the kobj_type of a kobject.
 * If "name" is specified, the uevent will contain it in
 * the DEVTYPE variable.
 */
struct device_type {
	const char *name;
	const struct attribute_group **groups;
	int   (*uevent) (struct device *dev, struct kobj_uevent_env *env);
	char *(*devnode)(struct device *dev, umode_t *mode);
	void  (*release)(struct device *dev);

	const struct dev_pm_ops *pm;
};


struct device *
device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, 
              const char *fmt, ...)	
+-- device_create_vargs(class, parent, devt, drvdata, fmt, vargs); 
    +-- dev->devt = devt;
    +-- dev->class = class;
    +-- dev->parent = parent;
    +-- dev->release = device_create_release;
    +-- dev_set_drvdata(dev, drvdata);
    +-- device_register(dev);          /*将一个新的device对象插入设备模型;*/
        +-- device_initialize(dev);
        +-- device_add(dev);

struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
+-- client->dev.parent = &client->adapter->dev;
+-- client->dev.bus = &i2c_bus_type;          //predefined bus_type
+-- client->dev.type = &i2c_client_type;      //predefined device_type
+-- client->dev.of_node = info->of_node;
+-- status = device_register(&client->dev);
    +-- device_initialize(dev);
    +-- device_add(dev);


int device_add(struct device *dev)
+-- device_private_init(dev);
+-- dev_set_name(dev, "%s", dev->init_name);
+-- if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
        dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
+-- kobject_add(&dev->kobj, dev->kobj.parent, NULL);
+-- device_create_file(dev, &uevent_attr);
+-- device_create_file(dev, &devt_attr);
+-- device_create_sys_dev_entry(dev);
+-- devtmpfs_create_node(dev);
+-- device_add_class_symlinks(dev);
+-- device_add_attrs(dev);
    +-- struct class *class = dev->class;
    +-- const struct device_type *type = dev->type;   //拿到predefined的device_type
    +-- if (class) {
            device_add_attributes(dev, class->dev_attrs);
            device_add_bin_attributes(dev, class->dev_bin_attrs);
        }
    +-- if (type)
            device_add_groups(dev, type->groups);     //用拿到的device_type初始化设备
    +-- device_add_groups(dev, dev->groups);
+-- bus_add_device(dev);
+-- dpm_sysfs_add(dev);
+-- device_pm_add(dev);
+-- if (dev->bus)
        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                     BUS_NOTIFY_ADD_DEVICE, dev);
+-- kobject_uevent(&dev->kobj, KOBJ_ADD);  //通知user space,有内核对象加入
+-- bus_probe_device(dev);                 //在总线的设备/驱动链表上搜索,这里导致probe函数的调用


2.3 驱动
/**
 * struct device_driver - The basic device driver structure
 * @name:       Name of the device driver.
 * @bus:        The bus which the device of this driver belongs to.
 * @owner:      The module owner.
 * @mod_name:   Used for built-in modules.
 * @suppress_bind_attrs: Disables bind/unbind via sysfs.
 * @of_match_table: The open firmware table.
 * @probe:      Called to query the existence of a specific device,
 *              whether this driver can work with it, and bind the driver
 *              to a specific device.
 * @remove:     Called when the device is removed from the system to
 *              unbind a device from this driver.
 * @shutdown:   Called at shut-down time to quiesce the device.
 * @suspend:    Called to put the device to sleep mode. Usually to a
 *              low power state.
 * @resume:     Called to bring a device from sleep mode.
 * @groups:     Default attributes that get created by the driver core
 *              automatically.
 * @pm:         Power management operations of the device which matched
 *              this driver.
 * @p:          Driver core's private data, no one other than the driver
 *              core can touch this.
 *
 * The device driver-model tracks all of the drivers known to the system.
 * The main reason for this tracking is to enable the driver core to match
 * up drivers with new devices. Once drivers are known objects within the
 * system, however, a number of other things become possible. Device drivers
 * can export information and configuration variables that are independent
 * of any specific device.
 */
struct device_driver {
	const char                 *name;
	struct bus_type            *bus;                //驱动所属的总线
	struct module              *owner;
	const char                 *mod_name;	        /* used for built-in modules */
	bool                       suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id  *of_match_table;

	int  (*probe)   (struct device *dev);    //设备探测函数,用于探测设备是否可以被该驱动程序管理
	int  (*remove)  (struct device *dev);
	void (*shutdown)(struct device *dev);
	int  (*suspend) (struct device *dev, pm_message_t state);
	int  (*resume)  (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops    *pm;

	struct driver_private      *p;            //驱动管理的设备的链表在这里面
};


struct driver_private {
	struct kobject              kobj;
	struct klist                klist_devices; //该驱动所管理的设备链表头
	struct klist_node           knode_bus;
	struct module_kobject       *mkobj;
	struct device_driver        *driver;
};

3. sysfs文件系统模型
3.1 文件系统
    所谓"文件", 就是按一定的形式存储在介质上的信息,所以一个文件其实包含了两方面的信息,一是存储的数据本身,二是有关该文件的元数据(文件的组织和管理的信息)。在内存中, 每个文件都有一个dentry(目录项)inode(索引节点)结构,dentry记录着文件名,上级目录等信息,正是它形成了我们所看到的树状结构;而有关文件的组织和管理的信息主要存放inode里面,它记录着文件在存储介质上的位置与分布。同时dentry->d_inode指向相应的inode结构。dentry与inode是多对一的关系,因为有可能一个文件有好几个文件名。所有的dentry用d_parent和d_child连接起来,就形成了我们熟悉的树状结构。
    inode代表的是物理意义上的文件,通过inode可以得到一个数组,这个数组记录了文件内容的位置,如该文件位于硬盘的第3,8,10块,那么这个数组的内容就是3,8,10。其索引节点号inode->i_ino,在同一个文件系统中是唯一的,内核只要根据i_ino,就可以计算出它对应的inode在介质上的位置。就硬盘来说,根据i_ino就可以计算出它对应的inode属于哪个块(block),从而找到相应的inode结构。但对于某一种特定的文件系统而言,仅仅用inode还是无法描述出所有的文件系统(比如ext3,在内存中用ext3_inode_info描述。他是一个包含inode的"容器")。
struct inode {
	umode_t                 i_mode;
	unsigned short          i_opflags;
	uid_t                   i_uid;
	gid_t                   i_gid;
	unsigned int            i_flags;

	const struct inode_operations	*i_op;
	struct super_block	*i_sb;
	struct address_space	*i_mapping;

#ifdef CONFIG_SECURITY
	void                    *i_security;
#endif

	/* Stat data, not accessed from path walking */
	unsigned long           i_ino;
	/*
	 * Filesystems may only read i_nlink directly.  They shall use the
	 * following functions for modification:
	 *
	 *    (set|clear|inc|drop)_nlink
	 *    inode_(inc|dec)_link_count
	 */
	union {
		const unsigned int i_nlink;
		unsigned int __i_nlink;
	};
	dev_t                   i_rdev;
	struct timespec         i_atime;
	struct timespec         i_mtime;
	struct timespec         i_ctime;
	spinlock_t              i_lock;	/* i_blocks, i_bytes, maybe i_size */
	unsigned short          i_bytes;
	blkcnt_t	                i_blocks;
	loff_t                  i_size;

	/* Misc */
	unsigned long           i_state;
	struct mutex            i_mutex;

	unsigned long           dirtied_when;	/* jiffies of first dirtying */

	struct hlist_node       i_hash;
	struct list_head	i_wb_list;	/* backing dev IO list */
	struct list_head	i_lru;		/* inode LRU list */
	struct list_head	i_sb_list;
	union {
		struct list_head	        i_dentry;
		struct rcu_head         i_rcu;
	};
	atomic_t	                i_count;
	unsigned int            i_blkbits;
	u64                     i_version;
	atomic_t	                i_dio_count;
	atomic_t	                i_writecount;

	/* former ->i_op->default_file_ops */
	const struct file_operations    *i_fop;	
	struct file_lock	                *i_flock;
	struct address_space            i_data;
#ifdef CONFIG_QUOTA
	struct dquot            *i_dquot[MAXQUOTAS];
#endif
	struct list_head	i_devices;
	union {
		struct pipe_inode_info  *i_pipe;
		struct block_device     *i_bdev;
		struct cdev             *i_cdev;
	};

	__u32                   i_generation;
	……        
	void                    *i_private; /* fs or device private pointer */
};


struct dentry {
	/* RCU lookup touched fields */
	unsigned int         d_flags;           /* protected by d_lock */
	seqcount_t           d_seq;             /* per dentry seqlock */
	struct hlist_bl_node d_hash;            /* lookup hash list */
	struct dentry        *d_parent;         /* parent directory */
	struct qstr          d_name;
	struct inode         *d_inode;          /* Where the name belongs to - NULL is
	                                         * negative */
	unsigned char        d_iname[DNAME_INLINE_LEN];	  /* small names */

	/* Ref lookup also touches following */
	unsigned int         d_count;           /* protected by d_lock */
	spinlock_t           d_lock;            /* per dentry lock */
	const struct dentry_operations *d_op;
	struct super_block   *d_sb;             /* The root of the dentry tree */
	unsigned long        d_time;            /* used by d_revalidate */
	void                 *d_fsdata;         /* fs-specific data */

	struct list_head     d_lru;             /* LRU list */

	/* d_child and d_rcu can share memory */
	union {
		struct list_head d_child;       /* child of parent list */
	 	struct rcu_head  d_rcu;
	} d_u;
	struct list_head     d_subdirs;         /* our children */
	struct list_head     d_alias;           /* inode alias list */
};


我们要实现一种文件系统就是要实现VFS所定义的一系列接口: file_operations, dentry_operations, inode_operations等,供上层调用。file_operations是对每个具体文件的读写操作; dentry_operations, inode_operations则是对文件的属性(如改名字)建立或删除的操作。

struct file_operations {
	struct module *owner;
	loff_t (*llseek) (struct file *, loff_t, int);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	……
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	……
	int (*mmap) (struct file *, struct vm_area_struct *);
	int (*open) (struct inode *, struct file *);
	int (*flush) (struct file *, fl_owner_t id);
	int (*release) (struct inode *, struct file *);
	……
};


struct dentry_operations {
	int (*d_revalidate)(struct dentry *, struct nameidata *);
	int (*d_hash)(const struct dentry *, const struct inode *,
			struct qstr *);
	int (*d_compare)(const struct dentry *, const struct inode *,
			const struct dentry *, const struct inode *,
			unsigned int, const char *, const struct qstr *);
	int (*d_delete)(const struct dentry *);
	void (*d_release)(struct dentry *);
	void (*d_prune)(struct dentry *);
	void (*d_iput)(struct dentry *, struct inode *);
	char *(*d_dname)(struct dentry *, char *, int);
	struct vfsmount *(*d_automount)(struct path *);
	int (*d_manage)(struct dentry *, bool);
} ____cacheline_aligned;



struct inode_operations {
	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
	……

	int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *);
	int (*link) (struct dentry *,struct inode *,struct dentry *);
	int (*unlink) (struct inode *,struct dentry *);
	int (*symlink) (struct inode *,struct dentry *,const char *);
	int (*mkdir) (struct inode *,struct dentry *,umode_t);
	int (*rmdir) (struct inode *,struct dentry *);
	int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
	int (*rename) (struct inode *, struct dentry *,
			struct inode *, struct dentry *);
	……
} ____cacheline_aligned;

在2.4时代,不同文件系统索引节点的内存映像(ext3_inode_info,reiserfs_inode_info,msdos_inode_info ...)都是用一个union内嵌在inode数据结构中的. 但inode作为一种非常基本的数据结构而言,这样搞太大了,不利于快速的分配和回收。但是后来发明了container_of(...)这种方法后,就把union移到了外部,我们可以用类似container of(inode, struct ext3_inode_info, vfs_inode),从inode出发,得到其的"容器"。

//创建/sys/devices、/sys/dev 、/sys/dev/block、/sys/dev/char、/sys/bus、/sys/devices/system...
do_basic_setup(void)
+-- driver_init();
    +-- devices_init();
        +-- devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
        +-- dev_kobj             = kobject_create_and_add("dev", NULL);                   
        +-- sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); 
        +-- sysfs_dev_char_kobj  = kobject_create_and_add("char", dev_kobj);  
    +-- buses_init();
        +-- bus_kset    = kset_create_and_add("bus", &bus_uevent_ops, NULL); 
        +-- system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj); 
    +-- classes_init();
        +-- class_kset  = kset_create_and_add("class", NULL, NULL);
    +-- firmware_init();
        +-- firmware_kobj   = kobject_create_and_add("firmware", NULL);
    +-- hypervisor_init();
        +-- hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
    +-- platform_bus_init();
        +-- device_register(&platform_bus);
        +-- bus_register(&platform_bus_type);
    +-- cpu_dev_init();
        +-- subsys_system_register(&cpu_subsys, cpu_root_attr_groups)
    +-- memory_dev_init();
        +-- subsys_system_register(&memory_subsys, NULL);





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值