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

更多内容请参考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. java多线程之生产者-消费者

    public class Product { private String lock; public Product(String lock) { this.lock = lock; } public ...

  2. python遍历多个列表生成列表或字典

    key=['a','b','c','d'] value=[1,2,3,4] mydict=dict(zip(key,value)) print mydict 输出结果: {'a': 1, 'c': 3 ...

  3. Unity AssetBundle,Asset,GameObject之间的联系

    一.问题 首先,这里说明一下,我这边的GameObject有点笼统,就是表达的是游戏中的具体实例. 二.概念 1)Asset是什么? 游戏中具体的资源,像texture,mesh,material,s ...

  4. 短视频技术详解:Android端的短视频开发技术

    在 <如何快速实现移动端短视频功能?>中,我们主要介绍了当前短视频的大热趋势以及开发一个短视频应用所涉及到的功能和业务.在本篇文章中,我们主要谈一谈短视频在Android端上的具体实现技术 ...

  5. java模拟键鼠操作

    很久之前百度的,所以忘记了作者,所以仅作为自己的日记纪录在此: package com.robot.test;import java.awt.AWTException;import java.awt. ...

  6. 手动安装gitlab-runner

    手动安装gitlab-runner 在终端使用命令curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runn ...

  7. RocketMQ与MYSQL事务消息整合

    1.基础理论知识篇“两阶段提交”如果你了解可以跳过这段,当然如果你想深入了解你可以购买相关书籍或去搜索相关资料阅读 两阶段提交分为 正常提交和异常提交或异常回滚 上面是正常提交的示意图,协调者发起预提 ...

  8. Codeforces Gym101246J:Buoys(三分搜索)

    http://codeforces.com/gym/101246/problem/J 题意:给出n个点坐标,要使这些点间距相同的话,就要移动这些点,问最少的需要的移动距离是多少,并输出移动后的坐标. ...

  9. c++ 二分答案

    c++ 二分答案 问题 使得x^x达到或超过n位数字的最小正整数x是多少?n<=2000000000 分析 对与这种较难求解的问题,我们很难想出较好的解决策略.但是,我们至少知道答案一定在1与2 ...

  10. EnjoyingSoft之Mule ESB开发教程系列第五篇:控制消息的流向-数据路由

    目录 1. 使用场景 2. 基于消息头的路由 2.1 使用JSON提交订单的消息 2.2 使用XML提交订单的消息 2.3 使用Choice组件判断订单格式 3. 基于消息内容的路由 4. 其他控制流 ...