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系统的层次结构可以分为以下几个主要层次:
1. 硬件层(Hardware Layer)
这是最底层,包括CPU、内存、硬盘、网卡等硬件设备。
2. 内核层(Kernel Layer)
Linux内核是操作系统的核心部分,负责管理硬件资源、调度进程、提供系统服务等。
常见的内核版本有Linux、FreeBSD、Solaris等。
3. 系统库层(System Libraries Layer)
系统库是应用程序和内核之间的接口,提供了常用的系统调用函数,如文件操作、进程管理、网络通信等。
常见的系统库有glibc、musl 等。
4. 系统工具层(System Utilities Layer)
系统工具是管理和维护操作系统的工具程序,如文件系统工具、网络工具、系统管理工具等。
常见的系统工具有bash、cron、systemd 等。
5. 服务层(Services Layer)
服务层包括各种系统服务,如Web服务(Apache、Nginx)、数据库服务(MySQL、PostgreSQL)、文件服务(Samba、NFS)等。
6. 桌面环境层(Desktop Environment Layer)
桌面环境提供了图形化的用户界面,方便用户与系统交互。
常见的桌面环境有GNOME、KDE、Xfce等。
7. 应用层(Application Layer)
应用层包括各种应用程序,如办公软件、浏览器、媒体播放器、游戏等。
Linux系统的层次结构由底层的硬件到上层的应用程序,每一层都扮演着重要的角色,相互协作为用户提供了完整的操作系统功能。
linux virtio原理Linux virtio是一种在虚拟化环境中使用的设备驱动模型,它旨在提供高性能和低延迟的I/O操作。
本文将详细介绍virtio的原理及其在Linux系统中的应用。
一、virtio的原理1. 设备模型:virtio将虚拟设备分为前端和后端两部分。
前端设备运行在虚拟机中,后端设备运行在宿主机上。
两者之间通过virtio驱动进行通信。
2. 驱动模型:virtio驱动是一个通用的设备驱动框架,它提供了一组标准的设备接口,包括设备初始化、I/O操作和中断处理等。
驱动程序通过这些接口与前端设备进行通信。
3. 通信机制:virtio使用共享内存和事件通知机制实现前后端设备之间的高效通信。
前端设备将数据写入共享内存缓冲区,并通过事件通知机制通知后端设备。
后端设备读取共享内存中的数据,并进行相应的处理。
4. I/O虚拟化:virtio支持多种设备类型的虚拟化,包括网络设备、磁盘设备和图形设备等。
通过虚拟化技术,virtio可以将物理设备的功能在虚拟机中进行模拟,实现对虚拟机的透明访问。
二、virtio在Linux系统中的应用1. 网络虚拟化:virtio-net是virtio的网络设备驱动,它提供了高性能的网络虚拟化功能。
通过virtio-net驱动,虚拟机可以直接访问物理网络,实现与宿主机的高速数据传输。
2. 块设备虚拟化:virtio-blk是virtio的块设备驱动,它可以将宿主机上的块设备映射到虚拟机中,实现对虚拟机的块设备访问。
通过virtio-blk驱动,虚拟机可以实现高性能的块设备I/O操作。
3. 图形虚拟化:virtio-gpu是virtio的图形设备驱动,它可以将宿主机上的图形设备映射到虚拟机中,实现对虚拟机的图形输出。
通过virtio-gpu驱动,虚拟机可以实现高性能的图形渲染和显示。
三、结语virtio作为一种高性能的设备驱动模型,在虚拟化环境中得到了广泛的应用。
描述linux操作系统的基本架构
Linux操作系统的基本架构是一个分层的架构,它由多个组件
和层次结构组成。
以下是Linux操作系统的基本架构的主要组
成部分:
1.内核(Kernel):内核是操作系统最底层的部分,负责管
理和控制计算机的硬件资源。
它提供了访问硬件、进程管理、内存管理、文件系统以及网络功能等基本服务。
2.Shell:Shell是操作系统的用户界面,提供了用户与内核
进行交互的方式。
用户可以通过Shell来执行命令、运行程序、管理文件等操作。
3.系统库(System Libraries):系统库提供了一些常用功能
的函数接口,使得应用程序能够更方便地访问操作系统的功能。
例如,C语言的标准库提供了很多文件操作、字符串处理等功能。
4.系统实用程序(System Utilities):系统实用程序是一些
辅助工具,用于管理系统配置、监控性能、诊断问题、安全管理等操作。
例如,登陆管理器、网络配置工具、进程监控工具等。
5.应用程序(Applications):应用程序是在操作系统上运行
的各种应用软件,如文本编辑器、网页浏览器、办公套件、图形处理软件等。
整个系统架构是层次结构的,每一层都依赖于下一层,并提供对上一层的抽象接口。
内核提供了最基本的功能和服务,上层的组件则依赖于内核提供的接口来实现更高级别的功能。
这种分层结构使得系统的各个组件能够独立地发展和演化,同时也提供了灵活性和可扩展性。
Linux实验总结分析报告前⾔感谢中科⼤孟⽼师和李⽼师的精⼼讲授,在本门课中,我受益匪浅。
通过阅读孟⽼师的著作——《庖丁解⽜Linux》,更使我加深了对本门课的理解。
再次感谢两位⽼师。
⼀、精简的Linux系统的概念模型冯·诺依曼体系结构如图所⽰,其中运算器、存储器、控制器、输⼊设备和输出设备5⼤基本类型部件组成了计算机硬件;核⼼是CPU,与内存和输⼊输出(I/O)设备进⾏交互,是整个计算机的灵魂、⼤脑。
内存则是存放了指令和数据,⼆者皆以⼆进制形式存放。
输⼊输出设备则包括⿏标、键盘、显⽰器与磁盘等等设备,是计算机与外界进⾏交互的⼯具。
进程管理进程管理的重点是进程的执⾏。
在内核中,这些进程称为线程,代表了单独的处理器虚拟化(线程代码、数据、堆栈和 CPU寄存器)。
在⽤户空间,通常使⽤进程这个术语,不过 Linux 实现并没有区分这两个概念(进程和线程)。
内核通过 SCI 提供了⼀个应⽤程序编程(API)来创建⼀个新进程(fork、exec 或 Portable Operating System Interface [POSⅨ] 函数),停⽌进程(kill、exit),并在它们之间进⾏通信和同步(signal 或者 POSⅨ机制)。
进程管理还包括处理活动进程之间共享 CPU 的需求。
内核实现了⼀种新型的调度算法,不管有多少个线程在竞争 CPU,这种算法都可以在固定时间内进⾏操作。
这种算法就称为 O⑴调度程序,这个名字就表⽰它调度多个线程所使⽤的时间和调度⼀个线程所使⽤的时间是相同的。
O⑴调度程序也可以⽀持多处理器(称为对称多处理器或 SMP)。
您可以在 ./linux/kernel 中找到进程管理的源代码,在 ./linux/arch 中可以找到依赖于体系结构的源代码。
内存管理内核所管理的另外⼀个重要资源是内存。
Linux 包括了管理可⽤内存的⽅式,以及物理和虚拟映射所使⽤的硬件机制。
不过内存管理,要管理的可不⽌ 4KB缓冲区。
Linux设备模型浅析之设备篇本文属本人原创,欢转载,转载请注明出处。
由于个人的见识和能力有限,不可能面面俱到,也可能存在谬误,敬请网友指出,本人的邮箱是yzq.seen@,博客是。
Linux设备模型,仅仅看理论介绍,比如LDD3的第十四章,会感觉太抽象不易理解,而通过阅读内核代码就更具体更易理解,所以结合理论介绍和内核代码阅读能够更快速的理解掌握linux设备模型。
这一序列的文章的目的就是在于此,看这些文章之前最好能够仔细阅读LDD3的第十四章。
大部分device和driver都被包含在一个特定bus中,platform_device和platform_driver就是如此,包含在platform_bus_type中。
这里就以对platform_bus_type的调用为主线,浅析platform_device的注册过程,从而理解linux设备模型。
platform_bus_type用于关联SOC的platform device和platform driver,比如在内核linux-2.6.29中所有S3C2410中的platform device都保存在devs.c中。
这里就以S3C2410 RTC为例。
在文章的最后贴有一张针对本例的device model图片,可在阅读本文章的时候作为参照。
一、S3C2410 RTC的platform device定义在arch/arm/plat-s3c24xx/devs.c中,如下:static struct resource s3c_rtc_resource[] = {[0] = {.start = S3C24XX_PA_RTC,.end = S3C24XX_PA_RTC + 0xff,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_RTC,.end = IRQ_RTC,.flags = IORESOURCE_IRQ,},[2] = {.start = IRQ_TICK,.end = IRQ_TICK,.flags = IORESOURCE_IRQ}};struct platform_device s3c_device_rtc = {.name = "s3c2410-rtc",.id = -1,.num_resources = ARRAY_SIZE(s3c_rtc_resource),.resource = s3c_rtc_resource,};把它们添加在arch/arm/mach-s3c2440/ mach- smdk2440.c中,如下:static struct platform_device *smdk2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_iis,& s3c_device_rtc};系统初始化的时候会调用drivers/base/platform.c里的platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices))将其注册到platform_bus_type,最终被添加到device hierarchy 。
简介作者:hjlin内核版本:2.6.29设备驱动模型框架是linux驱动编程的基础。
它通过kobject,kset,ktype等底层数据结构将bus_type, device, device_driver 等高层数据结构组织起来,形成一个层次、分类清晰的驱动模型。
优点如下:1.代码重用。
将对象抽象为总线、驱动、设备三种,各司其职。
同一总线的多个驱动使用相同的总线对象。
同一驱动可以关联驱动多个设备。
2.通过sysfs文件系统,清晰了展示内核驱动模型中的层次关系。
同时sysfs文件系统还提供了方便的同用户控件交互的接口。
框架数据结构KobjectKobject是代表驱动模型中的一个对象。
总线、驱动、设备都继承了它。
(在结构体中包含kobject)。
每个kobject在sysfs中表现为一个目录。
每个kobject都有一个parent kobject和所属的kset。
Kset就是kobject所属的kset,通过kset 的链表可以找到所有属于它的kobject。
这些kobject进行uevent操作时,都会调用所属的kset 的uevent_ops方法。
父kobj,用于表示kobject之间或者kobject和kset,kset之间的在sysfs 中的目录结构关系。
如果父kobj不存在,并且所属的kset存在的话,则父kobj就是设置为所属的kset的内嵌kobj。
因此,注册设备、驱动或者总线的时候如果不指定parent kobj的话,父kobj则会设置为所属的kset的kobj。
(todo:最好画图表示关系)Kest通过kset可以将kobject组织成一颗层次树。
kobj_typebus_type代表一个总线。
对应/sys/bus下的一个目录。
管理相应总线下的所有驱动和设备。
struct bus_type {const char *name; //总线名称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); //uevent方法int (*probe)(struct device *dev); //match成功之后会调用。
一:前言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如果创建失败。