LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2890|回复: 6

[==LFS精华系列==]内核模块详解

[复制链接]
发表于 2003-11-18 10:04:48 | 显示全部楼层 |阅读模式
本文件描述了 在linux内核中动态载入模块的策略,它不是模块内部结构的技术性描述,它更多的是
一个编译和使用模块的例子。

      注意:你必须确信你使用的modutils-x-y-x.tar.gz 是适于这个内核的最新的版本。“x.y.z"反映了发布
模块包时的内核版本。一些老的模块包认不出一些现在的内核所支持新的模块特性。当前要求的版本列在
文件 linux/Documentation/Changes里面。

  ***注意***
  内核已经改变成 支持移除模块 和 使用新的kmod支持。读本文时要留意这点。Kmod做kerneld同样的事,但
  不要求额外的程序(见 Documentation/kmod.txt)





  首先......
  -------------

  不管怎样,你第一步是编译内核,按文件 linux/README解释的那样。它一般是这样的:
          make config
        make dep
        make clean
        make zImge 或 make zlib
在'make config",你可选择你想 包含在”常驻“内核 和 你想作为可加载模块的特性,你通常选择那些在启动时需要的
最小的常驻集合:
             你的启动分区的文件系统
             一个SCSI驱动,但要看下面的  SCSI模块列表
             标准的硬盘支持
             网络支持(CONFIG_NET)
             TCP/IP支持(CONFIG INET),但没有驱动
             其他一些没有她 你就不能活的东东.......



        模块集是不断增长的,你能够在 “make config"里  为那些当前内核作为可加载模块提供的 特性选择”m"选项。
        你也能够创建很少依赖于核心版本的模块,在make config时通过使能CONIFIG_MODVERSIONS,在
稳定的内核版本(如1.2和2.0系列)中,这是非常有用的。
     如果你有一些非官方内核包所包含的 模块源代码,你肯定会喜欢这个选项.....

     这里是一个包含在内核源代码中的可用模块的 例子:
          大部分文件系统:minix,msdos,umsdos,sysv,isofs,hpfs,smbfs,nfs
           中级SCSI驱动:(为高层和底层 scsi驱动所需)
           所有的SCSI高级 驱动:disk,tape,cdrom,generic

           大部分以太网 驱动太多了,请看./Documentation/networking/net-modules.txt)
           大部分CDROM驱动:
                   aztcd:    Aztech,Orchild,Okana,Wearnes
                cm206: Philips/LMS CM206
                gscd: Goldstar GCDR-420
                mcd,mcdx:Mitsumi LU005,FX001
                optcd:         Optics Storage Dolphin 8000AT
                sjcd:           Sanyo CDR-H94A
                sbpcd:          Matsushita/Panasonic CR52x,CR56x,CD200,
                              Longshine LCS-7260,TEAC CD-55A
                sonycd535: Sony CDU-531/535, CDU-510/515

        其他一些多功能模块,如:
                 lp:line printer
                 binfmt_elf: elf loader(elf文件载入器)
                binfmt_java: java loader(java载入器)
                isp16: cdrom interface   (cdrom 接口)
                serial: the serial (tty) interface(串口)

        当你打造内核时,你可以这样建立模块:
        make modules
        这将编译所有的模块,更新linux/modules 路径。在这个路径里,你将找到
一堆指向 内核树 中不同的目标文件的符号链接。

        现在,在你建立里所有的模块之后,应该这样:
        make modules_install
        这会复制所有新的模块到”/lib/modules/kernel_release/的子目录,这里,“kernel_realease"是如同
2.0.1或者 当前的内核版本号的东东。

        一旦你重启使用了这个新内核,你就能够按照意愿用"insmod"和“rmmod” 安装 和移出模块。在读了
insmod的man-page之后,你也就会知道 你用insmod配置一个模块是多么容易。





有趣的特性:
----------------
        你也可使用两个工具:“modprobe”和“depmod”,modprobe是“insmod”的包装(或者说扩展)。
这些工具使用(和操作)一套 描述 当前内核所有可用模块(在/lib/modules)的层次以及依赖关系的文件。


            用modprobe 工具,你能像这样 载入任何模块,而无须考虑你正在运行 哪一个内核,或者这个模块依赖于什么模块:
          /sbin/modprobe module

        在modprobe配置文件(etc/modules.conf)的帮助下,你可在许多方面调整modprobe的行为,包括
为每个模块的insmod选项的自动设置。当然,所有这些都可以看 man-pages.

        为了成功使用modprobe,你一般可在/etc/rc.d/rc.S脚本中放置这样的命令:(更多的请读模块工具包
”modutils-x.y.z.tar.gz“中的“rc.hints"文档。)
        /sbin/depmod -a


       它将计算不同模块间的依赖关系。然后,举个例子(如果你想这样做的话):
             /sbin/modprobe umsdos
你将自动载入 msdos和umsdos模块,因为umsdos要运行在msdos之上。


使用modinfo:
------------------

有时候你需要知道一个  模块可用什么参数,或者你发现了一个bug,想同维护者联系,那么modinfo将是
非常方便的。

每个模块(一般而言)都有  作者/维护者 的描述和 参数列表。

举个例子,"modinfo -a eepro100"将会返回:
        Maintainer:Andrey V. Savochkin <saw@saw.sw.com.sg>
"modinfo -d eepro100"将返回一个描述:
        Intel i82557/i82558 PCI EtherExpressPro driver
更重要的,"modinfo -p eepro100"将返回这个列表:

        debug int
        options int array (min = 1, max = 8)
        full_duplex int array (min = 1, max = 8)
        congenb int
        txfifo int
        rxfifo int
        txdmacount int
        rxdmacount int
        rx_copybreak int
        max_interrupt_work int
        multicast_filter_limit int



”终极“功能:
--------------

       好了,你已经读了上面的,留有深刻印象.......
       现在,我们要告诉你,忘了一切 关于  安装和移除 可载入模块的东东....

       有了kerneld这个守护进程,所有这些杂务都将被自动处理。只要在配置核心"make config"时
CONFIG_KERNELD=y,并且确信在启动后,"/sbin/depmod -a"已经被执行后,尽可能快地开始/sbin/kerneld
(欲知详情,请读模块工具包中的相关内容)

         无论何时,如果一个程序想要   内核使用一个 只可作为可载入模块的特性时,如果内核还没有安装这个
模块,它会要求内核守护进程(kerneld)处理这种情信,尽力作好。

         下面是详细的处理过程:
         ---内核发现 被要求的功能没有驻留在内核里面
         ---内核发送一条消息给内核守护进程(kerneld),带有要求功能的符号描述
         ---内核守护进程请 modprobe之类的程序  载入一个适合于 这个符号描述的 模块
         ---modprobe浏览它内置的”别名“转换表看是否有一个匹配的。这个表能够用一个在"/etc/modules.conf"里的
”alias"行被配置和扩充。
         ---然后,insmod 插入一个 由modprobe决定    的内核需要的模块。每个模块将按照"/etc/modules.conf"
里“options”行    进行配置。
        ----modprobe退出,kerneld告诉kernel请求成功(或者失败....)
        ----如果该模块已经被作为常驻部分 配置进 内核,内核就照原样使用这个新安装的模块

        蛋糕上的酥皮(the icing of the cake)是:当自动安装模块一段时间(通常是1分钟)不用之后,该模块也将
被自动从内核中移除。


        这使内核在任何时间内都使用最少的内存,使其更具活力,而不是为无用的代码所占用。


         事实上,kerneld只有一点副作用:
         你必须建立一个最小的内核,它(内核)或多或少依赖于实际安装的硬件。“虚拟”内核的安装改为由其他
东东控制:配置文件以及 当前机器和它的内核的实际的使用模式。

        为了使用kerneld而避免太多的“争论”,你需要一个从   对你的内核而言是“最新”   的版本中取得modprobe,
和一个modprobe的配置文件("/etc/modules.conf")
        因为modprobe已经知道许多模块,最小的配置文件看来像这样:

        alias scsi_hostadapter aha1542  # or whatever SCSI adapter you hav
                                                      #e或者你的无论什么SCSI适配器
        alias eth0 3c509        # or whatever net adapter you have
                                #或者无论哪一种网络适配器
        # you might need an "options" line for some net adapters:
        #对于一些网络适配器,你需要一 个“选项”
        options 3c509 io=0x300 irq=10
        # you might also need an "options" line for some other module:
        #对其他一些模块,你也需要一个选项
        options cdu31a cdu31a_port=0x1f88 sony_pas_init=1

你也能够增加下面这些行,但它们都只是”摆个样子“:
        alias net-pf-3 off        # no ax25 module available (yet)
                                 #没有ax25模块可用
        alias net-pf-4 off        # if you don't use the ipx module
                                #如果你不使用ipx模块
        alias net-pf-5 off        # if you don't use the appletalk module
                               #如果你不使用appletalk模块


作者:
        Jacques Gelinas <jacques@solucorp.qc.ca>
        Bjorn Ekwall <bj0rn@blox.se>
译者:
        Ways Li <ways@pub.wjinfo.cn>


发表于 2003-11-18 10:51:32 | 显示全部楼层
ways兄辛苦了,谢谢!
发表于 2003-11-18 11:09:09 | 显示全部楼层

回复: modules.txt的翻译,对配置模块,修改modules.conf有帮助,见笑了:)

最初由 Ways 发表
本文件描述了 在linux内核中动态载入模块的策略,它不是模块内部结构的技术性描述,它更多的是
一个编译和使用模块的例子。

      注意:你必须确信你使用的modutils-x-y-x.tar.gz 是适于这个内核的最新的(版本)。“x.y.z"反映了发布
模块包时的内核版本。一些老的模块包认不出一些现在的内核所支持新的模块特性。当前要求的版本列在
文件 linux/Documentation/Changes里面。

  ***注意***
  内核已经改变成 支持移除模块 和 使用新的kmod支持。读本文时要留意这点。Kmod做kerneld同样的事,但
  不要求额外的程序(见 Documentation/kmod.txt)





  首先......
  -------------

  不管怎样,你第一步是编译内核,按文件 linux/README解释的那样。它一般是这样的:
          make config
        make dep
        make clean
        make zImge 或 make zlib
在'make config",你可选择你想 包含在”常驻“内核 和 你想作为可加载模块的特性,你通常选择那些在启动时需要的最小的常驻
集合:
             你的启动分区的文件系统
             一个SCSI驱动,但要看下面的  SCSI模块列表
             标准的硬盘支持
             网络支持(CONFIG_NET)
             TCP/IP支持(CONFIG INET),但没有驱动

             其他一些没有她 你就不能活的东东.......

        模块集是不断增长的,你能够在 “make config"里  为那些当前内核作为可加载模块提供的 特性选择”m"选项。
        你也能够创建很少依赖于核心版本的模块,在make config时通过使能CONIFIG_MODVERSIONS,在
稳定的内核版本(如1.2和2.0系列)中,这是非常有用的。
     如果你有一些非官方内核包所包含的 模块源代码,你肯定会喜欢这个选项.....

     这里是一个包含在内核源代码中的可用模块的 例子:
          大部分文件系统:minix,msdos,umsdos,sysv,isofs,hpfs,smbfs,nfs
           中级SCSI驱动:(为高层和底层 scsi驱动所需)
           所有的SCSI高级 驱动:disk,tape,cdrom,generic

           大部分以太网 驱动太多了,请看./Documentation/networking/net-modules.txt)
           大部分CDROM驱动:
                   aztcd:    Aztech,Orchild,Okana,Wearnes
                cm206: Philips/LMS CM206
                gscd: Goldstar GCDR-420
                mcd,mcdx:Mitsumi LU005,FX001
                optcd:         Optics Storage Dolphin 8000AT
                sjcd:           Sanyo CDR-H94A
                sbpcd:          Matsushita/Panasonic CR52x,CR56x,CD200,
                              Longshine LCS-7260,TEAC CD-55A
                sonycd535: Sony CDU-531/535, CDU-510/515

        其他一些多功能模块,如:
                 lp:line printer
                 binfmt_elf: elf loader(elf文件载入器)
                binfmt_java: java loader(java载入器)
                isp16: cdrom interface   (cdrom 接口)
                serial: the serial (tty) interface(串口)

        当你打造内核时,你可以这样建立模块:
        make modules
        这将编译所有的模块,更新linux/modules 路径。在这个路径里,你将找到
a bunch of指向      内核树中 不同的目标文件的符号链接。

        现在,在你建立里所有的模块之友,也应该这样:
        make modules_install
        这会复制所有新的模块到”/lib/modules/kernel_release/的子目录,这里,“kernel_realease"是如同
2.0.1或者 当前的内核版本号的东东。

        一旦你重启使用了这个新内核,你就能够按照意愿用"insmod"和“rmmod” 安装 和移出模块。在读了
insmod的man-page之后,你也就会知道 你用insmod配置一个模块是多么容易。





有趣的特性:
----------------
        你也使用了两个工具:“modprobe”和“depmod”,modprobe是“insmod”的包装(或者说扩展)。
这些工具使用(和操作)一套 描述 当前内核所有可用模块(在/lib/modules)的层次以及依赖关系的文件。


            用modprobe 工具,你能像这样 载入任何模块,而无须考虑你正在运行 哪一个内核,或者这个模块依赖于什么模块:
          /sbin/modprobe module

        在modprobe配置文件(etc/modules.conf)的帮助下,你可在许多方面调整modprobe的行为,包括
为每个模块的insmod选项的自动设置。当然,所有这些都可以看 man-pages.

        为了成功使用modprobe,你一般可在/etc/rc.d/rc.S脚本中放置这样的命令:(更多的请读模块工具包
”modutils-x.y.z.tar.gz“中的“rc.hints"文档。)
        /sbin/depmod -a


       它将计算不同模块间的依赖关系。然后,举个例子(如果你想这样做的话):
             /sbin/modprobe umsdos
你将自动载入 msdos和umsdos模块,因为umsdos要运行在msdos之上。


使用modinfo:
------------------

有时候你需要知道一个  模块可用什么参数,或者你发现了一个bug,想同维护者联系,那么modinfo将是
非常方便的。

每个模块(一般而言)都有  作者/维护者 的描述和 参数列表。

举个例子,"modinfo -a eepro100"将会返回:
        Maintainer:Andrey V. Savochkin <saw@saw.sw.com.sg>
"modinfo -d eepro100"将返回一个描述:
        Intel i82557/i82558 PCI EtherExpressPro driver
更重要的,"modinfo -p eepro100"将返回这个列表:

        debug int
        options int array (min = 1, max = 8)
        full_duplex int array (min = 1, max = 8)
        congenb int
        txfifo int
        rxfifo int
        txdmacount int
        rxdmacount int
        rx_copybreak int
        max_interrupt_work int
        multicast_filter_limit int



”终极“功能:
--------------

       好了,你已经读了上面的,留有深刻印象.......
       现在,我们要告诉你,忘了一切 关于  安装和移除 可载入模块的东东....

       有了kerneld这个守护进程,所有这些杂务都将被自动处理。只要在配置核心"make config"时
CONFIG_KERNELD=y,并且确信在启动后,"/sbin/depmod -a"已经被执行后,尽可能快地开始/sbin/kerneld
(欲知详情,请读模块工具包中的相关内容)

         无论何时,如果一个程序想要   内核使用一个 只可作为可载入模块的特性时,如果内核还没有安装这个
模块,它会要求内核守护进程(kerneld)处理这种情信,尽力作好。

         下面是详细的处理过程:
         ---内核发现 被要求的功能没有驻留在内核里面
         ---内核发送一条消息给内核守护进程(kerneld),带有要求功能的符号描述
         ---内核守护进程请 modprobe之类的程序  载入一个适合于 这个符号描述的 模块
         ---modprobe浏览它内置的”别名“转换表看是否有一个匹配的。这个表能够用一个在"/etc/modules.conf"里的
”alias"行被配置和扩充。
         ---然后,insmod 插入一个 由modprobe决定    的内核需要的模块。每个模块将按照"/etc/modules.conf"
里“options”行    进行配置。
        ----modprobe退出,kerneld告诉kernel请求成功(或者失败....)
        ----如果该模块已经被作为常驻部分 配置进 内核,内核就照原样使用这个新安装的模块

        蛋糕上的酥皮(the icing of the cake)是:当自动安装模块一段时间(通常是1分钟)不用之后,该模块也将
被自动从内核中移除。


        这使内核在任何时间内都使用最少的内存,使其更具活力,而不是为无用的代码所占用。


         事实上,kerneld的只有一点副作用:
         你必须建立一个最小的内核,它(内核)或多或少依赖于实际安装的硬件。“虚拟”内核的安装改为由其他
东东控制:配置文件以及 当前机器和它的内核的实际的使用模式。

        为了使用kerneld而避免太多的“争论”,你需要一个从   对你的内核而言是“最新”   的版本中取得modprobe,
和一个modprobe的配置文件("/etc/modules.conf")
        因为modprobe已经知道许多模块,最小的配置文件看来像这样:

        alias scsi_hostadapter aha1542  # or whatever SCSI adapter you hav
                                                      #e或者你的无论什么SCSI适配器
        alias eth0 3c509        # or whatever net adapter you have
                                #或者无论哪一种网络适配器
        # you might need an "options" line for some net adapters:
        #对于一些网络适配器,你需要一 个“选项”
        options 3c509 io=0x300 irq=10
        # you might also need an "options" line for some other module:
        #对其他一些模块,你也需要一个选项
        options cdu31a cdu31a_port=0x1f88 sony_pas_init=1

你也能够增加下面这些行,但它们都只是”摆个样子“:
        alias net-pf-3 off        # no ax25 module available (yet)
                                 #没有ax25模块可用
        alias net-pf-4 off        # if you don't use the ipx module
                                #如果你不使用ipx模块
        alias net-pf-5 off        # if you don't use the appletalk module
                               #如果你不使用appletalk模块


作者:
        Jacques Gelinas <jacques@solucorp.qc.ca>
        Bjorn Ekwall <bj0rn@blox.se>
译者:
        Ways Li <ways@pub.wjinfo.cn>





而无须考虑你正在运行 哪一个内核

??????
发表于 2003-11-18 11:38:21 | 显示全部楼层
$ cat /usr/src/linux/.config | grep KERNELD

什么都没有?这篇文章对应哪个kernel版本呀,看内容好像是2.0?
 楼主| 发表于 2003-11-18 15:42:44 | 显示全部楼层
-------------请        qing兄指教-------
这是原文:
Using the modprobe utility, you can load any module like this:

        /sbin/modprobe module

without paying much attention to which kernel you are running, or what
other modules this module depends on.

我的理解是这样的:
    我使用了三个不同的内核,分别是2.4.22和2.4.20,还有2.6.0-test9,
都放在/boot下面,在/lib/modules 下也有三个子目录,对应于三个不同内核
的可加载模块.
    我的网卡,用的是tulip驱动,在modules.conf只有一行关于它的setting:
     alias eth0 tulip
     用这个共同的modules.conf配置文件,无论我 boot是选择 哪个kernel,
我都可以用 :
    modprobe tulip
正确加载相应的模块,而不会产生混淆。
     所以说,我不用在意我当前运行的哪一个内核。

     但是,如果我运行  2.6.0-test9的内核,到/lib/modules/2.4.22目录里
用insmod加载2.4.22的tulip模块,会失败(废话,当然会失败:-)



-----------------------------答penny兄------
***注意***
  内核已经改变成 支持移除模块 和 使用新的kmod支持。读本文时要留意这点。

CONFIG_KMOD可以找到,呵呵

这是2.4.22的文档中带的modules.txt


------------------------------to all----------
   我很菜,也在学习:p
   翻译能够强迫自己 看文档
    有时间,我打算也看看 kmod.txt

    今天搬家,好累
 楼主| 发表于 2003-11-18 16:51:37 | 显示全部楼层

kmod.txt很短,但是很难翻译

Kmod:内核模块载入器
Kirk Petersen

Kmod是一个kerneld的简单代替者。它由一个request_module()替代和一个叫做 kmod的内核线程组成.
当内核要求一个模块时,kmod通过所要求的名字来唤醒和执行modprobe

如果你安装了/proc文件系统,你可设置modprobe的路径(就是内核到哪里去找modprobe):

        echo "/sbin/modprobe" > /proc/sys/kernel/modprobe

为了定时地卸载不用的模块,将下面的这些放到root的crontab入口:

        0-59/5 * * * * /sbin/rmmod -a

Kmod只载入模块。kerneld做更多事情(尽管在标准的kernel里不会用到它的其它特性)。如果你要求像
request_route之类的功能,我们建议你 采取类似的方法。一个简单的request_route函数被调用,一个kroute
内核线程就会发出来做这个工作        但我们或许应该使其最小。

kernled也有一个存储  设备驱动程序  设置的机制。用modprobe来做很简单。当一个模块被卸载时,
modprobe能  在每一个驱动配置定位per-driver-configurable(/proc/sys/drivers/blash)里  查找设备驱动设置,并把它们存为一个文件。当一个模块加载时,简单地cat这个文件回proc文件系统的位置。
或者,一个脚本也可能是在/etc/modules.conf的一个设置。有很多方法可以用(我个人更喜欢用/proc)

为什么要替换kerneld?
        ---kerneld 用SysV IPC,而它现在可以编译成一个模块。除了这点,SysV IPC很差劲,应该避免
           (当然是对内核级的东东而言)
        ---kmod和kerneld最终都要做同样的事情(调用modprobe),为什么不跳过  中间人呢?
        ---从ipc/msg.c 中移除kerneld相关的东东,可以使它减小40%
        ---kmod通过标准的内核机制报告错误,避免了kerneld和Unix domain sockets之间
            鸡生蛋和蛋生鸡的问题。

Keith Owens <kaos@ocs.com.au> 1999.12

kmod和modprobe的联合能够循环,特别是modprobe用一个要求一个模块的系统调用时。
如果modules.dep不存在,modprobe就会被(kmod)以-s 选项开始,modprobe 试图syslog()一个消息,
syslog()需要Unix sockets,如果Unix是一个模块,那么kmod运行“ modprobe -s net-pf-1"。这运行一个
modprobe的拷贝,它报怨modules.dep不存在,试图用syslog(),开始另一个modprobe的拷贝。这不是唯一的
kmod/modprobe循环的情形,只是最普遍的。

        为了检测由”modprobe需要一个模块化的服务“所引起的循环,kmod限制kmod发出的modprobes并发数目。见
kernle/kmod.c中的MAX_KMOD_CONCURRENT。当这个限制被处理是,kernel发出消息”kmod:runaway modprobe loop assumed and stopped"。

对用户而言,建立一个很模块化的系统时需要注意的是:在安装完模块后,在第一次启动新内核前,创建
modules.dep是个好主意。“depmod -ae m.n.p",这里m.n.p时新内核的版本号。
发表于 2003-11-18 20:31:44 | 显示全部楼层
to penny:

$ cat /usr/src/linux/.config | grep KERNELD

什么都没有?这篇文章对应哪个kernel版本呀,看内容好像是2.0?





***注意***
内核已经改变成 支持移除模块 和 使用新的kmod支持。读本文时要留意这点。Kmod做kerneld同样的事,但
不要求额外的程序(见 Documentation/kmod.txt)



仔细看看就明白了:)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表