快捷搜索:  as  2018  FtCWSyGV  С˵  test  xxx  Ψһ  w3viyKQx

澳门新葡亰黑平台:精华推荐:内核模块编程的详细介绍



不知道在什幺时刻,Linux 呈现了 module 这种器械,切实着实,它是 Linux 的一大年夜改革。有了 module 之后,写 device driver 不再是一项噩梦,改动 kernel 也不再是一件苦楚的事了。由于你不必要每次要测试 driver 就从新 compile kernel 一次。那的确是会累逝众人。Module 可以容许我们动态的改变 kernel,加载 device driver,而且它也能缩短我们 driver development 的光阴。在这篇文章里,我将要跟各位先容一下 module 的道理,以及若何写一个 module。

module 翻译成中文便是模块,不过,事实上去翻译这个字一点都没意义。在讲模块之前,我先举一个例子。信托很多人都用过 RedHat。在 RedHat 里,我们可以履行 sndconfig,它可以帮我们 config 声卡。config 完之后假如捉获得你的声卡,那你的声卡顿时就可以动了,而且还不用从新激活谋略机。这是怎幺做的呢 ? 便是靠module。module 着实是一样平常的法度榜样。然则它可以被动态载到 kernel 里成为 kernel的一部分。载到 kernel 里的 module 它具有跟 kernel 一样的权力。可以 access 任何 kernel 的 data structure。你听过 kdebug 吗 ? 它是用来 debug kernel 的。它便是先将它本身的一个 module 载到 kernel 里,而在 user space 的 gdb 就可以经过跟这个 module 沟通,得知 澳门新葡亰黑平台kernel 里的 data structure 的值,除此之外,还可以经过载到 kernel 的 module 去变动 kernel 里 data structure。

我们知道,在写 C 法度榜样的时刻,一个法度榜样只能有一个 main。Kernel 本身着实也是一个法度榜样,它本身也有个 main,叫 start_kernel()。当我们把一个 module 载到 kernel 里的时刻,它会跟 kernel 整合在一路,成为 kernel 的一部分。请各位想想,那 module 可以有 main 吗 ? 谜底很显着的,是 No。来由很简单。一个法度榜样只能有一个 main。在应用 module 时,有一点要记着的是 module 是处于被动的角色。它是供给某些功能让别人去应用的。

Kernel 里有一个变量叫 module_list,每当 user 将一个 module 载到 kernel 里的时刻,这个 module 就会被记录在 module_list 里面。当 kernel 要应用到这个 module 供给的 function 时,它就会去 search 这个 list,找到 module,然后再应用其供给的 function 或 variable。每一个 module 都可以 export 一些 function 或变量来让别人应用。除此之外,module 也可以应用已经载到 kernel 里的 module 供给的 function。这种情形叫做 module stack。比方说,module A 用到 module B 的器械,那在加载 module A 之前必须要先加载 module B。否则 module A 会无法加载。除了 module 会 export 器械之外, kernel 本身也会 export 一些 function 或 variable。同样的,module 也可以应用 kernel 所 export 出来的器械。因为大年夜家日常平凡都是撰写 user space 的法度榜样,以是,当忽然去写 module 的时刻,会把日常平凡写法度榜样用的 function 拿到 module 里应用。像是 printf 之类的器械。我要奉告各位的是,module 所应用的 function 或 variable,要嘛便是自己写在 module 里,要嘛便是其余 module 供给的,再不便是 kernel 所供给的。你不能应用一样平常 libc 或 glibc所供给的 function。像 printf 之类的器械。这一点可能是各位要多小心的地方。(大概你可以先 link 好,再载到 kernel,我好象试过,然则忘了)

刚才我们说到 kernel 本身会 export 出一些 function 或 variable 来让 module 应用,然则,我们不是万能的,我们怎幺知道 kernel 有开放那里器械让我们应用呢 ? Linux 供给一个 command,叫 ksyms,你只要履行 ksyms -a 就可以知道 kernel 或今朝载到 kernel 里的 module 供给了那些 function 或 variable。底下是我的澳门新葡亰黑平台系统的情形:

c0216ba0 drive_info_R744aa133

c01e4a44 boot_cpu_data_R660bd466

c01e4ac0 EISA_bus_R7413793a

c01e4ac4 MCA_bus_Rf48a2c4c

c010cc34 __verify_write_R203afbeb

. . . . .

在 kernel 里,有一个 symbol table 是用来记录 export 出去的 function 或 variable。除此之外,也会记录着那个 module export 那些 function。上面几行中,表示 kernel 供给了 drive_info 这个 function/variable。以是,我们可以在 kernel 里直接应用它,等载到 kernel 里时,会自动做好 link 的动作。由此,我们可以知道,module 本身着实是还没做 link 的一些 object code。统统都要等到 module 被加载 kernel 之后,link 才会完成。各位应该可以看到 drive_info 后面还接着一些稀罕的字符串。_R744aa133,这个字符串是根据今朝 kernel 的版本再做些 encode 得出来的结果。为什幺额外必要这一个字符串呢 ?

Linux 不知道从那个版澳门新葡亰黑平台本以来,就多了一个 config 的选项,叫做 Set version number in symbols of module。这是为了避免对系统造成不稳定。我们知道 Linux 的 kernel 更新的很快。在 kernel 更新的历程,无意偶尔为了效率起见,会对某些旧有的 data structure 或 function 做些改变,而且一变可能有的 variable 被拿掉落,有的 function 的 prototype 跟原本的都不太一样。假如这种情形发生的时刻,那可能曩昔 2.0.33 版本的 module 拿到 2.2.1 版本的 kernel 应用,假设原本 module 应用了 2.0.33 kernel 供给的变量叫 A,然则到了 2.2.1 因为某些缘故原由必须把 A 都设成 NULL。那当此 module 用在 2.2.1 kernel 上时,假如它没去反省 A 的值就直接应用的话,就会造成系统的差错。大概不会全部系统都逝世掉落,然则这个 module 肯定是很难发挥它的功能。为了这个缘故原由,Linux 就在 compile module 时,把 kernel 版本的号码 encode 到各个 exported function 和 variable 里。

以是,刚才大概我们不应该讲 kernel 供给了 drive_info,而应该说 kernel 供给了 driver_澳门新葡亰黑平台info_R744aa133 来让我们应用。这样大概各位会对照明白。也便是说,kernel 觉得它供给的 driver_info_R744aa133 这个器械,而不是 driver_info。以是,我们可以发明有的人在加载 module 时,系统都不停奉告你某个 function 无法 resolved。这便是由于 kernel 里没有你要的 function,要不然便是你的 module 里应用的 function 跟 kernel encode 的结果不一样。以澳门新葡亰黑平台是无法 resolve。办理要领,要嘛便是将 kernel 里的 set version 选项关掉落,要嘛便是将 module compile 成 kernel 有法子吸收的型式。

您可能还会对下面的文章感兴趣: