驱动中的模块

90 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 29 天,点击查看活动详情

一、模块传参

一个模块向内核模块传参,例如main函数。

一个模块用了另一个模块的数据,这称为模块依赖。

示例程序

module_param(name,type,perm);//将指定的全局变量设置成模块参数 
/* name:全局变量名 
type: 
使用符号         实际类型           传参方式 
 bool             bool         insmod xxx.ko 变量名=0 或 1 
 invbool          bool         insmod xxx.ko 变量名=0 或 1 
 charp            char *       insmod xxx.ko 变量名="字符串内容 
 short            short        insmod xxx.ko 变量名=数值 
 int              int          insmod xxx.ko 变量名=数值 
 long             long         insmod xxx.ko 变量名=数值 
 ushort       unsigned short   insmod xxx.ko 变量名=数值 
 uint         unsigned int     insmod xxx.ko 变量名=数值 
 ulong        unsigned long    insmod xxx.ko 变量名=数值 
 
perm:给对应文件 /sys/module/name/parameters/变量名 指定操作权限 
#define S_IRWXU 00700 
#define S_IRUSR 00400 
#define S_IWUSR 00200 
#define S_IXUSR 00100 
#define S_IRWXG 00070 
#define S_IRGRP 00040 
#define S_IWGRP 00020 
#define S_IXGRP 00010 
#define S_IRWXO 00007 
#define S_IROTH 00004 
#define S_IWOTH 00002 //不要用 编译出错 
#define S_IXOTH 00001
*/

注意 可用MODULE_PARAM_DESC宏对每个参数进行作用描述,用法:

MODULE_PARM_DESC(变量名,字符串常量) ;

字符串常量的内容用来描述对应参数的作用

modinfo可查看这些参数的描述信息

二、模块依赖

既然内核模块的代码与其它内核代码共用统一的运行环境,也就是说模块只是存在形式上独立,运行上其实和内核其它源码是一个整体,它们隶属于同一个程序,因此一个模块或内核其它部分源码应该可以使用另一个模块的一些全局特性。

一个模块中这些可以被其它地方使用的名称被称为导出符号,所有导出符号被填在同一个表中这个表被称为符号表。

B模块使用了A模块导出的符号,此时称B模块依赖于A模块,则:

  1. 编译次序:先编译模块A,再编译模块B,当两个模块源码在不同目录时,需要:

    i. 先编译导出符号 的模块A

    ii. 拷贝A模块目录中的Module.symvers到B模块目录

    iii. 编译使用符号的模块B。否则编译 B模块时有符号未定义错误

  2. 加载次序:先插入A模块,再插入B模块,否则B模块插入失败

  3. 卸载次序:先卸载B模块,再卸载A模块,否则A模块卸载失败

三、内核空间和用户空间

为了彻底解决一个应用程序出错不影响系统和其它app的运行,操作系统给每个app一个独立的假想的地址空间,这个假想的地址空间被称为虚拟地址空间(也叫逻辑地址),操作系统也占用其中固定的一部分,32位Linux的虚拟地址空间大小为4G ,并将其划分两部分:(mmu映射)

  1. 0~3G 用户空间 :每个应用程序只能使用自己的这份虚拟地址空间

  2. 3G~4G 内核空间:内核使用的虚拟地址空间,应用程序不能直接使用这份地址空间,但可以通过一些系统调用函数与其中的某些空间进行数据通信

实际内存操作时,需要将虚拟地址映射到实际内存的物理地址,然后才进行实际的内存读写。

这里需要注意的一点是:内核:开始一段程序没有虚拟空间,在物理地址执行完启动mmu开始在虚拟地址空间运行程序。

四、执行流

执行流:有开始有结束总体顺序执行的一段独立代码,又被称为代码上下文

计算机系统中的执行流的分类:

  • 执行流:

    1. 任务流--任务上下文(都参与CPU时间片轮转,都有任务五状态:就绪态、运行态、睡眠态、僵死态、暂停态)
      1. 进程

      2. 线程

        1. 内核线程:内核创建的线程

        2. 应用线程:应用进程创建的线程

    2. 异常流--异常上下文
      1. 中断

      2. 其它异常

  • 应用编程可能涉及到的执行流:

    1. 进程

    2. 线程

内核编程可能涉及到的执行流:

  1. 应用程序自身代码运行在用户空间,处于用户态 ----------------- 用户态app

  2. 应用程序正在调用系统调用函数,运行在内核空间,处于内核态,即代码是内核代码但处于应用执行流(即属于一个应用进程或应用线程) -------------------- 内核态app

  3. 一直运行于内核空间,处于内核态,属于内核内的任务上下文 --------- 内核线程

  4. 一直运行于内核空间,处于内核态,专门用来处理各种异常 --------- 异常上下文