sysfs是linux 内核从2.6中开始引入的设备管理模型,该模型通过一个虚拟的文件系统sysfs 将整个硬件的层级模型显现和组织起来,并将其采用矩阵式管理方式,还是支持热插拔等功能,该设备模型自从2.6内核引入至今 到5.0以上版本都没有经过大改,说明了该模型兼容性较好,能够不断适应新的硬件发展。

sysfs文件系统将每个设备抽象成文件,并将其组织形式如下:

一个usb 的鼠标设备mouse 1, 其设备类型class为输入设备,同时usb总线 buses类型中有归属与usb-hid, 在deivces一个驱动设备中其属于usb2 中的port 1端口设备dev1:1-0,采用类似一个矩阵式管理形式。

sysfs文件系统,将所有的设备都在sys目录内进行组织:

sys目录解释如下:

  • block:包含所有的块设备。
  • bus:包含所有的总线类型。
  • class: 包含所有的设备类型。
  • dev::包括所有的块设备和字符设备,该目录下维护一个按照字符设备和块设备的主次号码(major:minor)链接到真是设备(/sys/devices)的符号链接文件。
  • devices:包括系统中所有的设备并根据设备挂接的总线类型组织层次结构。
  • firmware:含对固件对象(firmware object)和属性进行操作和观察的接口。
  • fs:该目录使用来描述系统中所有的文件系统,包括文件系统本身和按照文件系统分类存放的已挂载点。
  • hypervisor:该目录是与虚拟化Xen相关的装置。
  • module: 该目录下有系统中所有的模块信息,不论这些模块是以内联(inlined)方式编译到内核映像文件中还是编译为外模块(.ko文件),都可能出现在/sys/module中。即module目录下包含了所有的被载入kernel的模块。
  • power:该目录是系统中的电源选项,对正在使用的power子系统的描述。这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机/重启等等。

kobject

内核sysfs文件系统使用kobject将上述图片中的各个对象链接起来,并组成一个分层的结构体系,内核为sysfs文件目录内的每个目录都创建一个kobject结构,kobject是sysfs文件系统的最基本的管理单元,相当于面向对象中的最顶层基类,其他类型都相当与是对kobject的派生类。

在linux 5.4.56 内核版本中,kobject结构如下

struct kobject {const char       *name;struct list_head  entry;struct kobject        *parent;struct kset     *kset;struct kobj_type  *ktype;struct kernfs_node   *sd; /* sysfs directory entry */struct kref     kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASEstruct delayed_work  release;
#endifunsigned 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;
};

先对比较简单

  • name:为该koject 的name,相当于sysfs内的目录名称。
  • entry:为一个链接结构,用于将其他kobject结构链接起来
  • parent: 指向该kobject的父kobject,即相当于该kobejct的父目录。
  • kset::相同类型的kobject集合,指向该kobject归属于哪个kset(详细后面描述)
  • ktype: 指向该对象类型,里面包含了对该对象的一些操作以及默认属性。
  • sd:  syfs目录节点,所有的kobject都以kernfs_node节点挂载到syfs 管理文件中,在内核中所有节点的根root节点为struct kernfs_node *sysfs_root_kn(位于mount.c文件中),sysfs会遍历sysfs_root_kn内的所有节点。
  • kref: kobject计数,当该计数为0时,该kobject将会释放。
  • 其他状态:其他为描述该kobject类型。

kobject 主要实现及接口实现主要位于lib/kobject.c文件。

在内核模块中对外提供的API主要如下:

API名称 作用及描述
void kobject_init(struct kobject *kobj, struct kobj_type *ktype) 非GPL接口, kobject初始化函数,需要提供kobj_type
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,  struct kobject *parent, const char *fmt, ...) 初始化kobject,并将其加入到sysfs文件系统中
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent) 创建一个kobject 并将其加入到指向的parent中,如果parent为NULL,则指向的时sys根目录,如block等
int kobject_rename(struct kobject *kobj, const char *new_name) 重新修改kobj name
int kobject_move(struct kobject *kobj, struct kobject *new_parent) 将该kobject从parent中移除掉
int kobject_set_name(struct kobject *kobj, const char *fmt, ...) 非GPL接口,设置kobject name
int kobject_add(struct kobject *kobj, struct kobject *parent,    const char *fmt, ...) 非GPL接口,添加kobject接口到parent中
void kobject_del(struct kobject *kobj) 非GPL接口,删除该kobject
struct kobject *kobject_get(struct kobject *kobj) 非GPL接口, 获取kobject,会增加kobject中的 kref计数
int kset_register(struct kset *k) 初始化并注册kobject
void kobject_put(struct kobject *kobj) 减少kobject中的计数,一般kobject释放 并 不直接释放而是通过该接口通过减少计数,直到为0时进行释放
void kset_unregister(struct kset *k) 去注册kobject

用例一:kobject使用

下面为一个最基本简单 用例,使用上述API,编写一个内核模块,实现在sys的根目录内创建一个test目录,与block、dev等目录平行:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
MODULE_LICENSE("GPL v2");static struct kobject * testKobj = NULL;
static int __init sysfs_test_init(void)
{testKobj = kobject_create_and_add("test", NULL);if (!testKobj){printk(KERN_INFO "create test kbject failed\n");return 1;}return 0;
}static void __exit sysfs_test_exit(void)
{kobject_put(testKobj);
}module_init(sysfs_test_init);
module_exit(sysfs_test_exit);
MODULE_AUTHOR("hzk");
MODULE_DESCRIPTION("A simple moudule for sysft test");
MODULE_VERSION("V1.0");

,makefile如下

obj-m :=test_sysfs.o
KERNEL :=/usr/src/linux-headers-5.4.0-56-generic
#KERNEL :=/usr/src/kernels/3.10.0-957.el7.x86_64
PWD :=$(shell pwd)
modules:make -C $(KERNEL) M=$(PWD) modules
clean:rm -f *.o *.ko
~                      

运行结果如下在sys根目录下生成test目录

kobj_type

通过上述简单用例主要为kobject的基本使用规则,在kobject中还有一个重要的数据结构为kobj_type结构,主要提供koj类型,主要数据结构如下:

struct kobj_type {void (*release)(struct kobject *kobj);const struct sysfs_ops *sysfs_ops;struct attribute **default_attrs;  /* use default_groups instead */const struct attribute_group **default_groups;const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);const void *(*namespace)(struct kobject *kobj);void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};

下面将依次说明上述kobj_type中的主要数据结构

  • release: 在linux内核驱动代码中,由于创建者在创建完成kobject之后,供用户程序进行使用,但是通常在内核驱动生命周期中,其实并无法预知该kobject何时被释放,故在设计kobject数据结构时,采用引用计数方法来记录,当引用计数为0时可以释放该kobject,而通常在内核驱动程序中经常会在kobjct基础上外挂一些数据,所以当该kobject释放时需要同时释放该驱动的一些数据,故需要提供release 回调给驱动程序用于释放一些数据。
  • default_attrs: 一般在每个sysfs目录内都会存在一些该目录的属性,使应用程序可以与内核进行交互。
  • syfs_ops:为内核提供的与数据交互的一些接口一般包含show和restore两个功能。

在linux内核内部提供一个默认的kobj_type,故如果一个驱动没有特殊要求,可以不设置,使用默认dynamic_kobj_ktype

static void dynamic_kobj_release(struct kobject *kobj)
{pr_debug("kobject: (%p): %s\n", kobj, __func__);kfree(kobj);
}static struct kobj_type dynamic_kobj_ktype = {.release    = dynamic_kobj_release,.sysfs_ops  = &kobj_sysfs_ops,
};

kobj_sysfs_ops 实现如下:

/* default kobject attribute operations */
static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,char *buf)
{struct kobj_attribute *kattr;ssize_t ret = -EIO;kattr = container_of(attr, struct kobj_attribute, attr);if (kattr->show)ret = kattr->show(kobj, kattr, buf);return ret;
}static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,const char *buf, size_t count)
{struct kobj_attribute *kattr;ssize_t ret = -EIO;kattr = container_of(attr, struct kobj_attribute, attr);if (kattr->store)ret = kattr->store(kobj, kattr, buf, count);return ret;
}const struct sysfs_ops kobj_sysfs_ops = {.show    = kobj_attr_show,.store    = kobj_attr_store,
};

用例二:kobj_type

在上述用例一基础上,提供进行简单修改,提供kobj_type的release功能:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL v2");static struct kobject * testKobj = NULL;static void test_sysfs_release(struct kobject * kobj)
{printk(KERN_INFO "test sysfs release\n");kfree(kobj);
}static struct kobj_type test_type = {//.sysfs_ops = &test_sysfs_ops,.release   = test_sysfs_release,// .default_groups = test_sys_groups,
};
static int __init sysfs_test_init(void)
{int ret = 0;testKobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);if (!testKobj){printk(KERN_INFO "kzalloc kobject failed\n");\return 1;}ret = kobject_init_and_add(testKobj, &test_type, NULL, "test");if (ret){printk(KERN_INFO "int and add kbject failed\n");return 1;}return 0;
}static void __exit sysfs_test_exit(void)
{kobject_put(testKobj);
}module_init(sysfs_test_init);
module_exit(sysfs_test_exit);
MODULE_AUTHOR("hzk");
MODULE_DESCRIPTION("A simple moudule for sysft test");
MODULE_VERSION("V1.0");

将kobject改为动态申请,这样当引用计数为0时,  需要收到释放动态申请的kobject,需要在kobj_type 中设置该驱动模块的release函数,该用例也是内核源码中释放kobject实现的一个原理。

attribute

attribute属性为该sys目录内的一些属性值,一般用于驱动程序与用户交互的数据等,attribute结构如下:

struct attribute {const char     *name;umode_t           mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOCbool          ignore_lockdep:1;struct lock_class_key  *key;struct lock_class_key  skey;
#endif
};
  • name:为该属性名称
  • mode:为该属性读写权限,按照通常的rwx以及root 用户 group进行组合。

其用法一般需要结合sysfs_ops,用户对该属性的读写操作

struct sysfs_ops {ssize_t    (*show)(struct kobject *, struct attribute *, char *);ssize_t   (*store)(struct kobject *, struct attribute *, const char *, size_t);
};

用例三:默认attribute

attribute主要有两种方法,第一种方式是在创建kobject时通过在struct kobj_type 结构中指定默认attribue方式。

在用例二的基础上进一步进行改进,对test目录内提供两个属性,属性名称分别为name和para

include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
MODULE_LICENSE("GPL v2");static struct kobject * testKsetKobj = NULL;static ssize_t test_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
{struct kobj_attribute * obj_attr = NULL;obj_attr = container_of(attr,struct kobj_attribute, attr);if (!obj_attr->show){return 0;}return obj_attr->show(kobj, obj_attr, buf);
}static ssize_t test_attr_store(struct kobject *kobj, struct attribute * attr, const char *buf, size_t len)
{struct kobj_attribute * obj_attr = NULL;obj_attr = container_of(attr,struct kobj_attribute, attr);if (!obj_attr->store){return 0;}return obj_attr->store(kobj, obj_attr, buf, len);
}static const struct sysfs_ops test_sysfs_ops ={.show = test_attr_show,.store = test_attr_store,
};
static void test_kset_release(struct kobject *kobj)
{printk(KERN_INFO "test kset relsase\n");kfree(kobj);
}
static ssize_t sysfs_test_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{return sprintf(buf,"hello world\n");
}static ssize_t sysfs_test_store(struct kobject *kobj, struct kobj_attribute * attr, const char * buf, size_t count)
{printk(KERN_INFO "sys test module recv: %s\n", buf);return count;
}
static struct kobj_attribute testName =__ATTR(name, 0664,sysfs_test_show,sysfs_test_store);static struct kobj_attribute testPara =__ATTR(para, 0664,sysfs_test_show,sysfs_test_store);static struct attribute *test_sys_attrs[] = {&testName.attr,&testPara.attr,NULL,
};ATTRIBUTE_GROUPS(test_sys);static struct kobj_type test_ktype = {.sysfs_ops = &test_sysfs_ops,.release   = test_kset_release,.default_groups = test_sys_groups,
};
static int __init kset_test_init(void)
{testKsetKobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);if(!testKsetKobj){printk(KERN_INFO "create and add kset kobject failed\n");return 1;}if (kobject_init_and_add(testKsetKobj, &test_ktype, NULL,"test")){kfree(testKsetKobj);return 1;}return 0;
}
static void __exit kset_test_exit(void)
{kobject_put(testKsetKobj);
}module_init(kset_test_init);
module_exit(kset_test_exit);
MODULE_AUTHOR("hzk");
MODULE_DESCRIPTION("A simple moudule for sysft test");
MODULE_VERSION("V1.0");

执行结果如下:

用例四:非默认attribute

除了上述用例三在创建kobject时借助kobj_type 中的default_attrs来创建默认属性,sysfs还提供了专用接口用于创建一个非默认attribute 接口如下:

int sysfs_create_group(struct kobject *kobj,  const struct attribute_group *grp)

attribute_group定义如下:

struct attribute_group {const char       *name;umode_t           (*is_visible)(struct kobject *,struct attribute *, int);umode_t         (*is_bin_visible)(struct kobject *,struct bin_attribute *, int);struct attribute    **attrs;struct bin_attribute    **bin_attrs;
};

通过在attrs中指定要创建的attribute。

include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
MODULE_LICENSE("GPL v2");static struct kobject * testKobj = NULL;
static struct kobject * testkobj_hello = NULL;static ssize_t sysfs_test_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{return sprintf(buf,"hello world\n");
}static ssize_t sysfs_test_store(struct kobject *kobj, struct kobj_attribute * attr, const char * buf, size_t count)
{printk(KERN_INFO "sys test module recv: %s\n", buf);return count;
}
static struct kobj_attribute testName =__ATTR(name, 0664,sysfs_test_show,sysfs_test_store);static struct kobj_attribute testPara =__ATTR(para, 0664,sysfs_test_show,sysfs_test_store);
static struct attribute *testAttr[] = {&testName.attr,&testPara.attr,NULL,
};
static struct attribute_group testGroup = {.attrs = testAttr,
};
static int __init sysfs_test_init(void)
{testKobj = kobject_create_and_add("test", NULL);if (!testKobj){printk(KERN_INFO "create test kbject failed\n");return 1;}testkobj_hello = kobject_create_and_add("hello", testKobj);if (!testkobj_hello){printk(KERN_INFO "create test hello kbject failed\n");return 1;}sysfs_create_group(testkobj_hello, &testGroup);return 0;
}static void __exit sysfs_test_exit(void)
{sysfs_remove_group(testkobj_hello,&testGroup);kobject_put(testkobj_hello);kobject_put(testKobj);
}module_init(sysfs_test_init);
module_exit(sysfs_test_exit);
MODULE_AUTHOR("hzk");
MODULE_DESCRIPTION("A simple moudule for sysft test");
MODULE_VERSION("V1.0");

运行结果如下:

内嵌kobject和attribute

一般kobject和attribute很少单独使用,单独使用一般都没有太多意义,内核和驱动工程师很少单独创建一个kobject和 单独使用attribute,内核中在上述的基础上提供了更高一层级的使用方法,而kobject和attribute作为内嵌到其中,相当于C++面向对象中的派生类,例如字符设备cdev结构:

struct cdev {struct kobject kobj;struct module *owner;const struct file_operations *ops;struct list_head list;dev_t dev;unsigned int count;
} __randomize_layout;

kobject是sysfs的管理基本单位,很多时候在编写release,show或者其他函数中需要根据传入的kobject参数获取到cdev整个结构的地址,就需要使用到内核中的container_of结构,例如在上述cdev结构需要根据提供的kobj,获取到cdev结构,使用方法如下:

struct cdev * device  = container_of(kp, struct cdev, kobj);

attribute使用方法类似,内核中提供了各种各样的基于attribute的扩展属性,例如在kobject模块中就存在一个默认的kobj_attribute属性,定义如下:

struct kobj_attribute {struct attribute attr;ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,char *buf);ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t count);
};

其使用方法同样如下

struct kobj_attribute * kattr = container_of(attr, struct kobj_attribute, attr);

这样类似的嵌入结构在内核的数据结构中非常常见。

kset

kset为相同类型的kobject集合,为kobject更高一级的组织形式,其数据结构主要如下:

struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;
  • list::用于链接kset中所有kobject的链表 头部
  • list_lock:为list锁
  • kobj:为内嵌的kobject,其kset本身也可以认为是一个kobject.
  • uevent_ops为:事件操作集合

内核主要提供kset相关API如下:

API 作用及说明
struct kset *kset_create_and_add(const char *name,   const struct kset_uevent_ops *uevent_ops,    struct kobject *parent_kobj) 生成并添加一个kset
struct kobject *kset_find_obj(struct kset *kset, const char *name) 从kset中查找该名为name的kobject
int kset_register(struct kset *k) 注册一个kset
void kset_unregister(struct kset *k) 去注册kset

kset使用方法需要按照一定的套路来实现:

1:首先创建一个kset

2: 创建一个kobject,并将该kobject指向该kset

3:将kobject添加到sysfs,此时不需要指定parent,可以根据设置的kset 自动按照所属的kset层级进行添加

include <linux/init.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
MODULE_LICENSE("GPL v2");static struct kobject * testKobj = NULL;
static struct kset    * testKset = NULL;
static struct kobject * testKsetKobj = NULL;
static struct kobject * testKsetKobj2 = NULL;static ssize_t test_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
{struct kobj_attribute * obj_attr = NULL;obj_attr = container_of(attr,struct kobj_attribute, attr);if (!obj_attr->show){return 0;}return obj_attr->show(kobj, obj_attr, buf);
}static ssize_t test_attr_store(struct kobject *kobj, struct attribute * attr, const char *buf, size_t len)
{struct kobj_attribute * obj_attr = NULL;obj_attr = container_of(attr,struct kobj_attribute, attr);if (!obj_attr->store){return 0;}return obj_attr->store(kobj, obj_attr, buf, len);
}static const struct sysfs_ops test_sysfs_ops ={.show = test_attr_show,.store = test_attr_store,
};
static void test_kset_release(struct kobject *kobj)
{printk(KERN_INFO "test kset relsase\n");
}static ssize_t sysfs_test_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{return sprintf(buf,"hello world\n");
}static ssize_t sysfs_test_store(struct kobject *kobj, struct kobj_attribute * attr, const char * buf, size_t count)
{printk(KERN_INFO "sys test module recv: %s\n", buf);return count;
}
static struct kobj_attribute testName =__ATTR(name, 0664,sysfs_test_show,sysfs_test_store);static struct kobj_attribute testPara =__ATTR(para, 0664,sysfs_test_show,sysfs_test_store);static struct attribute *test_sys_attrs[] = {&testName.attr,&testPara.attr,NULL,
};
ATTRIBUTE_GROUPS(test_sys);static struct kobj_type test_ktype = {.sysfs_ops = &test_sysfs_ops,.release   = test_kset_release,.default_groups = test_sys_groups,
};
static int __init kset_test_init(void)
{testKobj = kobject_create_and_add("test", NULL);if (!testKobj){printk(KERN_INFO "create test kbject failed\n");return 1;}testKset = kset_create_and_add("kset_test", NULL, testKobj);if (!testKset){printk(KERN_INFO "create and add kset failed\n");kobject_put(testKobj);return 1;}testKsetKobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);if(!testKsetKobj){printk(KERN_INFO "create and add kset kobject failed\n");kset_unregister(testKset);kobject_put(testKobj);return 1;}testKsetKobj2 = kzalloc(sizeof(struct kobject), GFP_KERNEL);if(!testKsetKobj2){printk(KERN_INFO "create and add kset kobject2 failed\n");kset_unregister(testKset);kobject_put(testKobj);return 1;}testKsetKobj->kset=testKset;if (kobject_init_and_add(testKsetKobj, &test_ktype, NULL,"test_para")){kset_unregister(testKset);kobject_put(testKsetKobj);kobject_put(testKobj);return 1;}testKsetKobj2->kset=testKset;if (kobject_init_and_add(testKsetKobj2, &test_ktype, NULL,"test_para_2")){kset_unregister(testKset);kobject_put(testKsetKobj);kobject_put(testKsetKobj2);kobject_put(testKobj);return 1;}return 0;
}
static void __exit kset_test_exit(void)
{kset_unregister(testKset);kobject_put(testKsetKobj);kobject_put(testKsetKobj2);kobject_put(testKobj);
}module_init(kset_test_init);
module_exit(kset_test_exit);
MODULE_AUTHOR("hzk");
MODULE_DESCRIPTION("A simple moudule for sysft test");
MODULE_VERSION("V1.0");

创建一个kset 名称为kset_test,该kset下面有两个kobject 分别为test_para和test_para_2, 该每个下面都有两个相同名称的属性name和para,

kset 与 kobj_type

kset侧重于对相同类型的kobject的集合,而kobject_type关心的是kobject 对象的类型,两者用途不同。

kset内的所有kobject具有相同的属性,所以kset经常被用户相同设备类型驱动但是有多个设备场景,每个设备的sys目录下都具有相同的属性。

subsystem

在早期得sysfs的系统设计中,kset之上还有更高一个层级的设计为subsystem系统抽象,该结构为一系列的kset集合,为更高一层的抽象,其实本质上subsystem为相同类型的kobject的集合和kse的概念有点相重合,在后来版本中将该结构进删除,删除补丁为:

driver core patches for 2.6.23

该部分在现代内核代码中已经灰飞烟灭,故不再描述该功能 。

linux 内核设备管理模型sysfs(入门篇)相关推荐

  1. linux 内核设备管理模型sysfs(进阶篇)

    <linux 内核设备管理模型sysfs(入门篇)>讲述了内核设备管理模型sysfs的基础管理单元kobject和kset,但是在实际过程中很少有驱动工程师有机会直接操作上述结构,linu ...

  2. linux 内核模型,The Linux Kernel Device Model - Overview -- Linux 内核设备模型概述

    --------------------------------------------------------------------------------------------------- ...

  3. Scala进阶之路-并发编程模型Akka入门篇

    Scala进阶之路-并发编程模型Akka入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Akka Actor介绍 1>.Akka介绍 写并发程序很难.程序员不得不处 ...

  4. 【Linux内核系列】百分百干货篇丨不要错过,5个方面分析内核架构,让你对内核不再陌生

    5个方面分析内核架构,让你对内核不再陌生 1. 内存管理 mm_struct 2. 进程管理 task_struct 3. 网络协议栈 sk_buff 4. 文件系统 super_block 5. 设 ...

  5. 和菜鸟一起学linux内核源码之启动篇

    又是一个周末,日子过得比较散,虽然期间也有不断地看书学习,总觉得有点小盲目.想想毕业也快要1年了,从事嵌入式linux的研发工作也1年多了.这1年多的从实习到正式工作到现在的自己,进步有,也很大,但是 ...

  6. linux 内核驱动模型,linux设备驱动模型架构分析 一

    linux设备驱动模型架构分析 一 发布时间:2018-07-04 15:14, 浏览次数:584 , 标签: linux 概述 LDD3中说:"Linux内核需要一个对系统结构的一般性描述 ...

  7. linux内核基本模型,Linux设备模型(1)_基本概念

    Linux设备模型(1)_基本概念 作者:wowo 发布于:2014-2-27 17:01 分类:统一设备模型 1. 前言 在"Linux内核的整体架构"中,蜗蜗有提到,由于Lin ...

  8. 学习linux内核-- 内存,看一篇就够了(多图)

    内存模块 1 linux内存总体布局:内存分成用户态和内核态 4G进程地址空间解析 内核地址空间 进程地址空间 2 地址转换和页表 2.1 地址转换 虚拟内存是指程序使用的逻辑地址.每个进程4G.所有 ...

  9. Linux学习 第一期 Ubuntu入门篇

    第1讲 开发电脑的选择 一.开发电脑要求 1.1.CPU要求 4核8线程,2核编译代码性能?编译大工程的时候很耗费CPU,编译QT大概要很久. 核心越多越好,主频越高越好. 1.2.内存要求 最少16 ...

最新文章

  1. APUE和UNP怎么学?
  2. SpringBoot ElasticSearch 全文搜索
  3. 怎么找回失踪的NTLDR文件
  4. 【PAT乙级】1030 完美数列 (25 分)
  5. PHP的require与include
  6. Vue.JS项目输入框中使用v-model导致number类型值自动转换成string问题的解决方案
  7. Qt简介以及如何配置Qt使用VS2010进行开发
  8. Atom飞行手册翻译: 4.1 配置API
  9. 局域网只看到少数电脑_利用局域网高速传输大文件的两种方法
  10. 广西(柳州)创建国家级车联网先导区建设方案
  11. 机器学习数学基础十:相关分析
  12. 把基础打牢了,将来就可以触类旁通,行行都可以写出精彩
  13. 笔记本重装系统后office没了
  14. 华硕灵耀pro16参数 华硕灵耀pro16怎么样
  15. 单线双向模块_UART学习
  16. 转载 RINEX 中观测值的类型
  17. 读《Spring 实战(第四版)》第三章 高级装配
  18. Ansys workbench 17.2 学习笔记
  19. python 股票_十分钟学会用Python交易股票
  20. CSS标准颜色值查找 16进制10进制颜色值表 颜色中英文名称 在线颜色配色对比效

热门文章

  1. 如何实现快速高效开发?低代码平台jeecgboot完美解决—jeecgboot3.1新特性
  2. Javascript调试之console对象,它的一些小技巧你都知道吗?
  3. jeecg 如何重新加载当前渲染tab页面
  4. JAVA与SAP数据交互的方式总结
  5. Eclipse导入类库【Java】
  6. AutoKeras使用
  7. Linux IPC实践(10) --Posix共享内存
  8. MySQL学习笔记_10_MySQL高级操作(下)
  9. python3 函数注意要点
  10. Percona XtraBackup热备份实践