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

更多内容请参考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.模块的编译和装载

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

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

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

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

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

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

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

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

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

  6. linux设备驱动程序_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. kafka笔记6

    我们讨论可靠性时,一般使用保证这个词,它是确保系统在各种不同的环境下能够发生一致的行为.Kafka可以在哪些方面作出保证呢? 1.Kafka可以保证分区消息的顺序 2.只有消息被写入分区的所有同步副本 ...

  2. Python 爬虫从入门到进阶之路(六)

    在之前的文章中我们介绍了一下 opener 应用中的 ProxyHandler 处理器(代理设置),本篇文章我们再来看一下 opener 中的 Cookie 的使用. Cookie 是指某些网站服务器 ...

  3. Hyperledger Fabric1.4的多机部署

    之前的文章深入解析Hyperledger Fabric启动的全过程主要讲解了Fabric的网络搭建,以及启动的整体流程,但是都是通过单机完成的.而区块链本身就是去中心化的,所以最终还是要完成Fabri ...

  4. java集合知识点总结

    下面是java中常见的集合: List--列表:内部元素有序,可以重复, ArrayList:线程不安全,效率高.数据结构是线性表,底层结构是顺序表,也就是数组,有唯一的下标来指定元素的位置,查询快, ...

  5. 【fullGC】内存监控工具

    什么是fullGC: 从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为Major GC,而Full GC是对整个堆来说的,在最近几个版本的J ...

  6. mysql-8.0-winx64安装以及修改密码

    一.下载安装包(https://dev.mysql.com/downloads/mysql/) 二.添加my.ini配置文件 打开刚刚解压的文件夹 C:\mysql-8.0.16-winx64,在该文 ...

  7. Spring Environment抽象

    1:概述 Spring中Environment是Spring3.1版本引入的,是Spring核心框架定义的一个接口,用来表示整个应用运行时环境.该环境模型只接受两种应用环境profiles(配置文件) ...

  8. cat more less 命令混用

    在Linux系统中有三种命令可以用来查阅全部的文件,分别是cat.more和less命令.它们查阅文件的使用方法也比较简单都是 命令 文件名 ,但是三者又有着区别. 1.cat命令可以一次显示整个文件 ...

  9. 跟我学SpringCloud | 第九篇:服务网关Zuul初

    SpringCloud系列教程 | 第九篇:服务网关Zuul初探 前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散 ...

  10. 《深入浅出RxJS》读书笔记

    rxjs的引入 // 如果以这种方式导入rxjs,那么整个库都会导入,我们一般不可能在项目中运用到rxjs的所有功能 const Rx = require('rxjs'); 解决这个问题,可以使用深链 ...