问题
1. 把编译好的模块放到板子/lib/modules对应文件夹下,并且执行了depmod -a, 比如pl2303.ko, 那么下一次插入pl2303的串口线,是否可以识别,也就是自动加载pl2303驱动?
--------------------------------------------------------------------------------------------------------------
转自:http://blog.csdn.net/hunanchenxingyu/article/details/47292327

一、安装内核模块

一般步骤:

  1. 在/usr/src/Linux/下运行make menuconfig把需要编译成模块的项打上(M),保存并退出。
  2. 运行make modules,这一步将在/usr/src/linux/下生成*.o或*.ko文件。
  3. 运行make modeules_install来安装,这步会把生成的.o或ko文件拷贝到/lib/modules/`uname -r`/下。

如果你只要编译某一个或几个模块,就可以用下面这个快速的方法:

  1. 找到编译内核所需要的.config文件。 在/usr/src/linux/arch目录下有若干编译内核所用的配置。选择我们想要的配置,将它复制到/usr/src/linux目录下,改名为.config。 cp /usr/src/linux/arch/x86/xxconfig /usr/src/linux/.config
  2. 修改.config文件,去掉不用的模块,加上自己想要的模块。 打开.config,有许多XXXX=m的项,这些都是要被编译为模块 的项,因为我们不希望编译这些模块,所以要把XXXX=m的项统统去掉。然后再加上我们想要的模块,例如将# CONFIG_NTFS_FS is not set 改为CONFIG_NTFS_FS=m 当然,可以用你熟悉各种工具来做这件事。
  3. 编译NTFS模块。在/usr/src/linux目录下运行命令make modules来编译我们想要的模块。
  4. 安装模块。 编译后得到的.o文件在/usr/src/linux/目录下,手动将它复制到正确的目录下。 例如cp /usr/src/linux/fs/ntfs/ntfs.o /lib/modules/2.2.16-22/fs/

 注意:千万不能运行命令make modules_install,否则将带来严重的后果,它会删除你系统中的所有模块,只安装刚刚编译的模块(ntfs.o)。

二:安装完成以后,我们就可以加载模块了

和linux中加载模块有关的几个命令分别如下:

depmod, modprobe, lsmod

2.1.先来看看depmod命令:

depmod是一个 用来产生modules.dep和map文件的程序。在modules.dep文件中空白行和以'#'开头的行将被忽略.depmod通过读取/lib /modules/version目录下的每一个模块来创建一个记录模块相依性的列表。这个列表就是/lib/modules/version目录下的 modules.dep。depmod也会在/lib/modules/version目录下创建许多map文件,例如 modules.dep,modules.isapnpmap,modules.pcimap,modules.alias这些文件将会被hotplug 用到。

OPTIONS:
-a --all Probe all modules. This option is enabled by default if no
            file names are given in the command-line.
检查所有的模块,这个命令是默认的如果你没有指定模块名字的话。

-A --quick This option scans to see if any modules are newer than the
                 modules.dep file before any work is done%3

2.2.再来看看modprobe命令:

modprobe 命令是根据depmod -a的输出/lib/modules/version/modules.dep来加载全部的所需要模块。可以通过modprobe -l来显示可以当前可以加载的模块。modprobe 在挂载模块是不用指定模块文件的路径,也不用带文件的后缀.o 或.ko, 而insmod 需要的是模块的所在目录的绝对路径,并且一定要带有模块文件名后缀的(modulefile.o 或modulesfile.ko )。 insmod比较重要的用途是用来测试模块的正确性,加载一般都是依靠modprobe。

用法:modprobe xxx.ko        #加载某个模块
modprobe -r xxx.ko     #卸载某个模块

2.3.lsmod:

lsmod 显示当前加载的所有 模块,相当于cat /proc/modules,假设你没有设定开机加载某个模块,比如ntfs,那么开机后执行lsmod,列表里不会有ntfs这个模块的,这时你再执行 mount -t ntfs xxx后,执行lsmod后列表里就会有ntfs这个模块了。
还要注意的是lsmod显示的是模块名,而不是别名(alias)。

2.4.modinfo

显示kernel模块的对象文件,以显示该模块的相关信息

三、系统如何完成动态加载

在内核中有一个“Automatic kernel module loading"功能被编译到了内核中。当用户尝试打开某类型的文件时,内核会根据需要尝试加载相应的模块。我们来看看驱动程序自动加载是怎么实现的:

每一个设备都有Verdon ID, Device ID, SubVendor ID等信息。而每一个设备驱动程序,必须说明自己能够为哪些Verdon ID, Deviece

ID, SubVendor ID的设备提供服务。以PCI设备为例,它是通过一个pci_device_id的数据结构来实现这个功能的。例如:RTL8139的pci_device_id定义为:

static struct pci_device_id rtl8139_pci_tbl[] = {
{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, , , RTL8139 },
{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, , , RTL8139 },
......

在模块安装的时候,depmod会根据模块中的rtl8139_pci_tbl的信息,生成下面的信息,保存到/lib/modules/uname-r /modules.alias文件中,其内容如下:

alias pci:v000010ECd00008138sv*sd*bc*sc*i* 8139too
alias pci:v000010ECd00008139sv*sd*bc*sc*i* 8139too
......

另外在/lib/modules/uname-r /modules.dep文件中还保存这模块之间的依赖关系,其内容如下:

(这里省去了路径信息。)

8139too.ko:mii.ko

在内核启动过程中,

  • 总线驱动程序会按总线协议进行总线枚举,并且为每一个设备建立一个设备对象(总线驱动程序总是集成在内核之中,不能够按模块方式加载,你可以通过make menuconfig进入Bus options,这里面的各种总线,你只能够选择Y或N,而不能选择M.)。
  • 每一个总线对象有一个kset对象,每一个设备对象嵌入了一个kobject对象,kobject连接在kset对象上,这样总线和总线之间,总线和设备之间就组织成一颗树状结构。
  • 当总线驱动程序为扫描到的设备建立设备对象时,会初始化kobject对象,并把它连接到设备树中,同时会调用kobject_uevent()把这个(添加新设 备的)事件,以及相关信息(包括设备的VendorID,DeviceID等信息)。
  • 通过netlink发送到用户态中。在用户态的udevd检测到这个 事件,就可以根据这些信息,打开/lib/modules/uname-r /modules.alias文件,根据 alias pci:v000010ECd00008138sv*sd*bc*sc*i* 8139too 得知这个新扫描到的设备驱动模块为8139too。
  • 于是modprobe就知道要加载8139too这个模块了,同时modprobe根据 modules.dep文件发现,8139too依赖于mii.ko,如果mii.ko没有加载,modprobe就先加载mii.ko,接着再加载 8139too.ko。

实验

在你的shell中,运行:

# ps aux | grep udevd

# kill -9 25063 然后跟踪udevd,在shell中运行:

# strace -f /sbin/udevd --daemon  这时,我们看到udevd的输出如下:

 ......
close() =
munmap(0xb7f8c000, ) =
select(, [ ], NULL, NULL, NULL

我们发现udevd在这里被阻塞在select()函数中。 select函数原型如下:  int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

  • 第一个参数:nfds表示最大的文件描述符号,这里为7(明明是6 ?)。
  • 第二个参数:readfds为读文件描述符集合,这里为3,4,5,6.
  • 第三个参数:writefds为写文件描述符集合,这里为NULL。
  • 四个参数:exceptfds为异常文件描述符集合,这里为NULL。 第五个参数:timeout指定超时时间,这里为NULL。

select函数的作用是:

如果readfds中的任何一个文件有数据可读,或者witefds中的任何一个文件可以写入,或者exceptfds中的任 何一个文件出现异常时,就返回。否则阻塞当前进程,直到上诉条件满足,或者因阻塞时间超过了timeout指定的时间,当前进程被唤醒,select返 回。 所以,在这里udevd等待3,4,5,6这几个文件有数据可读,才会被唤醒。现在,到shell中运行:  # ps aux | grep udevd root ...... strace -o /tmp/udevd.debug -f /sbin/udevd --daemon root ...... /sbin/udevd --daemon  udevd的进程id为27617,现在我们来看看select等待的几个文件: # cd /proc/27615/fd # ls -l udevd的标准输入,标准输出,标准错误全部为 /dev/null. -> /dev/null -> /dev/null -> /dev/null  udevd在下面这几个文件上等待。  -> /inotify -> socket:[] -> socket:[] -> pipe:[] -> pipe:[]

由于不方便在运行中插入一块8139的网卡,因此现在我们以一个U盘来做试验,当你插入一个U盘后,你将会看到strace的输出,从它的输出可以看到 udevd在select返回后,调用了modprobe加载驱动模块,并调用了sys_mknod,在dev目录下建立了相应的节点。

execve("/sbin/modprobe", ["/sbin/modprobe", "-Q", "usb:v05ACp1301d0100dc00dsc00dp00"...] ...... mknod("/dev/sdb", S_IFBLK|, makedev(, )) =  ......

这里modprobe的参数"usb:v05AC..."对应modules.alias中的某个模块。 可以通过udevmonitor来查看内核通过netlink发送给udevd的消息,在shell中运行: # udevmonitor --env 然后再插入U盘,就会看到相关的发送给udevd的消息。

四、内核模块加载的配置:

有时候需要一次性加载许多模块,需要在一个地方统一配置modprobe的选项等,有一个比较重要的文件: /etc/modprobe.conf , 在opensuse中,和它有关的还有modprobe.d/文件夹下的许多文件和 modprobe.conf.local 文件,在  /etc/modprobe.conf 里会include其它所有的文件,一般建议在 modprobe.conf.local 中修改自己的配置。  /etc/modprobe.conf 其实就是用于 写入模块的加载命令或模块的别名的定义等。 man modprobe.conf :

alias my-mod really_long_modulename为模块定义一个便于使用的别名

options modulename option...在加载模块时添加选项

install modulename command...使用自己定义的命令去加载指定的模块,如install fred /sbin/modprobe barney; /sbin/modprobe
              --ignore-install fred" 每次加载fred模块的时候用的是 “/sbin/modprobe barney; /sbin/modprobe
              --ignore-install fred”命令

remove modulename command...用自己定义的命令删除指定的模块。

include filename 引入其它文件

blacklist modulename 不再加载某个模块

五、内核模块开机自动挂载:

对于开机自动挂载模块,在redhat系统里,网上说在内核启动的过程中,init执行/etc/rc.d/rc.sysinit后,启动内核外挂模块 时会读取 /etc/modprobe.conf 这个文件。在2.4的内核中, 只 要直接修改/etc/modprobe.conf加入install xxx即可。2.6内核则需修改/etc/rc.d/rc.sysinit文件。具体的过程可以看:http://blog.csdn.NET/ioriqqe/archive/2009/11/05/4772033.aspx

而在suse里,可以在root权限编辑/etc/sysconfig/kernel文件,添加需要启动的模块。

[driver]linux内核动态加载模块的更多相关文章

  1. stevedore动态加载模块

    stevedore动态加载模块,stevedore使用setuptools的entry points来定义并加载插件.entry point引用的是定义在模块中的对象,比如类.函数.实例等,只要在im ...

  2. linux内核被加载的过程

    二,linux内核被加载的过程 一,linux安装时遇到的概念解析 内核必须模块vmlinz(5M左右)不认识硬盘,原本是需要写跟loader中一样的内容,来加载非必要模块. 内核非必要的功能被编译为 ...

  3. AngularJs 动态加载模块和依赖

    最近项目比较忙额,白天要上班,晚上回来还需要做Angular知识点的ppt给同事,毕竟年底要辞职了,项目的后续开发还是需要有人接手的,所以就占用了晚上学习的时间.本来一直不打算写这些第三方插件的学习笔 ...

  4. angular-ui-router动态加载模块

    1.定义index.html主页,对于通用的js就不用require依赖加载了,其中main.js作为主模块,用require添加系统路由模块. <!DOCTYPE html> <h ...

  5. Apache动态加载模块

    添加步骤:如要额外安装cgi,先找到mod_cgi.c及mod_cgid.c.一般在apache安装包目录下,如 ./httpd-2.2.25/modules/generators .#编译安装 cg ...

  6. ubuntu动态加载模块简单模板

    1:简单代码 #include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("GPL"); ...

  7. linux 内核驱动加载过程中 向文件系统中的文件进行读写操作

    utils.h 文件: #ifndef __UTILS_H__ #define __UTILS_H__ void a2f(const char *s, ...); #endif utils.c 文件: ...

  8. 配置动态加载模块和js分模块打包,生产环境和开发环境公共常量配置

    1. 话不多少 先上代码:  route.js  // 引用模板 分模块编译 const main = r => require.ensure([], () => r(require('. ...

  9. Python importlib 动态加载模块

    # 创建一个 src 文件夹,里面有一个 commons.py 文件,内容如下 def add(): print("add ....") # 创建一个 app.py 文件,内容如下 ...

随机推荐

  1. iOS9 适配(杂七杂八)

    1.iOS9 以后,table cell 在旋转的时候会自动调整视图内容的布局,设置以下的属性,课禁止该行为. if (runTimeOSVersion >= 9.0f) { _listTabl ...

  2. 我心中的核心组件(可插拔的AOP)~第四回 异常拦截器

    回到目录 之前说过有关拦截器的文章,第二回  缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interceptio ...

  3. jquery学习笔记---this关键字

    1.    在JavaScript的变量作用域里有一条规则“全局变量都是window对象的属性”.当执行 checkThis() 时相当于 window.checkThis(),因此,此时checkT ...

  4. JAVA类与对象作业——动手动脑以及课后实验性问题

    一: 1.源代码 //MAO2015.10.6 //foo class Foo { int value; public Foo(int initValue) { value = initValue; ...

  5. TFS 2010 使用手册(二)项目集合与项目

    1.项目集合 1.1 项目集合创建 打开TFS管理控制台,点击“团队项目集合”. 图1点击“团队项目集合” 图2 点击“创建集合” 然后按照向导一步步完成项目集合的创建. 1.2 项目集合的删除 选中 ...

  6. 转帖:使用TortoiseGit处理代码冲突

    原址:http://www.cnblogs.com/jason-beijing/p/5718190.html   场景一  user0 有新提交 user1 没有pull -> 写新代码 -&g ...

  7. python seq

    missing parentheses in call to print  ==> python高版本 print("") name 'raw_input' is not d ...

  8. C# Excel操作类

    /// 常用工具类——Excel操作类 /// <para> ------------------------------------------------</para> / ...

  9. BZOJ3401: [Usaco2009 Mar]Look Up 仰望

    3401: [Usaco2009 Mar]Look Up 仰望 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 87  Solved: 58[Submit ...

  10. EXCEPTION与ERROR的区别

    EXCEPTION与ERROR的区别