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

更多内容请参考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. Matlab与.Net混合编程-多维数组赋值出错的问题

    问题描述:Matlab可编译供.net调用的dll.两种不同环境对数据类型的定义相差较大,因此在C#中调用Matlab编译的函数时,首先要将C#中的变量类型转换成与Matlab对应的中转类型.Matl ...

  2. 分享五个404页面模板 超好看的404页面你的网站离不了 seo优化404

    一个完整的网站离不开一个好的404页面,404页面不光是让你的网站美观,它对SEO的作用也很大,你想一下如果用户打开你的网站,输入一个不存在的风址,如果没有404直接就报错了,有了404就能打开一个美 ...

  3. 宜信开源|数据库审核软件Themis的规则解析与部署攻略

    一.介绍 Themis是宜信公司DBA团队开发的一款数据库审核产品,可帮助DBA.开发人员快速发现数据库质量问题,提升工作效率.其名称源自希腊神话中的正义与法律女神.项目取此名称,寓意此平台对数据库质 ...

  4. 5分钟学会Java9-Java11的七大新特性

    现在Java有多元化的发展趋势,既有JS又有C++还有C#的影子,不学习那是不行滴. 来来来,花5分钟看看Java9-Java11的七大新特性,还有代码样例. Java11 发布了,然而很多公司还在用 ...

  5. Python自学day-8

    一.SocketServer 简化了编写网络服务器的难度. SocketServer一共有如下几个类型: socketserver.TCPServer :提供一个TCP的socketserver. s ...

  6. kubernetes实战篇之helm安装

    系列目录 Helm是kubernetes的应用包管理工具,是CNCF孵化器下的一个项目,主要用来管理 Charts.类似于 Ubuntu 中的 APT 或 CentOS 中的 YUM.它提供了一种简单 ...

  7. dubbo整合springboot最详细入门教程

    说明 目前互联网公司,大部分项目都是基于分布式,一个项目被拆分成几个小项目,这些小项目会分别部署在不同的计算机上面,这个叫做微服务.当一台计算机的程序需要调用另一台计算机代码的时候,就涉及远程调用.此 ...

  8. Docker镜像和容器管理(二)

    Docker安装 Docker镜像管理 https://hub.docker.com/ 是公共的一个Docker镜像仓库,类似GitHub一样,上面有非常多的开源项目镜像. 可以直接在命令行搜索镜像 ...

  9. 微服务-springboot日志配置

    springboot 默认会加载classpath:logback-spring.xml文件. springProfile 中的name名字对应application-xx.properties 中的 ...

  10. 【名额有限】云开发AI拓展能力等你来体验!

    这次来了个超厉害的新能力! 人脸智能打马赛克.人脸智能裁剪--各种操作,都能一步到位! 迫不及待想体验,戳链接:https://wj.qq.com/s2/3986990/e0ef/ 还没有搞懂,继续往 ...