linux设备模型
- 格式:doc
- 大小:246.50 KB
- 文档页数:34
linux系统结构框架
Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。
内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。
1.内核:内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理等。
2.Shell:shell是命令行解释器,可以为用户提供对系统的访问,也可以被用作程序或者脚本的命令行环境。
有多种shell可以选择,比如bash,zsh,ksh等。
3.文件系统:Linux系统使用一个基于文件的层级结构来组织和存储系统资源。
每个文件和目录都从根目录“/”开始,然后层层嵌套。
4.应用程序:Linux系统上可以运行各种应用程序,包括文本编辑器、浏览器、开发工具等。
应用程序为用户提供了使用系统的接口。
在更细致的层次结构上,Linux系统的内存管理分为几个主要组件,包括物理内存管理、虚拟内存管理以及内核内存管理等。
物理内存管理负责物理内存的分配和回收,虚拟内存管理则将物理内存映射到虚拟地址空间,并实现内存的共享和保护。
内核内存管理则负责内核空间的分配和释放,以及内核页面的交换等。
Linux设备模型的关键之一:Uevent1. Uevent的功能Uevent是Kobject的一部分,用于在Kobject状态发生改变时,例如增加、移除等,通知用户空间程序。
用户空间程序收到这样的事件后,会做相应的处理。
该机制通常是用来支持热拔插设备的,例如U盘插入后,USB相关的驱动软件会动态创建用于表示该U盘的device结构(相应的也包括其中的kobject),并告知用户空间程序,为该U盘动态的创建/dev/目录下的设备节点,更进一步,可以通知其它的应用程序,将该U盘设备mount到系统中,从而动态的支持该设备。
2. Uevent在kernel中的位置下面图片描述了Uevent模块在内核中的位置:由此可知,Uevent的机制是比较简单的,设备模型中任何设备有事件需要上报时,会触发Uevent提供的接口。
Uevent模块准备好上报事件的格式后,可以通过两个途径把事件上报到用户空间:一种是通过kmod模块,直接调用用户空间的可执行文件;另一种是通过netlink通信机制,将事件从内核空间传递给用户空间。
注1:有关kmod和netlink,会在其它文章中描述,因此本文就不再详细说明了。
3. Uevent的内部逻辑解析3.1 Source Code位置Uevent的代码比较简单,主要涉及kobject.h和kobject_uevent.c两个文件,如下:include/linux/kobject.hlib/kobject_uevent.c3.2 数据结构描述kobject.h定义了uevent相关的常量和数据结构,如下:kobject_action1: /* include/linux/kobject.h, line 50 */2: enum kobject_acTIon {。
linux分层设计体系结构Linux是一种开源的操作系统,其设计采用了分层的体系结构。
这种设计使得Linux具有高度的灵活性和可扩展性,同时也方便了系统的维护和管理。
本文将详细介绍Linux的分层设计体系结构。
在Linux的分层设计中,最底层是硬件层。
硬件层包括计算机的各种硬件设备,如处理器、内存、硬盘、网络接口等。
Linux通过设备驱动程序来管理和控制这些硬件设备,使其能够与操作系统进行交互。
在硬件层之上是内核层。
内核是操作系统的核心,负责管理系统的资源和提供各种系统服务。
Linux的内核是一个单独的模块,可以独立于其他软件进行开发和维护。
内核提供了各种系统调用接口,以及对进程、文件系统、网络和设备的管理和控制功能。
在内核层之上是库层。
库是一组共享的代码和函数,可以为应用程序提供常用的功能和服务。
Linux提供了许多不同的库,如C库、数学库、网络库等。
这些库可以被开发人员用来开发应用程序,提高开发效率和代码复用性。
在库层之上是应用层。
应用层包括各种应用程序和工具,如文本编辑器、图形界面、网络浏览器等。
这些应用程序可以通过系统调用接口与内核进行交互,并利用库提供的功能来实现各种任务和操作。
除了以上四个层次外,Linux还有其他一些重要的组件和模块。
例如,系统初始化和启动过程中,会加载引导程序和初始化程序;文件系统是用来组织和管理文件和目录的;网络协议栈是用来实现网络通信的;系统服务是用来提供各种系统功能和服务的。
这些组件和模块与其他层次之间相互关联,共同构成了Linux的完整体系结构。
Linux的分层设计体系结构具有许多优点。
首先,分层设计使得系统的各个组件和模块之间相互独立,可以分别进行开发、测试和维护,提高了开发和维护效率。
其次,分层设计使得系统的各个层次之间的接口清晰明确,方便了系统的扩展和升级。
此外,分层设计还提高了系统的稳定性和可靠性,一旦某个层次出现问题,不会对其他层次造成影响。
Linux的分层设计体系结构是一种高效、灵活和可扩展的设计方式。
Linux设备驱动程序学习(15)-Linux设备模型(热插拔、mdev 与firmware)热插拔有2 个不同角度来看待热插拔:从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。
从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和mdev)的交互。
当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。
现在的计算机系统,要求Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。
这就对设备驱动作者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。
热插拔工具当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在/proc/sys/kernel/hotplug文件里查找处理设备连接的用户空间程序。
这个用户空间程序主要有hotplug:这个程序是一个典型的bash 脚本,只传递执行权给一系列位于/etc/hot-plug.d/ 目录树的程序。
hotplug 脚本搜索所有的有 .hotplug 后缀的可能对这个事件进行处理的程序并调用它们, 并传递给它们许多不同的已经被内核设置的环境变量。
(基本已被淘汰,具体内容请参阅《LDD3》)udev :用于linux2.6.13或更高版本的内核上,为用户空间提供使用固定设备名的动态/dev目录的解决方案。
它通过在sysfs 的/class/ 和/block/ 目录树中查找一个称为dev 的文件,以确定所创建的设备节点文件的主次设备号。
所以要使用udev,驱动必须为设备在sysfs中创建类接口及其dev属性文件,方法和sculld模块中创建dev属性相同。
udev的资料网上十分丰富,我就不在这废话了,给出以下链接有兴趣的自己研究:mdev:一个简化版的udev,是busybox所带的程序,十分适合嵌入式系统。
因为hotplug现在也在被慢慢地淘汰,udev不再依赖hotplug了,所以这里不再介绍;udev较mdev复杂,不太适合嵌入式使用。
linux分层设计体系结构Linux分层设计体系结构是一种将Linux操作系统的各个组件和功能分层组织的方式,以实现模块化设计、可维护性和可扩展性。
以下是Linux分层设计体系结构的主要层级:1. 用户接口层:这是用户与Linux系统交互的界面层,包括Shell、命令行工具和图形用户界面。
用户通过这一层来执行操作系统的命令和访问系统资源。
2. 系统调用接口层:这一层提供给应用程序访问Linux内核所提供的功能的接口。
它包括一系列的系统调用(system call),应用程序可以通过这些系统调用来请求内核执行某些操作,例如文件操作、进程控制等。
3. 库函数层:这一层提供了一系列的函数库,供应用程序调用。
这些函数库封装了一些常用的操作,如字符串操作、文件操作、网络操作等。
应用程序通过调用这些函数库来实现特定的功能。
4. 内核层:这一层是操作系统的核心,负责管理和控制计算机的硬件资源,提供各种功能和服务。
Linux内核包含多个子系统,如进程管理、文件系统、网络协议栈、设备驱动等。
5. 设备驱动层:这一层负责与硬件设备进行交互,通过提供特定的接口和功能来控制和管理设备。
设备驱动层包括字符设备驱动、块设备驱动、网络设备驱动等。
6. 硬件层:这一层是真实的物理硬件,包括处理器、内存、外设等。
硬件层由设备驱动来访问和控制。
通过将Linux系统划分为不同的层次,分层设计体系结构提供了一种模块化的方式来开发、维护和扩展Linux系统。
每个层级都有明确定义的职责和接口,不同层级之间的依赖关系也得到了良好的管理。
这种设计使得Linux系统更加灵活、可维护和可扩展。
linux操作系统的基本体系结构一、内核(Kernel)Linux操作系统的核心是内核,它负责管理系统资源、控制硬件设备、调度进程和提供基本的系统服务。
Linux内核采用单内核结构,包含了操作系统的大部分核心功能和驱动程序。
内核是操作系统的核心组件,它提供了操作系统运行所必须的基本功能。
Linux内核具有以下特点:1、多任务处理:Linux内核支持多任务处理,可以同时运行多个程序,并实现多个程序之间的切换和管理。
2、硬件管理:Linux内核负责管理硬件设备,与硬件设备交互,控制硬件设备的工作状态。
3、内存管理:Linux内核负责管理系统的内存,包括内存的分配、释放、映射和交换等操作。
4、文件系统:Linux内核支持多种文件系统,包括ext4、NTFS、FAT等,负责文件的读写、管理和保护。
5、进程管理:Linux内核管理系统进程,包括进程的创建、调度、挂起、唤醒和终止等操作。
6、网络通信:Linux内核支持网络通信功能,包括TCP/IP协议栈、网卡驱动等,实现网络数据传输和通信。
二、ShellShell是Linux操作系统的命令解释器,用户通过Shell与操作系统进行交互。
Shell接受用户的命令,并将其转换为对应的系统调用,最终由内核执行。
Linux系统中常用的Shell有Bash、Zsh等,用户可以根据自己的喜好选择不同的Shell。
Shell具有以下功能:1、命令解释:Shell接受用户输入的命令,并将其翻译为操作系统可以执行的命令。
2、执行程序:Shell可以执行各种程序、脚本和命令,包括系统工具、应用程序等。
3、环境控制:Shell可以设置环境变量、别名和路径等,帮助用户管理系统环境。
4、文件处理:Shell可以处理文件操作,包括创建、删除、复制、移动等。
5、脚本编程:Shell支持脚本编程,用户可以编写Shell脚本来自动执行一系列操作。
三、系统工具Linux操作系统提供了丰富的系统工具,帮助用户管理系统和执行各种任务。
linux内核sysfs详解【转】转⾃:"sysfs is a ram-based filesystem initially based on ramfs. It provides a meansto export kernel data structures, their attributes, and the linkages between them touserspace.” --- documentation/filesystems/sysfs.txt可以先把documentation/filesystems/sysfs.txt读⼀遍。
⽂档这种东西,真正读起来就嫌少了。
Sysfs⽂件系统是⼀个类似于proc⽂件系统的特殊⽂件系统,⽤于将系统中的设备组织成层次结构,并向⽤户模式程序提供详细的内核数据结构信息。
去/sys看⼀看,localhost:/sys#ls /sys/block/ bus/ class/ devices/ firmware/ kernel/ module/ power/Block⽬录:包含所有的块设备Devices⽬录:包含系统所有的设备,并根据设备挂接的总线类型组织成层次结构Bus⽬录:包含系统中所有的总线类型Drivers⽬录:包括内核中所有已注册的设备驱动程序Class⽬录:系统中的设备类型(如⽹卡设备,声卡设备等)sys下⾯的⽬录和⽂件反映了整台机器的系统状况。
⽐如bus,localhost:/sys/bus#lsi2c/ ide/ pci/ pci express/ platform/ pnp/ scsi/ serio/ usb/⾥⾯就包含了系统⽤到的⼀系列总线,⽐如pci, ide, scsi, usb等等。
⽐如你可以在usb⽂件夹中发现你使⽤的U盘,USB⿏标的信息。
我们要讨论⼀个⽂件系统,⾸先要知道这个⽂件系统的信息来源在哪⾥。
所谓信息来源是指⽂件组织存放的地点。
一:前言Linux设备模型是一个极其复杂的结构体系,在编写驱动程序的时候,通常不会用到这方面的东西,但是。
理解这部份内容,对于我们理解linux设备驱动的结构是大有裨益的。
我们不但可以在编写程序程序的时候知其然,亦知其所以然。
又可以学习到一种极其精致的架构设计方法。
由于之前已经详细分析了sysfs文件系统。
所以本节的讨论主要集中在设备模型的底层实现上。
上层的接口,如pci.,usb ,网络设备都可以看成是底层的封装。
二:kobject ,kset和ktypeKobject,kset,kypte这三个结构是设备模型中的下层架构。
模型中的每一个元素都对应一个kobject.kset和ktype可以看成是kobject在层次结构与属性结构方面的扩充。
将三者之间的关系用图的方示描述如下:如上图所示:我们知道。
在sysfs中每一个目录都对应一个kobject.这些kobject都有自己的parent。
在没有指定parent的情况下,都会指向它所属的kset->object。
其次,kset也内嵌了kobject.这个kobject又可以指它上一级的parent。
就这样。
构成了一个空间上面的层次关系。
其实,每个对象都有属性。
例如,电源管理,执插拨事性管理等等。
因为大部份的同类设备都有相同的属性,因此将这个属性隔离开来,存放在ktype中。
这样就可以灵活的管理了.记得在分析sysfs 的时候。
对于sysfs中的普通文件读写操作都是由kobject->ktype->sysfs_ops来完成的.经过上面的分析,我们大概了解了kobject.kset与ktype的大概架设与相互之间的关系。
下面我们从linux源代码中的分析来详细研究他们的操作。
三:kobject,kset和ktype的操作为了说明kobject的操作,先写一个测试模块,代码如下:#include <linux/device.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/string.h>#include <linux/sysfs.h>#include <linux/stat.h>MODULE_AUTHOR("eric xiao");MODULE_LICENSE("Dual BSD/GPL");void obj_test_release(struct kobject *kobject);ssize_t eric_test_show(struct kobject *kobject, struct attribute *attr,char *buf);ssize_t eric_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count); struct attribute test_attr = {.name = "eric_xiao",.mode = S_IRWXUGO,};static struct attribute *def_attrs[] = {&test_attr,NULL,};struct sysfs_ops obj_test_sysops ={.show = eric_test_show,.store = eric_test_store,};struct kobj_type ktype ={.release = obj_test_release,.sysfs_ops=&obj_test_sysops,.default_attrs=def_attrs,};void obj_test_release(struct kobject *kobject){printk("eric_test: release .\n");}ssize_t eric_test_show(struct kobject *kobject, struct attribute *attr,char *buf){printk("have show.\n");printk("attrname:%s.\n", attr->name);sprintf(buf,"%s\n",attr->name);return strlen(attr->name)+2;}ssize_t eric_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count) {printk("havestore\n");printk("write: %s\n",buf);return count;}struct kobject kobj;static int kobject_test_init(){printk("kboject test init.\n");kobject_init_and_add(&kobj,&ktype,NULL,"eric_test");return 0;}static int kobject_test_exit(){printk("kobject test exit.\n");kobject_del(&kobj);return 0;}module_init(kobject_test_init);module_exit(kobject_test_exit);加载模块之后,会发现,在/sys下多了一个eric_test目录。
该目录下有一个叫eric_xiao的文件。
如下所示:[root@localhost eric_test]# lseric_xiao用cat察看此文件:[root@localhost eric_test]# cat eric_xiaoeric_xiao再用echo往里面写点东西;[root@localhost eric_test]# echo hello > eric_xiaoDmesg的输出如下:have show.attrname:eric_xiao.havestorewrite: hello如上所示。
我们看到了kobject的大概建立过程.我们来看一下kobject_init_and_add()的实现。
在这个函数里,包含了对kobject的大部份操作。
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,struct kobject *parent, const char *fmt, ...){va_list args;int retval;//初始化kobjectkobject_init(kobj, ktype);va_start(args, fmt);//为kobjcet设置名称,在sysfs中建立相关信息retval = kobject_add_varg(kobj, parent, fmt, args);va_end(args);return retval;}上面的流程主要分为两部份。
一部份是kobject的初始化。
在这一部份,它将kobject与给定的ktype 关联起来。
初始化kobject中的各项结构。
另一部份是kobject的名称设置。
空间层次关系的设置,具体表现在sysfs文件系统中.对于第一部份,代码比较简单,这里不再赘述。
跟踪第二部份,也就是kobject_add_varg()的实现. static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,const char *fmt, va_list vargs){va_list aq;int retval;va_copy(aq, vargs);//设置kobject的名字。
即kobject的name成员retval = kobject_set_name_vargs(kobj, fmt, aq);va_end(aq);if (retval) {printk(KERN_ERR "kobject: can not set name properly!\n");return retval;}//设置kobject的parent。
在上面的例子中,我们没有给它指定父结点kobj->parent = parent;//在sysfs中添加kobjcet信息return kobject_add_internal(kobj);}设置好kobject->name后,转入kobject_add_internal()。
在sysfs中创建空间结构.代码如下:static int kobject_add_internal(struct kobject *kobj){int error = 0;struct kobject *parent;if (!kobj)return -ENOENT;//如果kobject的名字为空.退出if (!kobj->name || !kobj->name[0]) {pr_debug("kobject: (%p): attempted to be registered with empty ""name!\n", kobj);WARN_ON(1);return -EINV AL;}//取kobject的父结点parent = kobject_get(kobj->parent);//如果kobject的父结点没有指定,就将kset->kobject做为它的父结点/* join kset if set, use it as parent if we do not already have one */if (kobj->kset) {if (!parent)parent = kobject_get(&kobj->kset->kobj);kobj_kset_join(kobj);kobj->parent = parent;}//调试用pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",kobject_name(kobj), kobj, __FUNCTION__,parent ? kobject_name(parent) : "<NULL>",kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");//在sysfs中创建kobject的相关元素error = create_dir(kobj);if (error) {//v如果创建失败。