Linux设备驱动程序学习----2.内核模块与应用程序的对比

时间:2021-11-12 18:22:01

内核模块与应用程序的对比

更多内容请参考Linux设备驱动程序学习----目录

1. 内核模块与应用程序的对比

内核模块和应用程序之间的不同之处:

  1. 大多数中小规模的应用程序是从头到尾执行单个任务,而模块却只是预先注册自己以便服务于将来的某个请求,然后初始化函数立即结束。即模块初始化函数(hello_init)的任务就是为以后调用模块函数预先做准备。模块的退出函数(hello_exit)将在模块被卸载之前调用。

  2. 这和事件驱动编程有点类似,但不是所有的应用程序都是事件驱动的,而每个内核模块都是这样的。事件驱动程序和内核模块之间的另一个区别是,应用程序在退出时,可以不管资源的释放或者其他的清除工作,但模块的退出函数必须撤销初始化函数所做的一切,保证没有多余内容残留在系统中。

  3. 应用程序可以调用它并未定义的函数,因为链接过程能够解析外部引用,从而链接使用适当的函数库。而模块仅仅被链接到内核,因此模块能调用的函数仅仅是由内核导出的那些函数,而不存在任何可链接的函数库。因为没有任何函数库会和模块链接,因此源文件中不能包含通常应用程序的头文件。内核模块只能使用作为内核一部分的函数。和内核相关的大多数相关头文件保存在include/linux和include/asm目录中。

  4. 应用程序和内核编程的处理错误的方式不同,应用程序的段错误可以使用调试器跟踪到源代码中的问题,而内核错误即使不影响系统,也会杀死当前进程。

模块卸载的好处,有助于缩短模块化驱动程序的开发周期。

2. 用户空间和内核空间

  模块运行在内核空间,应用程序运行在用户空间。

  在Unix中,内核运行在*别,即超级用户态,这个级别可以进行所有的操作。而应用程序运行在最低级别,即用户态,这个级别处理器控制着对硬件的直接访问及对内存的非授权访问。

  内核空间和用户空间,不仅说明两种模式具有不同的优先级等级,还说明每个模式都有自己的内存映射,即自己的地址空间。

  当应用程序执行系统调用或者被硬件中断挂起时,Unix将执行模式从用户空间切换到内核空间。执行系统调用的内核代码运行在进程上下文中,代表调用进程执行操作。因此能够访问进程地址空间的所有数据。而处理器硬件中断的内核代码和进程时异步的,和任何一个进程无关。

  模块化代码在内核空间运行,用于扩展内核功能。驱动程序要执行两类任务,模块中的某些函数作为系统调用的一部分执行;其他函数则负责中断处理。

3. 内核中的并发

  内核编程和应用程序编程的区别在于对并发的处理。大部分应用程序,除了多线程应用程序外,通常都是顺序执行的。内核代码的运行环境更加复杂,即使是最简单的内核模块,都需要注意:同一时刻,可能会有很多事情发生。

内核编程必须考虑并发问题的原因:

  1. Linux系统中通常正在运行多个并发进程,并且可能有多个进程同时使用驱动程序;
  2. 大多数设备能够中断处理器,而中断处理程序异步运行,而且可能在驱动程序正试图处理其他任务时被调用;
  3. 有些软件抽象(如:内核定时器)也是异步运行的;
  4. Linux可能运行在对称多处理器系统(SMP),因此可能同时不止一个CPU运行驱动程序;
  5. 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.内核模块与应用程序的对比的更多相关文章

  1. Linux设备驱动程序学习----3&period;模块的编译和装载

    模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...

  2. Linux设备驱动程序学习----目录

    目录 设备驱动程序简介 1.设备驱动程序简介 构造和运行模块 2.内核模块和应用程序的对比 3.模块编译和装载 4.模块的内核符号表  5.模块初始化和关闭  6.模块参数  7.用户空间编写驱动程序 ...

  3. Linux设备驱动程序学习之分配内存

    内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...

  4. Linux设备驱动程序学习----1&period;设备驱动程序简介

    设备驱动程序简介 更多内容请参考Linux设备驱动程序学习----目录 1. 简介   Linux系统的优点是,系统内部实现细节对所有人都是公开的.Linux内核由大量复杂的代码组成,设备驱动程序可以 ...

  5. Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I&sol;O和非阻塞I&sol;O&rsqb;【转】

    转自:http://blog.csdn.net/jacobywu/article/details/7475432 阻塞型I/O和非阻塞I/O 阻塞:休眠 非阻塞:异步通知 一 休眠 安全地进入休眠的两 ...

  6. linux设备驱动程序&lowbar;hello word 模块编译各种问题集锦

    在看楼经典书籍<linux设备驱动程序>后,第一个程序就是编写一个hello word 模块. 原以为非常easy,真正弄起来,发现问题不少啊.前两天编过一次,因为没有记录,今天看的时候又 ...

  7. Linux设备驱动程序 第三版 读书笔记(一)

    Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...

  8. linux设备驱动程序--在用户空间注册文件接口

    linux字符设备驱动程序--创建设备节点 基于4.14内核,运行在beagleBone green 在上一讲中,我们写了第一个linux设备驱动程序--hello_world,在驱动程序中,我们什么 ...

  9. linux设备驱动程序--hello-world

    linux字符设备驱动程序--hello_world 基于4.14内核, beagleBone green平台 PC端的设备驱动程序 有过电脑使用经验的人都知道,当我们将外部硬件设备比如鼠标键盘插入到 ...

随机推荐

  1. IPV6

    (一) iOS 9.0.OS X 10.11 以上的系统 在IPv6的环境下 是支持IP地址访问网络的.所以大家测试机如果是 iOS9.0以上的系统,可以直接通过IP访问.这是因为iOS 9.0之后  ...

  2. AtomicInteger类保证线程安全的用法

    J2SE 5.0提供了一组atomic class来帮助我们简化同步处理.基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增.减.赋值(更新)操作 ...

  3. Bmob第三方登录详解

    Bmob第三方登录详解 Bmob 第三方登录 简介 本文主要介绍新浪微博,QQ,微信的登录接入以及如何配合BmobSDK中的第三方登录功能实现第三方登录. 在使用之前请先按照快速入门创建好可以调用Bm ...

  4. iOS UIButton详细介绍

    昨天,做了项目中的一点,觉得细节还是很重要的.像一个普通的UIButton,给它调试字体格式,大小什么的,确实是蛮耗时间的. 今天打算详细的归纳归纳.. typedef NS_ENUM(NSInteg ...

  5. python终端中退格键,方向键不能使用

    在安装Python的时候先安装 yum install readline-devel.x86_64 -y 如果python已经安装过了就重新安装 ./configure    make all mak ...

  6. RsaUtils

    参考来源:https://www.cnblogs.com/pcheng/p/9629621.html 里面的这段话,非常好 RSA加密对明文的长度有所限制,规定需加密的明文最大长度=密钥长度-11(单 ...

  7. selenium之frame

    https://blog.csdn.net/huilan_same/article/details/52200586

  8. Apache Commons Codec的Base64加解密库

    下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi import org.apache.commons.cod ...

  9. 原生js的开发笔记

    1.基本的dom操作 var a=document.getElementById('ma1').innerHTML;/获取html代码 alert(document.getElementById('m ...

  10. WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法

    原文:WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法 WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法        最近在做 ...