Linux设备驱动程序学习----2.内核模块与应用程序的对比
内核模块与应用程序的对比
更多内容请参考Linux设备驱动程序学习----目录
1. 内核模块与应用程序的对比
内核模块和应用程序之间的不同之处:
大多数中小规模的应用程序是从头到尾执行单个任务,而模块却只是预先注册自己以便服务于将来的某个请求,然后初始化函数立即结束。即模块初始化函数(hello_init)的任务就是为以后调用模块函数预先做准备。模块的退出函数(hello_exit)将在模块被卸载之前调用。
这和事件驱动编程有点类似,但不是所有的应用程序都是事件驱动的,而每个内核模块都是这样的。事件驱动程序和内核模块之间的另一个区别是,应用程序在退出时,可以不管资源的释放或者其他的清除工作,但模块的退出函数必须撤销初始化函数所做的一切,保证没有多余内容残留在系统中。
应用程序可以调用它并未定义的函数,因为链接过程能够解析外部引用,从而链接使用适当的函数库。而模块仅仅被链接到内核,因此模块能调用的函数仅仅是由内核导出的那些函数,而不存在任何可链接的函数库。因为没有任何函数库会和模块链接,因此源文件中不能包含通常应用程序的头文件。内核模块只能使用作为内核一部分的函数。和内核相关的大多数相关头文件保存在include/linux和include/asm目录中。
应用程序和内核编程的处理错误的方式不同,应用程序的段错误可以使用调试器跟踪到源代码中的问题,而内核错误即使不影响系统,也会杀死当前进程。
模块卸载的好处,有助于缩短模块化驱动程序的开发周期。
2. 用户空间和内核空间
模块运行在内核空间,应用程序运行在用户空间。
在Unix中,内核运行在最高级别,即超级用户态,这个级别可以进行所有的操作。而应用程序运行在最低级别,即用户态,这个级别处理器控制着对硬件的直接访问及对内存的非授权访问。
内核空间和用户空间,不仅说明两种模式具有不同的优先级等级,还说明每个模式都有自己的内存映射,即自己的地址空间。
当应用程序执行系统调用或者被硬件中断挂起时,Unix将执行模式从用户空间切换到内核空间。执行系统调用的内核代码运行在进程上下文中,代表调用进程执行操作。因此能够访问进程地址空间的所有数据。而处理器硬件中断的内核代码和进程时异步的,和任何一个进程无关。
模块化代码在内核空间运行,用于扩展内核功能。驱动程序要执行两类任务,模块中的某些函数作为系统调用的一部分执行;其他函数则负责中断处理。
3. 内核中的并发
内核编程和应用程序编程的区别在于对并发的处理。大部分应用程序,除了多线程应用程序外,通常都是顺序执行的。内核代码的运行环境更加复杂,即使是最简单的内核模块,都需要注意:同一时刻,可能会有很多事情发生。
内核编程必须考虑并发问题的原因:
- Linux系统中通常正在运行多个并发进程,并且可能有多个进程同时使用驱动程序;
- 大多数设备能够中断处理器,而中断处理程序异步运行,而且可能在驱动程序正试图处理其他任务时被调用;
- 有些软件抽象(如:内核定时器)也是异步运行的;
- Linux可能运行在对称多处理器系统(SMP),因此可能同时不止一个CPU运行驱动程序;
- Linux2.6内核代码已经是可抢占的,即使在单处理器系统上也存在类似多处理器系统的并发问题。
Linux内核代码(包括驱动程序)必须是可重入的,必须能够同时运行在多个上下文中。内核数据结构要保证多个线程分开执行,访问共享数据的代码必须避免破坏共享数据。驱动要能够处理并发问题,同时避免竞态。内核代码不能假定在给定代码段中能够独占处理器。
4. 当前进程
虽然内核模块不像应用程序那样顺序地执行,然而内核执行的大多数操作还是和某个特定进程相关。内核代码可通过访问全局项current来获得当前进程。
current在<asm/current.h>中定义,是一个指向struct task_struct的指针。current指针指向当前正在运行的进程。可以通过访问struct task_struct的某些成员来打印当前进程的进程ID和命令名:
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
存储在current->comm成员中的命令名是当前进程所执行的程序文件的基本名称,裁剪在15个字符以内。
5. 其他细节
应用程序在虚拟内存中布局,并具有一块很大的栈空间。栈用来保存函数调用历史及当前活动函数中的自动变量。而内核具有很小的栈,可能只有一个4096字节大小的页空间。驱动的函数必须和整个内核空间调用链一同共享这个栈。因此,不能声明大的自动变量,如果需要大的结构,应该在调用时动态分配该结构。
在内核API中,具有双下划线(__)的函数名称,通常是接口的底层组件,应谨慎使用。
内核代码不能实现浮点数运算,内核代码中不需要浮点运算。
更多内容请参考Linux设备驱动程序学习----目录
Linux设备驱动程序学习----2.内核模块与应用程序的对比的更多相关文章
- Linux设备驱动程序学习----3.模块的编译和装载
模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...
- Linux设备驱动程序学习----目录
目录 设备驱动程序简介 1.设备驱动程序简介 构造和运行模块 2.内核模块和应用程序的对比 3.模块编译和装载 4.模块的内核符号表 5.模块初始化和关闭 6.模块参数 7.用户空间编写驱动程序 ...
- Linux设备驱动程序学习之分配内存
内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...
- Linux设备驱动程序学习----1.设备驱动程序简介
设备驱动程序简介 更多内容请参考Linux设备驱动程序学习----目录 1. 简介 Linux系统的优点是,系统内部实现细节对所有人都是公开的.Linux内核由大量复杂的代码组成,设备驱动程序可以 ...
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】
转自:http://blog.csdn.net/jacobywu/article/details/7475432 阻塞型I/O和非阻塞I/O 阻塞:休眠 非阻塞:异步通知 一 休眠 安全地进入休眠的两 ...
- linux设备驱动程序_hello word 模块编译各种问题集锦
在看楼经典书籍<linux设备驱动程序>后,第一个程序就是编写一个hello word 模块. 原以为非常easy,真正弄起来,发现问题不少啊.前两天编过一次,因为没有记录,今天看的时候又 ...
- Linux设备驱动程序 第三版 读书笔记(一)
Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...
- linux设备驱动程序--在用户空间注册文件接口
linux字符设备驱动程序--创建设备节点 基于4.14内核,运行在beagleBone green 在上一讲中,我们写了第一个linux设备驱动程序--hello_world,在驱动程序中,我们什么 ...
- linux设备驱动程序--hello-world
linux字符设备驱动程序--hello_world 基于4.14内核, beagleBone green平台 PC端的设备驱动程序 有过电脑使用经验的人都知道,当我们将外部硬件设备比如鼠标键盘插入到 ...
随机推荐
- ES 20 - 查询Elasticsearch中的数据 (基于DSL查询, 包括查询校验match + bool + term)
目录 1 什么是DSL 2 DSL校验 - 定位不合法的查询语句 3 match query的使用 3.1 简单功能示例 3.1.1 查询所有文档 3.1.2 查询满足一定条件的文档 3.1.3 分页 ...
- Azkaban —— 编译及部署
一.Azkaban 源码编译 1.1 下载并解压 Azkaban 在3.0版本之后就不提供对应的安装包,需要自己下载源码进行编译. 下载所需版本的源码,Azkaban的源码托管在GitHub上,地址为 ...
- 老雷socket编程之PHP利用socket扩展实现聊天服务
老雷socket编程之PHP利用socket扩展实现聊天服务 socket聊天服务原理 PHP有两个socket的扩展 sockets和streamssockets socket_create(AF_ ...
- 高性能微服务网关.NETCore客户端Kong.Net开源发布
前言 项目地址:https://github.com/lianggx/Kong.Net 你的支持使我们更加强大,请单击 star 让更多的 .NETCore 认识它. 拥抱开源的脚步,我们从来都是一直 ...
- TypeScript算法与数据结构-数组篇
数组是数据结构中最简单,也是使用最广泛的一种.在原生的js中,数组给我们提供了很多方便的操作方法,比如push(), pop(), shift(), unshift().但是出于对数据结构的学习,我们 ...
- 并发编程-concurrent指南-原子操作类-AtomicReference
1.类 AtomicReference<V> public class AtomicReference<V>extends Objectimplements Serializa ...
- CentOS 网络互通情况下把一个Linux服务器的文件发送到另一个服务器
scp -r 文件名/目录名 root@192.168.2.144:/home/hsw -r 发送目录使用,表示把该目录下的所有子目录以及文件发送过去
- 002-pythn基础-循环、编码
1. 循环 while 条件: 代码块(循环体) else: 当上面的条件为假. 才会执行 执行顺序: 判断条件是否为真. 如果真. 执行循环体. 然后再次判断条件....直到循环条件为假. 程序退出 ...
- 模块(二)os hashlib
模块(二)os hashlib 1.序列化模块 1.1 json 将满足条件的数据结构转化成特殊的字符串,并且可以反序列化转回去 # 两对方法 # 1 dumps() loads() ## 多用于网络 ...
- 源码阅读 - java.util.concurrent (三)ConcurrentHashMap
在java.util.concurrent包中提供了一个线程安全版本的Map类型数据结构:ConcurrentMap.本篇文章主要关注ConcurrentMap接口以及它的Hash版本的实现Concu ...