mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-09 01:30:10 +08:00
commit
cb90168591
@ -1,191 +0,0 @@
|
||||
translate by amwps290
|
||||
How to load or unload a Linux kernel module
|
||||
======
|
||||
|
||||

|
||||
|
||||
This article is excerpted from chapter 15 of [Linux in Action][1], published by Manning.
|
||||
|
||||
Linux manages hardware peripherals using kernel modules. Here's how that works.
|
||||
|
||||
A running Linux kernel is one of those things you don't want to upset. After all, the kernel is the software that drives everything your computer does. Considering how many details have to be simultaneously managed on a live system, it's better to leave the kernel to do its job with as few distractions as possible. But if it's impossible to make even small changes to the compute environment without rebooting the whole system, then plugging in a new webcam or printer could cause a painful disruption to your workflow. Having to reboot each time you add a device to get the system to recognize it is hardly efficient.
|
||||
|
||||
To create an effective balance between the opposing virtues of stability and usability, Linux isolates the kernel, but lets you add specific functionality on the fly through loadable kernel modules (LKMs). As shown in the figure below, you can think of a module as a piece of software that tells the kernel where to find a device and what to do with it. In turn, the kernel makes the device available to users and processes and oversees its operation.
|
||||
|
||||
![Kernel modules][3]
|
||||
|
||||
Kernel modules act as translators between devices and the Linux kernel.
|
||||
|
||||
There's nothing stopping you from writing your own module to support a device exactly the way you'd like it, but why bother? The Linux module library is already so robust that there's usually no need to roll your own. And the vast majority of the time, Linux will automatically load a new device's module without you even knowing it.
|
||||
|
||||
Still, there are times when, for some reason, it doesn't happen by itself. (You don't want to leave that hiring manager impatiently waiting for your smiling face to join the video conference job interview for too long.) To help things along, you'll want to understand a bit more about kernel modules and, in particular, how to find the actual module that will run your peripheral and then how to manually activate it.
|
||||
|
||||
### Finding kernel modules
|
||||
|
||||
By accepted convention, modules are files with a .ko (kernel object) extension that live beneath the `/lib/modules/` directory. Before you navigate all the way down to those files, however, you'll probably have to make a choice. Because you're given the option at boot time of loading one from a list of releases, the specific software needed to support your choice (including the kernel modules) has to exist somewhere. Well, `/lib/modules`/ is one of those somewheres. And that's where you'll find directories filled with the modules for each available Linux kernel release; for example:
|
||||
```
|
||||
$ ls /lib/modules
|
||||
|
||||
4.4.0-101-generic
|
||||
|
||||
4.4.0-103-generic
|
||||
|
||||
4.4.0-104-generic
|
||||
|
||||
```
|
||||
|
||||
In my case, the active kernel is the version with the highest release number (4.4.0-104-generic), but there's no guarantee that that'll be the same for you (kernels are frequently updated). If you're going to be doing some work with modules that you'd like to use on a live system, you need to be sure you've got the right directory tree.
|
||||
|
||||
`uname -r` (the `-r` specifies the kernel release number from within the system information that would normally be displayed):
|
||||
```
|
||||
$ uname -r
|
||||
|
||||
4.4.0-104-generic
|
||||
|
||||
```
|
||||
|
||||
Good news: there's a reliable trick. Rather than identifying the directory by name and hoping you'll get the right one, use the system variable that always points to the name of the active kernel. You can invoke that variable using(thespecifies the kernel release number from within the system information that would normally be displayed):
|
||||
|
||||
With that information, you can incorporate `uname` into your filesystem references using a process known as command substitution. To navigate to the right directory, for instance, you'd add it to `/lib/modules`. To tell Linux that "uname" isn't a filesystem location, enclose the `uname` part in backticks, like this:
|
||||
```
|
||||
$ ls /lib/modules/`uname -r`
|
||||
|
||||
build modules.alias modules.dep modules.softdep
|
||||
|
||||
initrd modules.alias.bin modules.dep.bin modules.symbols
|
||||
|
||||
kernel modules.builtin modules.devname modules.symbols.bin
|
||||
|
||||
misc modules.builtin.bin modules.order vdso
|
||||
|
||||
```
|
||||
|
||||
You'll find most of the modules organized within their subdirectories beneath the `kernel/` directory. Take a few minutes to browse through those directories to get an idea of how things are arranged and what's available. The filenames usually give you a good idea of what you're looking at.
|
||||
```
|
||||
$ ls /lib/modules/`uname -r`/kernel
|
||||
|
||||
arch crypto drivers fs kernel lib mm
|
||||
|
||||
net sound ubuntu virt zfs
|
||||
|
||||
```
|
||||
|
||||
That's one way to locate kernel modules; actually, it's the quick and dirty way to go about it. But it's not the only way. If you want to get the complete set, you can list all currently loaded modules, along with some basic information, by using `lsmod`. The first column of this truncated output (there would be far too many to list here) is the module name, followed by the file size and number, and then the names of other modules on which each is dependent:
|
||||
```
|
||||
$ lsmod
|
||||
|
||||
[...]
|
||||
|
||||
vboxdrv 454656 3 vboxnetadp,vboxnetflt,vboxpci
|
||||
|
||||
rt2x00usb 24576 1 rt2800usb
|
||||
|
||||
rt2800lib 94208 1 rt2800usb
|
||||
|
||||
[...]
|
||||
|
||||
```
|
||||
|
||||
How many are far too many? Well, let's run `lsmod` once again, but this time piping the output to `wc -l` to get a count of the lines:
|
||||
```
|
||||
$ lsmod | wc -l
|
||||
|
||||
113
|
||||
|
||||
```
|
||||
|
||||
Those are the loaded modules. How many are available in total? Running `modprobe -c` and counting the lines will give us that number:
|
||||
```
|
||||
$ modprobe -c | wc -l
|
||||
|
||||
33350
|
||||
|
||||
```
|
||||
|
||||
There are 33,350 available modules!?! It looks like someone's been working hard over the years to provide us with the software to run our physical devices.
|
||||
|
||||
Note: On some systems, you might encounter customized modules that are referenced either with their unique entries in the `/etc/modules` file or as a configuration file saved to `/etc/modules-load.d/`. The odds are that such modules are the product of local development projects, perhaps involving cutting-edge experiments. Either way, it's good to have some idea of what it is you're looking at.
|
||||
|
||||
That's how you find modules. Your next job is to figure out how to manually load an inactive module if, for some reason, it didn't happen on its own.
|
||||
|
||||
### Manually loading kernel modules
|
||||
|
||||
Before you can load a kernel module, logic dictates that you'll have to confirm it exists. And before you can do that, you'll need to know what it's called. Getting that part sometimes requires equal parts magic and luck and some help from of the hard work of online documentation authors.
|
||||
|
||||
I'll illustrate the process by describing a problem I ran into some time back. One fine day, for a reason that still escapes me, the WiFi interface on a laptop stopped working. Just like that. Perhaps a software update knocked it out. Who knows? I ran `lshw -c network` and was treated to this very strange information:
|
||||
```
|
||||
network UNCLAIMED
|
||||
|
||||
AR9485 Wireless Network Adapter
|
||||
|
||||
```
|
||||
|
||||
Linux recognized the interface (the Atheros AR9485) but listed it as unclaimed. Well, as they say, "When the going gets tough, the tough search the internet." I ran a search for atheros ar9 linux module and, after sifting through pages and pages of five- and even 10-year-old results advising me to either write my own module or just give up, I finally discovered that (with Ubuntu 16.04, at least) a working module existed. Its name is ath9k.
|
||||
|
||||
Yes! The battle's as good as won! Adding a module to the kernel is a lot easier than it sounds. To double check that it's available, you can run `find` against the module's directory tree, specify `-type f` to tell Linux you're looking for a file, and then add the string `ath9k` along with a glob asterisk to include all filenames that start with your string:
|
||||
```
|
||||
$ find /lib/modules/$(uname -r) -type f -name ath9k*
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_common.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
|
||||
|
||||
```
|
||||
|
||||
Just one more step, load the module:
|
||||
```
|
||||
# modprobe ath9k
|
||||
|
||||
```
|
||||
|
||||
That's it. No reboots. No fuss.
|
||||
|
||||
Here's one more example to show you how to work with active modules that have become corrupted. There was a time when using my Logitech webcam with a particular piece of software would make the camera inaccessible to any other programs until the next system boot. Sometimes I needed to open the camera in a different application but didn't have the time to shut down and start up again. (I run a lot of applications, and getting them all in place after booting takes some time.)
|
||||
|
||||
Because this module is presumably active, using `lsmod` to search for the word video should give me a hint about the name of the relevant module. In fact, it's better than a hint: The only module described with the word video is uvcvideo (as you can see in the following):
|
||||
```
|
||||
$ lsmod | grep video
|
||||
|
||||
uvcvideo 90112 0
|
||||
|
||||
videobuf2_vmalloc 16384 1 uvcvideo
|
||||
|
||||
videobuf2_v4l2 28672 1 uvcvideo
|
||||
|
||||
videobuf2_core 36864 2 uvcvideo,videobuf2_v4l2
|
||||
|
||||
videodev 176128 4 uvcvideo,v4l2_common,videobuf2_core,videobuf2_v4l2
|
||||
|
||||
media 24576 2 uvcvideo,videodev
|
||||
|
||||
```
|
||||
|
||||
There was probably something I could have controlled for that was causing the crash, and I guess I could have dug a bit deeper to see if I could fix things the right way. But you know how it is; sometimes you don't care about the theory and just want your device working. So I used `rmmod` to kill the uvcvideo module and `modprobe` to start it up again all nice and fresh:
|
||||
```
|
||||
# rmmod uvcvideo
|
||||
|
||||
# modprobe uvcvideo
|
||||
|
||||
```
|
||||
|
||||
Again: no reboots. No stubborn blood stains.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/5/how-load-or-unload-linux-kernel-module
|
||||
|
||||
作者:[David Clinto][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dbclinton
|
||||
[1]:https://www.manning.com/books/linux-in-action?a_aid=bootstrap-it&a_bid=4ca15fc9&chan=opensource
|
||||
[2]:/file/397906
|
||||
[3]:https://opensource.com/sites/default/files/uploads/kernels.png (Kernel modules)
|
@ -0,0 +1,201 @@
|
||||
# 装载/卸载 Linux 内核模块
|
||||
|
||||

|
||||
|
||||
本文来自 Manning 出版的 [Linux in Action][1] 的第 15 章。
|
||||
|
||||
Linux 使用内核模块管理硬件外设。 我们来看看它是如何工作的。
|
||||
|
||||
运行中的 Linux 内核是您不希望破坏的东西之一。毕竟,内核是驱动计算机所做的一切的软件。考虑到在一个运行的系统上必须同时管理诸多细节,最好能让内核尽可能的减少分心,专心的完成它的工作。但是,如果在不重新启动整个系统的情况下,对计算环境进行任何微小的更改都是不可能的,那么插入一个新的网络摄像头或打印机可能会对您的工作流程造成严重的破坏。每次添加设备时都必须重新启动,以使系统识别它,这效率很低。
|
||||
|
||||
为了在稳定性和可用性之间建立一个有效的平衡,Linux 将内核隔离,但是允许您通过可加载内核模块 (LKMs) 实时添加特定的功能。如下图所示,您可以将模块视为软件的一部分,它告诉内核在哪里找到一个设备以及如何使用它。反过来,内核使设备对用户和进程可用,并监视其操作。
|
||||
|
||||
![Kernel modules][3]
|
||||
|
||||
内核模块充当设备和 Linux 内核之间的转换器。
|
||||
|
||||
没有什么能够阻止你编写你自己的模块来完全按照你喜欢的方式来支持一个设备,但是为什么呢? Linux 模块库已经非常强大,通常不需要自己去实现一个模块。 而绝大多数时候,Linux 会自动加载新设备的模块,而您甚至不知道它。
|
||||
|
||||
不过,有时候,出于某种原因,它本身并不会运行。 (你不想让那个招聘经理不耐烦地等待你的笑脸加入视频会议面试时间太长。)为了帮助你解决问题,你需要更多地了解内核模块,特别是 ,如何找到运行你的外设的实际模块,然后如何手动激活它。
|
||||
|
||||
### 查找内核模块
|
||||
|
||||
按照公认的约定,模块是位于 `/lib/modules/` 目录下的具有 .ko(内核对象)扩展名的文件。 然而,在你一直导航到这些文件之前,你可能不得不做出选择。 因为在引导时你需要从加载发行版列表中选择一个选项,所以支持您选择的特定软件(包括内核模块)必须存在某处。 那么,`/lib/modules/` 就是其中之一。 你会发现目录里充满了每个可用的 Linux 内核版本的模块; 例如:
|
||||
|
||||
```
|
||||
$ ls /lib/modules
|
||||
|
||||
4.4.0-101-generic
|
||||
|
||||
4.4.0-103-generic
|
||||
|
||||
4.4.0-104-generic
|
||||
|
||||
```
|
||||
|
||||
在我的电脑上,运行的内核是版本号最高的版本(4.4.0-104-generic),但不能保证这对你来说是一样的(内核经常更新)。 如果您将要在一个运行的系统上对你想要使用的模块做一些工作的话,则需要确保您拥有正确的目录树。
|
||||
|
||||
`uname -r`( `-r` 指定了系统信息中的内核版本号):
|
||||
|
||||
```
|
||||
$ uname -r
|
||||
|
||||
4.4.0-104-generic
|
||||
|
||||
```
|
||||
|
||||
好消息:有一个可靠的窍门。 不通过名称来识别目录,并希望能够找到正确的目录,而是使用始终指向使用的内核名称的系统变量。 您可以使用(从系统信息中指定通常显示的内核版本号)来调用该变量:
|
||||
|
||||
通过这些信息,您可以使用称为命令替换的过程将 `uname` 并入您的文件系统引用中。 例如,要导航到正确的目录,您需要将其添加到 `/lib/modules` 。 要告诉 Linux “uname” 不是文件系统的位置,请将 `uname` 部分用反引号括起来,如下所示:
|
||||
|
||||
```
|
||||
$ ls /lib/modules/`uname -r`
|
||||
|
||||
build modules.alias modules.dep modules.softdep
|
||||
|
||||
initrd modules.alias.bin modules.dep.bin modules.symbols
|
||||
|
||||
kernel modules.builtin modules.devname modules.symbols.bin
|
||||
|
||||
misc modules.builtin.bin modules.order vdso
|
||||
|
||||
```
|
||||
|
||||
你可以在 `kernel/` 目录下的子目录中找到大部分模块。 花几分钟时间浏览这些目录,了解事物的排列方式和可用内容。 这些文件名通常会让你知道你在看什么。
|
||||
|
||||
```
|
||||
$ ls /lib/modules/`uname -r`/kernel
|
||||
|
||||
arch crypto drivers fs kernel lib mm
|
||||
|
||||
net sound ubuntu virt zfs
|
||||
|
||||
```
|
||||
|
||||
这是查找内核模块的一种方法; 实际上,这是一种快速的方式。 但这不是唯一的方法。 如果你想获得完整的集合,你可以使用 `lsmod` 列出所有当前加载的模块以及一些基本信息。 这个截断输出的第一列(在这里列出的太多了)是模块名称,后面是文件大小和数量,然后是每个模块的名称:
|
||||
|
||||
```
|
||||
$ lsmod
|
||||
|
||||
[...]
|
||||
|
||||
vboxdrv 454656 3 vboxnetadp,vboxnetflt,vboxpci
|
||||
|
||||
rt2x00usb 24576 1 rt2800usb
|
||||
|
||||
rt2800lib 94208 1 rt2800usb
|
||||
|
||||
[...]
|
||||
|
||||
```
|
||||
|
||||
到底有多少?好吧,我们再运行一次 `lsmod ` ,但是这一次将输出管道输送到 `wc -l` 看一下一共多少行:
|
||||
|
||||
```
|
||||
$ lsmod | wc -l
|
||||
|
||||
113
|
||||
|
||||
```
|
||||
|
||||
那些是加载的模块。 总共有多少个? 运行 `modprobe -c` 并计算这些行将给我们这个数字:
|
||||
|
||||
```
|
||||
$ modprobe -c | wc -l
|
||||
|
||||
33350
|
||||
|
||||
```
|
||||
|
||||
有33,350个可用模块!?! 看起来好像有人多年来一直在努力为我们提供软件来驱动我们的物理设备。
|
||||
|
||||
注意:在某些系统中,您可能会遇到自定义的模块,这些模块在 `/etc/modules` 文件中使用其唯一条目进行引用,也可以作为保存到 `/etc/modules-load.d/` 的配置文件。这些模块很可能是本地开发项目的产物,可能涉及前沿实验。不管怎样,知道你在看什么是好事。
|
||||
|
||||
这就是你如何找到模块。 如果出于某种原因,它不会自行运行,您的下一个工作就是弄清楚如何手动加载非活动模块。
|
||||
|
||||
### 手动加载内核模块
|
||||
|
||||
在加载内核模块之前,逻辑上您必须确认它的存在。在这之前,你需要知道它叫什么。要做到这一点,有时需要同样的魔法和运气以及在线文档作者的辛勤工作的帮助。
|
||||
|
||||
我将通过描述一段时间前遇到的问题来说明这个过程。在一个晴朗的日子里,出于某种原因,笔记本电脑上的 WiFi 接口停止工作了。就这样。也许是软件升级把它搞砸了。谁知道呢?我运行了 `lshw -c network` ,得到了这个非常奇怪的信息:
|
||||
|
||||
```
|
||||
network UNCLAIMED
|
||||
|
||||
AR9485 Wireless Network Adapter
|
||||
|
||||
```
|
||||
|
||||
Linux 识别到了接口(Atheros AR9485),但将其列为未声明。 那么,正如他们所说的那样,“当情况变得严峻时,就会在互联网上进行艰难的搜索。” 我搜索了一下 atheros ar9 linux 模块,在浏览了 5 页甚至是 10 年前的页面后,它们建议自己写模块或者放弃,然后我终于发现(使用 Ubuntu 16.04, 至少)存在一个工作模块。 它的名字是 ath9k 。
|
||||
|
||||
是的! 这场战斗胜券在握! 向内核添加模块比听起来容易得多。 要仔细检查它是否可用,可以针对模块的目录树运行 `find`,指定 `-type f` 来告诉 Linux 您正在查找文件,然后将字符串 `ath9k` 和星号一起添加以包含所有以你的字符串打头的文件:
|
||||
|
||||
```
|
||||
$ find /lib/modules/$(uname -r) -type f -name ath9k*
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_common.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
|
||||
|
||||
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
|
||||
|
||||
```
|
||||
|
||||
再一步,加载模块:
|
||||
|
||||
```
|
||||
# modprobe ath9k
|
||||
|
||||
```
|
||||
|
||||
就是这样。没有重新启动。没有大惊小怪。
|
||||
|
||||
这里还有一个示例,向您展示如何使用已经崩溃的运行模块。曾经有一段时间,我使用罗技网络摄像头和一个特定的软件会使摄像头在下次系统启动前无法被任何其他程序访问。有时我需要在不同的应用程序中打开相机,但没有时间关机重新启动。(我运行了很多应用程序,在引导之后将它们全部准备好需要一些时间。)
|
||||
|
||||
由于这个模块可能是运行的,所以使用 `lsmod` 来搜索视频这个词应该给我一个关于相关模块名称的提示。 实际上,它比提示更好:用 video 这个词描述的唯一模块是 uvcvideo(如下所示):
|
||||
|
||||
```
|
||||
$ lsmod | grep video
|
||||
|
||||
uvcvideo 90112 0
|
||||
|
||||
videobuf2_vmalloc 16384 1 uvcvideo
|
||||
|
||||
videobuf2_v4l2 28672 1 uvcvideo
|
||||
|
||||
videobuf2_core 36864 2 uvcvideo,videobuf2_v4l2
|
||||
|
||||
videodev 176128 4 uvcvideo,v4l2_common,videobuf2_core,videobuf2_v4l2
|
||||
|
||||
media 24576 2 uvcvideo,videodev
|
||||
|
||||
```
|
||||
|
||||
有可能是我自己的操作导致了崩溃,我想我可以挖掘更深一点,看看我能否以正确的方式解决问题。 但你知道它是如何的; 有时你不关心理论,只想让设备工作。 所以我用 `rmmod` 杀死了 `uvcvideo` 模块,然后用 `modprobe` 重新启动它,一切都好:
|
||||
|
||||
```
|
||||
# rmmod uvcvideo
|
||||
|
||||
# modprobe uvcvideo
|
||||
|
||||
```
|
||||
|
||||
再一次:不重新启动。没有其他的后续影响。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/18/5/how-load-or-unload-linux-kernel-module
|
||||
|
||||
作者:[David Clinto][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://opensource.com/users/dbclinton
|
||||
[1]:https://www.manning.com/books/linux-in-action?a_aid=bootstrap-it&a_bid=4ca15fc9&chan=opensource
|
||||
[2]:/file/397906
|
||||
[3]:https://opensource.com/sites/default/files/uploads/kernels.png "Kernel modules"
|
Loading…
Reference in New Issue
Block a user