Linux内核模块开发 第 5 章

news2024/10/6 18:34:15

The Linux Kernel Module Programming Guide

  • Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang
  • 译 断水客(WaterCutter
    在这里插入图片描述

5 预备知识(Preliminaries)

5.1 模块的入口函数和出口函数

C 程序通常从 main() 函数开始执行一系列指令,执行完成后退出。模块有所不同,它们通常从 module_init() 或者开发者用 module_init 指定(specified)的函数开始执行。这个函数即模块的入口函数(entry function),它告诉内核该模块提供的功能、建立模块运行需要的环境。module_init() 执行完退出后,模块将等待内核的请求,否则不会有任何动作。

模块终止前执行 module_exit() 或者开发者用 module_exit 指定的函数,即所谓出口函数(exit function)。这个函数用于撤销(undo)入口函数的行为,注销(unregister)入口函数注册的功能。

这两个函数是模块必须具备的,铁打不动。

5.2 模块可用的函数

模块是依赖于 insmod 或者 modprobe 解析的符号的 object 文件。所以模块中调用的外部函数(external function)限定于内核支持的那些系统调用(system call)。内核支持的系统调用可以在 /proc/kallsyms 文件中查看。

类似于 printf() 这种 C 标准库 libc 中的函数,是建立在系统调用 write() 之上的抽象用户接口。在模块中如果想输出到 stdout,只能使用 write()来代替 printf()

内核的系统调用可以通过模块替换,黑客经常将这种手段做后门或木马。

5.3 用户空间和内核空间

常说用户程序跑在用户空间,内核运行在内核空间,但要理解内核和用户程序的本质区别,还是得明确划分用户空间和内核空间的本因。

内核就是对资源访问的控制(A kernel is all about access to resources), 用户程序总是在竞争使用磁盘、内存、声卡、显卡等资源,内核的任务就是有条不紊地将这些资源分配给用户程序。

要保证内核顺利完成工作,就需要约束用户程序地访问权限,让用户程序不能随意访问资源,一切资源的访问都通过内核进行。这种需求反映在 CPU 设计中,就体现为多种特权模式,比如 x86 中的多种 ring 。

此等意义上,就可以把系统调用理解为用户API接口在内核空间的代表,代表用户程序实现对资源的访问。通常,在用户模式下使用库函数,将会调用一个或多个系统调用,这些系统调用代表库函数执行,但在特权模式下执行此操作,因为它们是内核本身的一部分。系统调用完成其任务后,它将返回并执行将传输回用户模式。

5.4 命名空间

当一个程序有很多全局变量,这些变量命名不清晰/不规范,造成区分问题时,就会造成命名空间污染(namespace pollution)。

即使是最小的模块也会与整个内核链接,最好将所有变量声明为静态变量,并为符号使用定义良好的前缀。如果不想将所有内容声明为静态,可以声明符号表并将其注册到内核。

/proc/kallsyms 文件中的所有符号与模块共享代码空间(code space),也就意味着编写模块时不能再声明包含在这个文件中的符号。

5.5 代码空间

O’Reilly 的 《Understanding The Linux Kernel》 中有专门的章节介绍 Linux 的内存管理(memory managment)。

每个应用程序和内核都有自己的内存空间。由于模块共享内核的代码空间,而不是像应用程序一样独有代码空间。因此,如果模块出现段错误,则内核就会出现段错误。所以写模块时应该时刻小心。

5.6 设备驱动

有些模块是设备驱动,为串口(serial port)这种硬件设备提供支持。

Unix 中,每个硬件都由 /dev 目录下的某个设备文件代表。比如 ‘/dev/sound’ 代表声卡,如果声卡硬件es1370,那么用户程序访问 ‘/dev/sound’ 时,系统就会通过 es1370.ko 模块与声卡交互,应用程序无需关心到底是什么型号的声卡。

让我们看一些设备文件。以下是代表主主IDE硬盘驱动器上的前三个分区的设备文件:

$ ls -l /dev/hda[1-3]
brw-rw----  1 root  disk  3, 1 Jul  5  2000 /dev/hda1
brw-rw----  1 root  disk  3, 2 Jul  5  2000 /dev/hda2
brw-rw----  1 root  disk  3, 3 Jul  5  2000 /dev/hda3

请注意用逗号分隔的数字列。第一个数字称为设备的主设备号,第二个数字是次设备号。主设备号标明使用哪个驱动程序访问硬件。每个驱动程序都分配有一个唯一的主编号,具有相同主编号的所有设备文件都由同一驱动程序控制。以上所有主要数字都是 3,因为它们都由同一个驱动程序控制。

驱动程序使用次设备号来区分它控制的各种硬件。回到上面的示例,尽管所有三个设备都由同一驱动程序处理,但它们具有唯一的次设备号,因为驱动程序将它们视为不同的硬件。

设备分为两种类型:字符设备和块设备。不同之处在于块设备具有请求缓冲区,因此它们可以选择响应请求的最佳顺序。这在存储设备的情况下很重要,在存储设备中,读取或写入彼此靠近的扇区比那些相距较远的扇区更快。另一个区别是块设备只能接受块中的输入和返回输出(其大小可以根据设备而变化),而字符设备可以使用任意数量的字节。世界上大多数设备都是字符,因为它们不需要这种类型的缓冲,并且它们不以固定的块大小运行。您可以通过查看 ls -l 输出中的第一个字符来判断设备文件是用于块设备还是字符设备。如果它是“b”,那么它是一个块设备,如果它是“c”,那么它是一个字符设备。您在上面看到的设备是块设备。以下是一些字符设备(串行端口):

crw-rw----  1 root  dial 4, 64 Feb 18 23:34 /dev/ttyS0
crw-r-----  1 root  dial 4, 65 Nov 17 10:26 /dev/ttyS1
crw-rw----  1 root  dial 4, 66 Jul  5  2000 /dev/ttyS2
crw-rw----  1 root  dial 4, 67 Jul  5  2000 /dev/ttyS3

如果要查看已分配的主要编号,可以查看:Documentation/admin-guide/devices.txt.

安装系统时,所有这些设备文件都是由 mknod 命令创建的。要创建一个名为 coffee 的新字符设备,主要/次要编号为 12 和 2,只需执行 mknod /dev/coffee c 12 2 。您不必将设备文件放入 /dev 中,但这是按照惯例完成的。Linus 将他的设备文件放在 /dev 中,你也应该如此。但是,在创建用于测试目的的设备文件时,可能可以将其放在编译内核模块的工作目录中。只需确保在编写完设备驱动程序后将其放在正确的位置即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/606172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

建筑与建材行业相关深度学习数据集大合集

近期又整理了一批建筑与建材行业相关深度学习数据集,分享给大家。废话不多说,直接上干货!! 1、埃及的地标数据集 自从历史开始以来,埃及一直是许多文明、文化和非常著名的地标的家园,现在你(和你的ML模型…

守护进程【Linux】

文章目录 前导知识shell、terminal、console进程组作业会话测试 会话控制jobfgbgps 守护进程作用查看守护进程创建守护进程 前导知识 shell、terminal、console terminal(终端)是一种可以和计算机交互的设备,通常有键盘和显示器&#xff0c…

RocketMq 的基本知识1

一RocketMq的基本知识 1.1 RocketMq的基本知识 MQ , Message Queue ,是一种提供 消息队列服务 的中间件,也称为消息中间件。 1.2 作用 1.流量消峰 2.异步传输 3.日志收集 1.3 核心概念 1消息: 消息是指,消息系统所…

基于内存操作的Redis数据库--详解

目录 基本概念 基本操作 redis的五个基本类型 Redis-key(不区分大小写) 字符串 string Redis的特殊类型 geospatial地理空间 事务 Redis的持久化 RDB(.rdb) 触发机制 优点 缺点 AOF(.aof) 优点…

冈萨雷斯DIP第8章知识点

8.1 基础 图像中的冗余 编码冗余:用于表示灰度的8比特编码所包含的比特数,要比表示该灰度所需要的比特数多。可通过变长编码来解决。 空间和时间冗余:与相邻像素相似(图像);时间:相邻帧中的像素(视频)。可以使用行程…

缺陷管理利器推荐:介绍几款好用的缺陷管理工具

缺陷管理是项目管理工作中的重要环节。Excel表格是国内团队常用的缺陷管理工具,具备上手容易,免费的优点,不过也存在协同不便,不易管理,效率低的不足之处。 一套缺陷管理工具可以帮助我们进行规范化自动化的缺陷管理&a…

LearnOpenGL-高级OpenGL-8.高级GLSL

本人初学者,文中定有代码、术语等错误,欢迎指正 文章目录 高级GLSLGLSL的内建变量在顶点着色器的内建变量gl_PointSizegl_VertexID 在片段着色器的内建变量gl_FragCoordgl_FrontFacinggl_FragDepth 接口块Uniform缓冲对象Uniform块布局使用Uniform缓冲简…

关于惠普M277打印机手动双面打印和自动双面打印设置

一.手动双面打印设置​​​​​​​ 1.键盘WINR,在运行框输入“control”,回车或者点击确定。 ​​​​​​​ 2.在控制面板找到设备和打印机,点击进去。 3.找到HP M277字样的打印机,右键选择打印机属性。 4.点击设…

有关部门信息表与员工信息表的常用SQL应用语句实现汇总

背景条件 已知有员工信息表(emp)和部门信息表(dept),具体表的信息如下: 员工信息表emp: 列名类型其他备注empnoDECIMAL(4)主键员工编号enameVARCHAR2(10)员工姓名jobVARCHAR2(9)工种mgrDECIM…

实现第一个内核程序的Hello World

背景 在内核的开发中,总要先入个门。那么就要来编写第一个内核程序 入门 一个 module_init 程序是Linux内核模块的一部分,通过module_init 方法就能将程序载入内核。 module_init 方法需要以下步骤 编写module_init 的代码,并将其保存为…

异常值检验、方差分析

异常值检验 T-test 参考:1.ttest和ttest2 区别 2. ttest在 matlab 3.T test分布表 方差分析(ANOVA) Def: 方差分析(analysis of variance, ANOVA)是一种统计检验,用于检验两组或更多组样本的均值是否相…

Allegro如何关闭出线自动拐弯功能操作指导

Allegro如何关闭出线自动拐弯功能操作指导 在用Allegro进行PCB设计的时候,对单个pin进行出线的时候,会遇到走线一出pin就会自动拐弯,并不会按照鼠标轨迹来设计,如下图 期望的效果如下图 如何关闭走线自动拐弯功能,具体操作如下 点击Route

django-vue-admin使用

一、源码地址 注意,一定要使用这个地址。(使用其他地址下载下来的感觉代码缺失,踩了大坑) django-vue-admin: 基于RBAC模型的权限控制的一整套基础开发平台,前后端分离,后端采用 djangodjango-rest-frame…

QT实现 WebsocketServer端与WebsocketClient 端通信

概 述 WebSockets 是一种通过单个 TCP 连接提供全双工通信信道的 web 技术。2011年,IETF 将 WebSocket 协议标准化为 RFC 6455 。Qt 提供的 QWebSocket 既可以用于客户端应用程序,也可以用于服务端应用程序,接口大部分和 QTcpSocket 一致。 …

R语言机器学习方法在生态经济学领域中的应用

近年来,人工智能领域已经取得突破性进展,对经济社会各个领域都产生了重大影响,结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一,目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据&#xf…

MoviePy介绍

MoivePy是一个用于视频编辑的Python库,可以:剪切、拼接、标题插入、视频合成、视频处理和创建自定义效果。它支持Windows、Linux、Mac,源码地址:https://github.com/Zulko/moviepy,最新发布版本v1.0.3,lice…

Qt(C++)开发一款图片防盗用水印制作小工具

一、前言 文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文…

[小白教程] Javascript Callback以及Promise/async/await 一文通

一、最初 一切从 Javascript 是一门异步编程语言说起,比如这种最简单的: let n 0function f1() {setTimeout(function () {n}, 1000)}f1()console.log(n)可能直觉上会觉得最终n1,但实际上打印出来的是0,因为尽管调用了f1函数&am…

vue笔记——实现打印功能1

第一步:安装vue-print-nb,打开项目终端输入 npm install vue-print-nb --save 第二步:打开package.json文件,在dependencies中出现vue-print-nb,说明安装成功,如下图所示。 第三步: 方法一:全…

电子科技大学计算机系统结构复习笔记(二):指令系统

目录 前言 重点一览 指令集系统结构(ISA)的分类 分类依据 存储结构 区别 图示 通用寄存器系统结构分类 存储器寻址 概述 寻址方式 MIPS寻址模式 小结 操作数类型 指令操作 与指令编码 常用操作数类型 常用指令系统的操作 常用指令系统编…