显示标签为“kernel”的博文。显示所有博文
显示标签为“kernel”的博文。显示所有博文

2019-07-26

Console-terminal-tty-shell-kernel


Console-terminal-tty-shell-kernel
1. 先看一图一表
    1.1 简表
    1.2 shell与内核的示意图
    1.3 Console-terminal-tty-shell-kernel示意图
2. console控制台有2类
3. console及terminal操作
    3.1 切换控制台
    3.2 查看有那些用户登录,分别占用了那些tty*?
    3.3 发送文字到其他控制台终端
    3.4 查看当前控制台终端
    3.5 关闭一个虚拟终端
4. shell是运行在tty之上的命令行解释器。
    4.1 查看可用shell
    4.2 查看系统默认的shell
    4.3 查找用户的默认shell
    4.4 查看当前使用的shell
5. 小节
6. Q&A
    6.1 还没看懂? 返回第一页重新看一边。
    6.2 还没看懂? 写的太简单了,请看如下更详细的解释:
    6.3 上文如有错误,还请不吝赐教,在评论区帮忙指正。

Linux世界,如何理解这几个关键字: Console, terminal, tty, shell, kernel???
console和terminal在功能上没什么区别。
tty和terminal是同义词。
shell是内核kernel的外壳。
Huh?

1. 先看图表

1.1 简表

关键字
中文
文件
描述
简单说是
console 控制台 /dev/console 物理控制台,(显示器,键盘) 硬件设备

ctrl + alt [F2,F7] 切换 支持独立登录会话的虚拟控制台 虚拟终端
terminal 终端 /dev/pts/*
/dev/tty*
文本输入/输出会话 会话session
tty TTY 特殊类型的设备文件, 伪设备
shell 外壳 /bin/bash 命令行解释器, 程序
Kernel 内核 /boot/vmlinuz* Linux操作系统内核 内核

1.2 shell与内核的示意图














User







The Shell







The Kernel







System
Hardware








































古老的单用户单任务系统,大概就这个结构。

1.3 Console-terminal-tty-shell-kernel示意图

现代的系统都是多用户,多任务,图形界面的复杂结构,就需要多个控制台,多个终端同时登录。

如上示意图,假设了4个用户同时登录,2个本机用户,2个远程用户
地点 界面 用户 console terminal > tty shell
本机 GUI User01 本机GUI tty7 (/dev/pts/0,1,2…) /bin/sh;/bin/bash…
本机 ctl User02 本机ctl tty2 (ctrl + alt [F2|F7]切换) /bin/sh
远程 ctl User03 ssh tty3 /usr//bin/fish
远程 ctl User04 ssh tty4 /usr//bin/zsh

2. console控制台有2类

console,控制台(/dev/console),有2类,
  • 物理控制台: (比如键盘,显示器);也叫物理终端
  • 虚拟控制台: 每个控制台都支持独立的登录会话

3. console及terminal操作

3.1 切换控制台

Ctrl + Alt + [F2...F7]

查看当前用户:
$ whoami
toma

3.2 查看有那些用户登录,分别占用了那些tty*?

$  who
toma     tty7         2019-07-20 20:20 (:0)
root     tty2         2019-07-25 23:22
$ w
 23:22:26 up 5 days,  3:02,  2 users,  load average: 0.48, 0.84, 1.14
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
toma     tty7      Sat20    5days  5:49m  0.01s /bin/sh /etc/xdg/xfce4/xinitrc
root     tty2      23:22   18.00s  1.46s  1.31s cmatrix

注: tty7是当前用户登录的xfce4图像界面,其他是通过(Ctrl + Alt [F2])登录的命令行界面。

3.3 发送文字到其他控制台终端

$ echo "hello" > /dev/tty2

3.4 查看当前控制台终端

Ctrl + Alt [F2] 切换到tty2,查看当前控制台终端
$ tty
/dev/tty2

Ctrl + Alt [F7] 切换到tty7,查看当前控制台终端
$ tty
/dev/pts/0

注: 这个tty不是直接在tty7的sh上运行的,是在tty7之上的图形界面之上,通过xfce4-terminal软件建立的虚拟终端会话。
多开一个xfce4-terminal软件界面,就多出一个这样的会话。
$ tty
/dev/pts/1

3.5 关闭一个虚拟终端

$ ls /dev/pts/
0  1  2  ptmx
exit退出或关掉任意一个xfce4-terminal界面,这里也会少一个文件。
至于tty2,需要切换到tty2,再exit退出。

4. shell是运行在tty之上的命令行解释器。

4.1 查看可用shell

$ chsh -l
/bin/sh
/bin/bash
/usr/bin/git-shell
/usr/bin/fish

$ cat /etc/shells
# Pathnames of valid login shells.
# See shells(5) for details.
/bin/sh
/bin/bash
/usr/bin/git-shell
/usr/bin/fish

4.2 查看系统默认的shell

$ echo $SHELL
/usr/bin/fish

通过环境变量
$ env | grep SHELL
SHELL=/usr/bin/fish

4.3 查找用户的默认shell

$ cat /etc/passwd | grep toma
toma:x:1001:985::/home/toma:/usr/bin/fish

4.4 查看当前使用的shell

$ ps
  PID TTY          TIME CMD
17333 pts/0    00:00:00 fish
28228 pts/0    00:00:00 ps

$ bash
$ ps
  PID TTY          TIME CMD
17333 pts/0    00:00:00 fish
28235 pts/0    00:00:00 bash
28241 pts/0    00:00:00 ps

// bash 可用如下方式,其他sh不一定有效。
$ ps -p $$
  PID TTY          TIME CMD
28235 pts/0    00:00:00 bash

$ echo $0
bash

5. 小节

console主要指物理终端,硬件设备键盘等;terminal提供文本输入的会话,/dev/下的体现都是字符类设备文件。
GUI下创建虚拟终端terminal会话的程序比如:/usr/bin/xfce4-terminal。
terminal = tty 是文本输入/输出的会话。
terminal 是统称概念,每个terminal都有具体的tty编号对应,且在/dev/下以字符文件形式存在。
shell是运行在tty之上的程序,打开终端自动运行的程序,内核的外壳,用户的命令提示符。比如bash,zsh,fish等。
shell通过控制tty与用户交互,并向用户提供启动其他程序的方式。

6. Q&A

6.1 还没看懂? 返回第一页重新看一边。

6.2 还没看懂? 写的太简单了,请看如下更详细的解释:

What is the exact difference between a 'terminal', a 'shell', a 'tty' and a 'console'?
https://unix.stackexchange.com/questions/4126/what-is-the-exact-difference-between-a-terminal-a-shell-a-tty-and-a-con

https://www.zhihu.com/question/21711307

The TTY demystified 解密TTY
http://www.linusakesson.net/programming/tty/
中文翻译:https://www.cnblogs.com/liqiuhao/p/9031803.html

还有疑问?console, terminal, tty的概念模糊不清,其实问题不大,这有历史的原因。
普通用户只要知道命令在终端里输入,其实是终端的shell里输入。打开终端就会运行默认的shell。会用基本的shell命令即可。

6.3 上文如有错误,还请不吝赐教,在评论区帮忙指正。


2019-07-03

Compile-kernel-module

1. 内核模块编程
1.1 简介
1.2 加载内核模块
1.3 最简单的模块
1.4 模块必要信息
1.4.1 内核模块必须至少包含的头文件:
1.4.2 内核模块必须至少有两个功能:
1.4.3 printk()日志记录
1.4.4 优先级
1.4.5 许可和模块文档
1.5 编译内核模块
1.6 实战
1.6.1 源代码文件: hello.c
1.6.2 Makefile文件: Makefile
1.6.3 使用make编译
1.6.4 使用modinfo查看新的模块文件
1,6.5 使用insmod加载内核模块
1.6.6 使用lsmod查看已加载的模块
1.6.7 使用rmmod卸载模块
1.6.8 使用dmesg查看日志
1.6.9 练习
1.6.10 其他信息
1.7 更多基础示例链接
1.7.1 将命令行参数传递给模块
1.7.2 跨越多个文件的模块
1.7.3 构建预编译内核的模块
1.7.4 与应用程序交互
2 make工具
2.1 DESCRIPTION
2.2 退出状态
2.3 选项
3. 其他内核编译方法及相关连接
3.1 编译Arch的内核模块
3.2 Arch构建系统
3.3 内核/传统编译
3.4 修补包
3.5 模块与程序

1. 内核模块编程

http://www.tldp.org/LDP/lkmpg/2.6/html/
Linux内核模块编程指南 2007-05-18见2.6.4

1.1 简介

什么是内核模块?模块是可以根据需要加载和卸载到内核中的代码片段。它们扩展了内核的功能,而无需重启系统。
例如,一种类型的模块是设备驱动程序,它允许内核访问连接到系统的硬件。还有很多的文件系统等。

1.2 加载内核模块

您可以通过运行lsmod来查看已经加载到内核中的模块,lsmod通过读取文件/proc/modules来获取其信息。
执行modprobe来加载模块.modprobe以两种形式之一传递一个字符串:
  > 模块名称,如softdog或ppp。
  > 一个更通用的标识符,如char-major-10-30。
如果modprobe被赋予通用标识符,它首先在文件/etc/modprobe.conf中查找该字符串。如果找到如下的别名行:alias char-major-10-30 softdog
它知道通用标识符引用模块softdog.ko。
然后,modprobe查看文件/lib/modules/version/modules.dep,查看是否必须加载其他模块才能加载所请求的模块。该文件由depmod -a创建,包含模块依赖项。
      例如,msdos.ko要求fat.ko模块已经加载到内核中。
最后,modprobe使用insmod首先将任何必备模块加载到内核中,然后加载所请求的模块。
modprobe将insmod指向/lib/modules/'uname -r'/, 模块的标准目录。

insmod对于模块的位置是相当愚蠢的,而modprobe知道模块的默认位置,知道如何找出依赖关系并以正确的顺序加载模块。
因此,例如,如果要加载msdos模块,则必须运行:
$ insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
$ insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko

要么:
$ modprobe msdos
所以,insmod要求你传递完整的路径名并以正确的顺序插入模块,而modprobe只取名字,没有任何扩展名,并通过解析/lib找出它需要知道的所有内容/modules/version/modules.dep。

1.3 最简单的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x121.html
Example 2-1. hello-1.c
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}

1.4 模块必要信息

1.4.1 内核模块必须至少包含的头文件:

#include <linux/module.h> /* module_init() module_exit() 函数来注册模块入口和退出处理。
#include <linux/kernel.h> /* Needed for KERN_INFO ,仅用于printk()日志级别的KERN_ALERT的宏扩展 */
#include <linux/init.h> /* Needed for the macros */

1.4.2 内核模块必须至少有两个功能:

  • 一个“开始”(初始化)功能调用 的init_module()当模块insmoded到内核被称为,
  • 以及“结束”(清理)函数调用在cleanup_module()这是刚刚称为在它被破坏之前。
从Linux 2.4开始,您可以重命名模块的init和cleanup功能; 它们不再需要分别被称为 init_module()和cleanup_module()。
这是通过 module_init()和module_exit()宏完成的。这些宏在linux / init.h中定义。
唯一需要注意的是,必须在调用宏之前定义init和cleanup函数,否则会出现编译错误。

1.4.3 printk()日志记录

由于代码运行在内核空间里面,不能直接使用用户空间的 print 函数,而要使用内核中的 printk 函数.
作为日志记录机制,用于记录信息或发出警告。
每个printk() 语句都带有一个优先级,即您看到的<1>和KERN_ALERT。
有8个优先级,内核有宏,所以你不必使用神秘的数字,你可以在linux/kernel.h中查看它们(及其含义)。
如果未指定优先级,则将使用默认优先级DEFAULT_MESSAGE_LOGLEVEL。

花点时间阅读优先级宏。头文件还描述了每个优先级的含义。
在实践中,不要使用数字,如<4>。始终使用宏,如 KERN_WARNING。

如果优先级低于int console_loglevel,则会在当前终端上打印消息。
如果syslogd和klogd都在运行,那么该消息也将附加到/var/log/messages,无论它是否打印到控制台。
我们使用高优先级(如KERN_ALERT)来确保将printk()消息打印到控制台而不是仅记录到日志文件中。
编写实际模块时,您需要使用对当前情况有意义的优先级。

1.4.4 优先级

https://szosoft.blogspot.com/2019/06/linux-journal.html#1021
cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/kernel.h
cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/printk.h
内核模块printk no (Key)journal
KERN_EMERG 0 Emergency 紧急
KERN_ALERT 1 Alert 警报
KERN_CRIT 2 Critical 危急
KERN_ERR 3 Error 错误
KERN_WARNING 4 Warning 警告
KERN_NOTICE 5 Notice 注意
KERN_INFO 6 Informational 信息
KERN_DEBUG 7 Debug 调试

1.4.5 许可和模块文档

MODULE_LICENSE("GPL");  /* Get rid of taint message by declaring code as GPL.  */
MODULE_AUTHOR("Tom"); /* Who wrote this module? */
MODULE_DESCRIPTION("Test"); /* What does this module do */
MODULE_VERSION("0.0.1");
MODULE_SUPPORTED_DEVICE("testdevice");   /* 声明模块支持哪些类型的设备。 */
在内核2.4及更高版本中,设计了一种机制来识别在GPL(和朋友)下许可的代码,以便可以警告人们代码是非开源的。
这是通过MODULE_LICENSE()宏实现的。通过将许可证设置为GPL,可以防止打印警告。
此许可证机制在linux/module.h中定义并记录:
$ cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/module.h |grep MODULE_

/*
 * 目前接受以下许可证标识为免费软件模块
 * "GPL" [GNU Public License v2 or later]
 * "GPL v2" [GNU Public License v2]
 * "GPL and additional rights" [GNU Public License v2 rights and more]
 * "Dual BSD/GPL" [GNU Public License v2 or BSD license choice]
 * "Dual MIT/GPL" [GNU Public License v2 or MIT license choice]
 * "Dual MPL/GPL" [GNU Public License v2 or Mozilla license choice]
 *
 * 以下其他标识可供选择
 * "Proprietary" [Non free products]
 */

1.5 编译内核模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x181.html
内核模块的编译需要与常规用户空间应用程序略有不同。
以前的内核版本要求我们关注这些设置,这些设置通常存储在Makefile中。虽然按层次结构组织,但许多冗余设置在次级Makefile中累积并使它们变大并且难以维护。
幸运的是,有一种新方法可以做这些事情,称为kbuild,外部可加载模块的构建过程现在完全集成到标准内核构建机制中。
要了解有关如何编译不属于官方内核的模块的更多信息(例如本指南中的所有示例),请参阅文件 linux/Documentation/kbuild/modules.txt.

编译时通过一个 Makefile 文件进行,把这个 Makefile 文件置于 hello.c 同一目录下.
Makefile对格式有要求。每一行文本除非顶头开始,如果需要格式编排,不能使用空格键来控制文本行缩进,必须使用Tab键

1.6 实战

1.6.1 源代码文件: hello.c

/*  hello.c - Demonstrates module documentation. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#define DRIVER_AUTHOR "Peter Jay Salzman <p@dirac.org>"
#define DRIVER_DESC   "A sample driver"

static int __init init_hello(void)
{
printk(KERN_INFO "HelloWorld\n");
return 0;
}

static void __exit cleanup_hello(void)
{
printk(KERN_INFO "GoodbyeWorld\n");
}

module_init(init_hello);
module_exit(cleanup_hello);

MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */
MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */
MODULE_SUPPORTED_DEVICE("testdevice");

1.6.2 Makefile文件: Makefile

obj-m += hello.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

从技术角度来看,第一行确实是必要的,为了方便起见,添加了“全部”和“清洁”目标。
现在您可以通过发出命令make来编译模块。您应该获得类似于以下内容的输出:

1.6.3 使用make编译

$ make
make -C /lib/modules/5.1.15-arch1-1-ARCH/build M=/home/toma/ko modules
make[1]: Entering directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'
  CC [M]  /home/toma/ko/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/toma/ko/hello.mod.o
  LD [M]  /home/toma/ko/hello.ko
make[1]: Leaving directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'

请注意,内核2.6引入了一种新的文件命名约定:内核模块现在具有.ko 扩展名(代替旧的.o扩展名),可以轻松地将它们与传统的目标文件区分开来。
原因是它们包含一个额外的.modinfo部分,其中保留了有关该模块的其他信息。我们很快就会看到这些信息有什么用处。
有关内核模块的Makefile的更多详细信息,请参见 linux/Documentation/kbuild/makefiles.txt .

$ ls -l   //编译后查看文件列表
name size
Makefile 154   //make文件
hello.c 786      //源文件
hello.ko 4528   //内核文件
hello.mod.c 646
hello.mod.o 2712
hello.o 2664   //目标文件
modules.order 30
Module.symvers 0

1.6.4 使用modinfo查看新的模块文件

$ modinfo hello.ko
filename:       /home/toma/ko/hello.ko
version:        0.0.1
description:    Test
author:         Tom
license:        GPL
srcversion:     BC3C3A49026E0297D738AE7
depends:     
retpoline:      Y
name:           hello
vermagic:       5.1.15-arch1-1-ARCH SMP preempt mod_unload

1,6.5 使用insmod加载内核模块

$ sudo insmod ./hello.ko

1.6.6 使用lsmod查看已加载的模块

$ lsmod |grep hello
Module                  Size  Used by
hello                  16384  0

1.6.7 使用rmmod卸载模块

$ sudo rmmod hello
$ lsmod |grep hello

1.6.8 使用dmesg查看日志

$ dmesg |tail
...
[562050.818179] HelloWorld
[562458.113633] GoodbyeWorld

1.6.9 练习

练习1
请参阅init_module()中 return语句上方的注释 ?将返回值更改为负值,重新编译并再次加载模块。怎么了?
$ sudo insmod ./hello-2.ko
insmod: ERROR: could not insert module ./hello-2.ko: Operation not permitted
$ dmesg |tail
...
[546135.110381] HelloWorld2.

练习2
将代码中许可的部分删除,再编译看看。
$ make
make -C /lib/modules/5.1.15-arch1-1-ARCH/build M=/home/toma/ko modules
make[1]: Entering directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'
  CC [M]  /home/toma/ko/hello-1.o
  Building modules, stage 2.
  MODPOST 1 modules
style="color: red; font-size: xx-small;">WARNING: modpost: missing MODULE_LICENSE() in /home/toma/ko/hello-1.o
see include/linux/module.h for more information
  CC      /home/toma/ko/hello-1.mod.o
  LD [M]  /home/toma/ko/hello-1.ko
make[1]: Leaving directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'

1.6.10 其他信息

现在看一下linux/drivers/char/Makefile的真实示例。
正如你所看到的,有些东西被硬件连接到内核(obj-y)但是那些obj-m去了哪里?
那些熟悉shell脚本的人很容易发现它们。
对于那些没有的,你看到的obj - $(CONFIG_FOO)条目会扩展为obj-y或obj-m,具体取决于CONFIG_FOO变量是否已设置为y或m。
虽然我们在这里,但那些正是你在linux/.config文件中设置的那种变量,最后一次你说make menuconfig 或类似的东西。

1.7 更多基础示例链接

1.7.1 将命令行参数传递给模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x323.html

1.7.2 跨越多个文件的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x351.html

1.7.3 构建预编译内核的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x380.html

1.7.4 与应用程序交互

https://www.oschina.net/translate/writing-a-simple-linux-kernel-module

2 make工具

2.1 DESCRIPTION

make实用程序将自动确定需要重新编译大型程序的哪些部分,并发出命令以重新编译它们。
我们的示例显示了C程序,因为它们非常常见,但您可以使用make与任何编译语言,其编译器可以使用shell命令运行。
实际上,make并不仅限于程序。
您可以使用它来描述任何一些任务,其中某些文件必须在其他文件更改时自动从其他文件更新。

要准备使用make,您必须编写一个名为makefile的文件,该文件描述程序中文件之间的关系,以及用于更新每个文件的命令的状态。
在程序中,通常从目标文件更新可执行文件,而目标文件又通过编译源文件来完成。

一旦存在合适的makefile,每次更改一些源文件时,这个简单的shell命令:
make
足以执行所有必要的重新编译。
make程序使用makefile描述和文件的最后修改时间来决定需要更新哪些文件。
对于每个文件,它会发出makefile中记录的命令。

make执行makefile中的命令以更新一个或多个目标名称,其中name通常是程序。
如果不存在-f选项,make将按顺序查找 makefiles GNUmakefile, makefile, and Makefile, in that order.

(我们建议使用Makefile,因为它突出显示在目录列表的开头附近,紧邻其他重要文件,如README。)
检查的第一个名称,建议不要将GNUmakefile用于大多数makefile。
如果您具有特定于GNU make的makefile,则应使用此名称,并且其他版本的make不会理解该名称。
如果makefile为' - ',则读取标准输入。

2.2 退出状态

如果所有的makefile都被成功解析并且没有构建的目标失败,则GNU make退出状态为零。
如果使用-q标志并且make确定需要重建目标,则将返回状态1。
如果遇到任何错误,将返回状态2。

2.3 选项

-b, -m Ignored for compatibility. 忽略兼容性.
-B, --always-make Unconditionally make all targets. 无条件地制定所有目标.
-C DIRECTORY, --directory=DIRECTORY Change to DIRECTORY before doing anything. 在做任何事之前改为DIRECTORY.
-d Print lots of debugging information. 打印大量调试信息.
--debug[=FLAGS] Print various types of debugging information.  FLAGS可以用于所有调试输出(与使用-d相同),
b用于基本调试,v用于更详细的基本调试,i用于显示隐式规则,
j用于调用命令的详细信息,m用于在重新生成makefile时进行调试.
 使用n禁用所有先前的调试标志.
-e, --environment-overrides Environment variables override makefiles. 环境变量覆盖makefile.
--eval=STRING Evaluate STRING as a makefile statement. 将STRING评估为makefile语句.
-f FILE, --file=FILE, --makefile=FILE Read FILE as a makefile. 将FILE作为makefile读取.
-h, --help Print this message and exit. 打印此消息并退出.
-i, --ignore-errors Ignore errors from recipes.  忽略为重制文件而执行的命令中的所有错误.
-I DIRECTORY, --include-dir=DIRECTORY Search DIRECTORY for included makefiles. 搜索DIRECTORY以获取包含的makefile.
-j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg. 一次允许N个工作;没有arg的无限工作.
-k, --keep-going Keep going when some targets can't be made. 当一些目标无法制作时继续前进.
-l [N], --load-average[=N],--max-load[=N] Don't start multiple jobs unless load is below N. 除非负载低于N,否则不要启动多个作业.
-L, --check-symlink-times Use the latest mtime between symlinks and target. 使用符号链接和目标之间的最新mtime.
-n, --just-print, --dry-run, --recon Don't actually run any recipe; just print them. 实际上不要运行任何配方;只需打印它们.
-o FILE, --old-file=FILE, --assume-old=FILE Consider FILE to be very old and don't remake it. 即使FILE很老,也不要重新生成它.
-O[TYPE], --output-sync[=TYPE] Synchronize output of parallel jobs by TYPE. 按TYPE同步并行作业的输出.
 当与-j并行运行多个作业时,请确保将每个作业的输出收集在一起,而不是穿插其他作业的输出.
 如果未指定type或是target,则将每个目标的整个配方的输出组合在一起.
 如果type为line,则配方中每个命令行的输出将组合在一起.
 如果type是recurse,则整个递归make的输出被组合在一起.
如果type为none,则禁用输出同步.
-p, --print-data-base Print make's internal database.  打印通过读取makefile产生的数据库(规则和变量值);
然后像往常一样或以其他方式指定执行.
要打印数据库而不尝试重新创建任何文件,请使用: make -p -f/dev/null.
-q, --question Run no recipe; exit status says if up to date. ``问题模式''.不要运行任何命令,也不要打印任何东西;如果指定的目标已经是最新的,则返回退出状态为零,否则返回非零值.
-r, --no-builtin-rules Disable the built-in implicit rules. 禁用内置隐式规则.
-R, --no-builtin-variables Disable the built-in variable settings. 禁用内置变量设置.
-s, --silent, --quiet Don't echo recipes.  无声操作;不要在执行时打印命令.
-S, --no-keep-going, --stop Turns off -k.  取消-k选项的效果.这是永远不必要的,
除了在递归make中,-k可能通过MAKEFLAGS从顶级make继承,
或者如果你在环境中的MAKEFLAGS中设置-k.
-t, --touch Touch targets instead of remaking them. 触摸目标而不是重新制作它们.
 这用于假装命令已完成,以欺骗未来的make调用.
--trace Print tracing information. 打印跟踪信息.
-v, --version Print the version number of make and exit. 打印make和exit的版本号.
-w, --print-directory Print the current directory. 打印当前目录.
--no-print-directory Turn off -w, even if it was turned on implicitly. 关闭-w,即使它是隐式打开的.
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE Consider FILE to be infinitely new. 认为FILE是无限新的.
 没有-n,它几乎与在运行make之前在给定文件上运行touch命令相同,只是修改时间仅在make的想象中改变.
--warn-undefined-variables Warn when an undefined variable is referenced. 引用未定义的变量时发出警告.

3. 其他内核编译方法及相关连接

3.1 编译Arch的内核模块

https://wiki.archlinux.org/index.php/Compile_kernel_module
首先,您需要安装构建依赖项,例如compiler(base-devel)和linux-headers。

3.2 Arch构建系统

https://wiki.archlinux.org/index.php/Kernel/Arch_Build_System
https://www.kernel.org/doc/Documentation/kbuild/kconfig.txt
内核/Arch构建系统
该拱门构建系统可以用来构建基于官方的自定义内核的Linux软件包。
这种编译方法可以自动化整个过程,并且基于经过良好测试的软件包。
您可以编辑PKGBUILD以使用自定义内核配置或添加其他修补程序。
$ pacman -Ss asp
extra/asp 5-1    Arch Linux build source file management tool
安装的ASP封装和基devel的包组。
您需要一个干净的内核来开始自定义。通过运行以下命令从ABS获取最新的内核包文件到您的构建目录:
$ asp update linux
$ asp checkout linux
然后,从各自的源获取您需要的任何其他文件(例如,自定义配置文件,修补程序等)。

3.3 内核/传统编译

https://wiki.archlinux.org/index.php/Kernel/Traditional_compilation#Download_the_kernel_source
安装核心包
安装base-devel软件包组,其中包含必要的软件包,例如make和gcc。
还建议安装以下软件包,如默认的Arch内核PKGBUILD中所列:xmlto,kmod,inetutils,bc,libelf,git

3.4 修补包

https://wiki.archlinux.org/index.php/Patching_packages#Applying_patches
本文介绍如何创建以及如何在Arch Build System(ABS)中将补丁应用于包。
一个补丁描述了一组针对一个或多个文件线路的变化。补丁通常用于自动更改源代码。

3.5 模块与程序

http://www.tldp.org/LDP/lkmpg/2.6/html/x427.html
程序 模块
用户空间      内核空间
printf() printk()
main()开始 init_module或 通过module_init调用指定的函数 开始
  cleanup_module或 使用module_exit调用指定的函数 结束



2019-06-28

Linux-kernel-module



1. kernel module

loadable kernel module (LKM) 可加载内核模块
LKM通常用于添加对新硬件(作为设备驱动程序)和/或文件系统的支持,或用于添加系统调用。
当不再需要LKM提供的功能时,可以卸载它以释放内存和其他资源。

目前大多数类Unix系统和微软的Windows都支持可装载内核模块,虽然他们可能会使用不同的名称:
  • loadable kernel module (LKM) in Linux, 可加载内核模块
  • kernel loadable module (kld) in FreeBSD, 内核可加载模块
  • kernel extension (kext) in macOS, 内核扩展(Apple)
  • kernel extension module in AIX, 内核扩展模块(IBM)
  • kernel-mode driver in Windows NT, 内核模式驱动(Microsoft)
  • downloadable kernel module (DKM) in VxWorks, 可下载内核模块
  • kernel loadable modules (or KLM), 内核可加载模块
  • and simply as kernel modules (KMOD). 内核模块

2. Linux kernel module

Linux内核是一个自由和开放源码,单片,类Unix 操作系统 内核。负责管理计算机硬件资源。

操作系统中的实现
Linux中的可加载内核模块由modprobe命令加载(和卸载)。
内核模块文件位于/lib/modules中,从2.6版开始使用扩展名.ko(“内核对象”)(以前的版本使用.o扩展名)。
$ ls -Rl /lib/modules/5.1.15-arch1-1-ARCH //列出所有内核模块

在紧急情况下,当系统由于模块损坏而无法启动时,可以通过修改内核启动参数列表来启用或禁用特定模块
(例如,如果使用GRUB,则通过在GRUB开始菜单中按“e”,然后编辑内核参数行)。

2.1 管理模块的实用程序。

  • insmod 加载内核模块的简单程序。建议使用modprobe (8), 这更聪明,可以处理模块依赖。
  • rmmod 卸载(可卸载内核模块)的简单程序。建议使用(modprobe -r)。
  • lsmod 列出当前加载的内核模块,(地格式化/proc/modules的内容).
    • $ lsmod
    • $ cat /proc/modules
  • depmod 输出适合modprobe实用程序的依赖项列表。(生成modules.dep和映射文件)
    • $ cat /lib/modules/'uname -r'/modules.dep
    • $ cat /lib/modules/5.1.15-arch1-1-ARCH/modules.dep
  • modprobe 在Linux内核中加载/卸载模块, 可自动加载依赖模块。
  • modinfo 显示有关Linux内核模块的信息
modinfo(8)可用于从模块本身提取模块的依赖关系,但不知道别名或安装命令。

        仅报告最常见的错误消息:由于尝试链接模块的工作现在在内核中完成,因此dmesg通常会提供有关错误的更多信息。

2.1.1 depmod 选项

depmod将输出适合modprobe实用程序的依赖项列表。
-a, --all Probe all modules 探测所有模块 (默认选项)
-A, --quick Only does the work if there's a new module 只有在有新模块时才能工作
-e, --errsyms Report not supplied symbols 报告未提供符号
-n, --show Write the dependency file on stdout only 仅在stdout上写入依赖文件
-P, --symbol-prefix Architecture symbol prefix 建筑符号前缀. 指定要忽略的前缀字符 (例如"_")。
-C, --config=PATH Read configuration from PATH 从PATH中读取配置
-v, --verbose Enable verbose mode 启用详细模式. 打印(stdout)每个模块所依赖的所有符号以及提供该符号的模块文件名。
-w, --warn Warn on duplicates 警告重复的依赖项,别名,符号版本等。
-V, --version show version 显示版本
-h, --help show this help 显示这个帮助

以下选项对于管理分发的人员非常有用:
-b, --basedir=DIR If your modules are not currently in the (normal) directory /lib/modules/version, but in a staging area, you can specify a basedir which is prepended to the directory name.
This basedir is stripped from the resulting modules.dep file, so it is ready to be moved into the normal location.
Use this option if you are a distribution vendor who needs to pre-generate the meta-data files rather than running depmod again later.
使用模块树的图像。
如果您的模块当前不在(普通)目录/lib/modules/version中,而是在暂存区域中,则可以指定一个基于目录名称的b​​asedir。从生成的modules.dep文件中删除此basedir,因此可以将其移动到正常位置。如果您是需要预生成元数据文件而不是稍后再次运行depmod的分发供应商,请使用此选项。
-e, --errsyms When combined with the -F option, this reports any symbols which a module needs which are not supplied by other modules or the kernel.
Normally, any symbols not provided by modules are assumed to be provided by the kernel (which should be true in a perfect world), but this assumption can break especially when additionally updated third party drivers are not correctly installed or were built incorrectly.
报告未提供符号
 与-F选项结合使用时,会报告模块需要的任何符号,这些符号不是由其他模块或内核提供的。通常,模块未提供的任何符号都假定由内核提供(在完美的世界中应该是真的),但是当额外更新的第三方驱动程序未正确安装或构建不正确时,此假设可能会中断。
-F, --filesyms=FILE Supplied with the System.map produced when the kernel was built, this allows the -e option to report unresolved symbols.
This option is mutually incompatible with -E.
 使用该文件而不是当前的内核符号。
随内核生成时生成的System.map一起提供,这允许-e选项报告未解析的符号。此选项与-E互不兼容。
-E, --symvers=FILE When combined with the -e option, this reports any symbol versions supplied by modules that do not match with the symbol versions provided by the kernel in its Module.symvers.
This option is mutually incompatible with -F.
使用Module.symvers文件检查符号版本。
 与-e选项结合使用时,会报告模块提供的任何符号版本,这些符号版本与其Module.symvers中内核提供的符号版本不匹配。此选项与-F互不兼容。


2.1.2 modprobe 选项

Management Options:
-a, --all Consider every non-argument to be a module name to be inserted or removed (-r) 载入全部的模块。将每个非参数视为要插入或删除的模块名称(-r)
-r, --remove Remove modules instead of inserting 删除模块而不是插入
--remove-dependencies Also remove modules depending on it 此外,根据它删除模块
-R, --resolve-alias Only lookup and print alias and exit 打印与别名匹配的所有模块名称。
--first-time Fail if module already inserted or removed 如果已插入或删除模块,则失败
-i, --ignore-install Ignore install commands 忽略安装命令
-i, --ignore-remove Ignore remove commands 忽略删除命令
-b, --use-blacklist Apply blacklist to resolved alias. 将黑名单应用于已解决的别名。通常由udev(7)使用。
-f, --force Force module insertion or removal.
Implies --force-modversions and –force-vermagic
强制模块插入或移除。 (保护机制 谨慎使用)
暗示--force-modversions和-force-vermagic
--force-modversion Ignore module's version 忽略模块的版本 (保护机制 谨慎使用)
--force-vermagic Ignore module's version magic 忽略模块的版本魔力(保护机制 谨慎使用)

Query Options:
-D, --show-depends Only print module dependencies and exit 打印模块依赖项. 以“insmod”开头,通常由分发使用,以确定生成initrd/initramfs映像时要包含哪些模块。
-c, --showconfig Print out known configuration and exit 打印已知配置并退出 arch:(wc -l 43700)
--show-modversions Dump module symbol version and exit 转储模块符号版本并退出 ( --dump-modversions)
--show-exports Only print module exported symbol versions and exit 仅打印模块导出符号版本并退出

General Options:
-n, --dry-run --show Do not execute operations, just print out 不要执行操作,只需打印出来。与-v结合使用,可用于调试问题。
-C, --config=FILE Use FILE instead of default search paths 使用FILE而不是默认搜索路径。会覆盖缺省配置目录(/etc/modprobe.d)。
-d, --dirname=DIR Use DIR as filesystem root for /lib/modules 使用DIR作为/lib/modules的文件系统根目录
-S, --set-version=VERSION Use VERSION instead of `uname -r` 使用VERSION而不是`uname -r` (它决定了在哪里找到模块)
-s, --syslog print to syslog, not stderr 打印到syslog,而不是stderr。当stderr不可用时,也会自动启用此功能。
-q, --quiet disable messages 禁用消息  但仍将以非零退出状态返回。内核使用它来机会性地探测使用request_module可能存在的模块。
-v, --verbose enables more messages 启用更多消息
-V, --version show version 显示版本
-h, --help show this help 显示这个帮助

2.1.3 modinfo 选项

-a, --author Print only 'author' 仅打印'作者'
-d, --description Print only 'description' 仅打印'描述'
-l, --license Print only 'license' 仅打印'许可'
-p, --parameters Print only 'parm' 仅打印'参数'
-n, --filename Print only 'filename' 仅打印'文件名'
-0, --null Use \0 instead of \n 使用\0(ASCII零字符)分隔字段,而不是\n换行.
-F, --field=FIELD Print only provided FIELD 仅打印提供FIELD, (author, description, license, parm, depends, alias)
-k, --set-version=VERSION Use VERSION instead of 'uname -r' 使用VERSION而不是'uname -r'
-b, --basedir=DIR Use DIR as filesystem root for /lib/modules 使用DIR作为/lib/modules的文件系统根目录
-V, --version Show version 显示版本
-h, --help Show this help 显示此帮助

2.2 内核目录

/lib/modules/'uname -r'/
$ ls -Rl /lib/modules/5.1.15-arch1-1-ARCH/ |grep ko.xz |wc -l //列出所有内核模块,这里的arch里有 5474个
$ lsmod |wc -l //当前arch系统加载的有96个。

$ ls -l /lib/modules/'uname -r'/
$ ls -l /lib/modules/5.1.15-arch1-1-ARCH/
size /lib/modules/’uname -r’/ 描述 n/示例内容 wc -l
213.9 kb modules.order (.ko) 模块 [清单]
kernel/drivers/gpu/drm/i915/i915.ko
5474
685.4 kb modules.dep (.ko.xz) 所有模块路径及 [依赖] 关系
kernel/drivers/gpu/drm/i915/i915.ko.xz: kernel/drivers/gpu/drm/drm.ko.xz ...(9个文件)
5474
919.6 kb modules.dep.bin
1.4 Mb modules.alias 从模块本身提取的 [别名]. modinfo -F alias
alias pci:v00008086d00008A70sv*sd*bc03sc*i* i915 (...239行)
30142
(3850)
1.4 Mb modules.alias.bin
576.8 kb modules.symbols [符号] 别名,由symbol_request()使用。
alias symbol:i915_gpu_raise i915 (...7行)
13526
(1207)
705 kb modules.symbols.bin
5.2 kb modules.builtin (.ko) [内置]
kernel/kernel/configs.ko
161
6.9 kb modules.builtin.bin
0.4 kb modules.devname 触发按需加载模块的 [设备节点]。
fuse fuse c10:229
17
0.8 kb modules.softdep 从模块本身提取的 [软依赖项]。
softdep ext4 pre: crc32c
26

2.3 查看linux内核模块依赖关系的n种方法

2.3.1 lsmod 命令 (仅载入的部分)

$ lsmod |grep i915
i915 2166784 11
i2c_algo_bit 16384 1 i915
drm_kms_helper 212992 1 i915
drm 495616 8 drm_kms_helper,i915
intel_gtt 24576 2 intel_agp,i915

2.3.2 modinfo -F depends 命令 (仅载入的部分)

$ sudo modinfo i915 -F depends
drm,drm_kms_helper,intel-gtt,i2c-algo-bit

2.3.3 cat modules.dep 文件

$ cat /lib/modules/5.1.15-arch1-1-ARCH/modules.dep |grep i915
kernel/drivers/gpu/drm/i915/i915.ko.xz:
kernel/drivers/i2c/algos/i2c-algo-bit.ko.xz
kernel/drivers/gpu/drm/drm_kms_helper.ko.xz
kernel/drivers/gpu/drm/drm.ko.xz
kernel/drivers/char/agp/intel-gtt.ko.xz
kernel/drivers/char/agp/agpgart.ko.xz
kernel/drivers/video/fbdev/core/syscopyarea.ko.xz
kernel/drivers/video/fbdev/core/sysfillrect.ko.xz
kernel/drivers/video/fbdev/core/sysimgblt.ko.xz
kernel/drivers/video/fbdev/core/fb_sys_fops.ko.xz

2.3.4 modprobe -D 命令

$ sudo modprobe -D i915
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/video/fbdev/core/fb_sys_fops.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/video/fbdev/core/sysimgblt.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/video/fbdev/core/sysfillrect.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/video/fbdev/core/syscopyarea.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/char/agp/agpgart.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/char/agp/intel-gtt.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/gpu/drm/drm.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/gpu/drm/drm_kms_helper.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/i2c/algos/i2c-algo-bit.ko.xz
insmod /lib/modules/5.1.15-arch1-1-ARCH/kernel/drivers/gpu/drm/i915/i915.ko.xz

2.4 查看其他信息

2.4.1 符号信息

$ cat /lib/modules/5.1.15-arch1-1-ARCH/modules.symbols |grep i915
alias symbol:i915_gpu_lower i915
alias symbol:i915_gpu_raise i915
alias symbol:i915_gpu_busy i915
alias symbol:i915_gpu_turbo_disable i915
alias symbol:i915_read_mch_val i915
alias symbol:intel_gvt_register_hypervisor i915
alias symbol:intel_gvt_unregister_hypervisor i915
alias symbol:snd_hdac_i915_set_bclk snd_hda_core
alias symbol:snd_hdac_i915_init snd_hda_core
alias symbol:ips_link_to_i915_driver intel_ips

2.4.2 别名

sudo modinfo i915 -F alias |wc -l
239

cat /lib/modules/5.1.15-arch1-1-ARCH/modules.alias |grep i915 |wc -l
239


2.4.3 模块配置信息

$ sudo modprobe -c |grep i915 |wc -l
249
看起来,配置信息就是别名和符号信息了。
$ cat /lib/modules/5.1.15-arch1-1-ARCH/modules.alias |grep i915 |wc -l
239
$ cat /lib/modules/5.1.15-arch1-1-ARCH/modules.symbols |grep i915 |wc -l
10

所有模块配置信息
$ modprobe -c | less

2.4.4 显示一个装入模块使用的选项

$ sudo systool -v -m i915
Module = "i915"
  Attributes:
    coresize            = "2166784"
    initsize            = "0"
    initstate           = "live"
    refcnt              = "11"
    srcversion          = "8352F0188F789229AD1F3A8"
    taint               = ""
    uevent              = <store method only>
  Parameters:
    alpha_support       = "Y"
    ...
  Sections:
    .altinstr_aux       = "0xffffffffc0bf6ad5"
    ...

2.4.5 配置文件目录及文件

以下是当前的arch linux
/etc/modprobe.d/
/etc/modules-load.d/
/etc/mkinitcpio.d/
/etc/mkinitcpio.d/linux.preset
/etc/mkinitcpio.conf

2.5 加载模块

2.5.1 自动处理

目前,所有必要模块的加载均由 udev 自动完成。
所以,如果不需要使用任何额外的模块,就没有必要在任何配置文件中添加启动时加载的模块。
但是,有些情况下可能需要在系统启动时加载某个额外的模块,或者将某个模块列入黑名单以便使系统正常运行。

systemd 读取 /etc/modules-load.d/ 中的配置加载额外的内核模块。
配置文件名称通常为 /etc/modules-load.d/<program>.conf。
格式很简单,一行一个要读取的模块名,而空行以及第一个非空格字符为#或;的行会被忽略,如:

/etc/modules-load.d/virtio-net.conf
# Load virtio-net.ko at boot
virtio-net

2.5.2 手动加载卸载

控制内核模块载入/移除的命令是kmod 软件包提供的, 要手动装入模块的话,执行:
# modprobe module_name

如果要移除一个模块:
# modprobe -r module_name

2.6 配置模块参数

要将参数传递给内核模块,可以使用modprobe手动传递它们,或者确保始终使用modprobe配置文件或使用内核命令行应用某些参数。

2.6.1 使用modprobe手动加载时设置

传递参数的基本方式是使用 modprobe 选项,格式是 key=value:
# modprobe module_name parameter_name=parameter_value

2.6.2 使用 /etc/modprobe.d/中的文件

/etc/modprobe.d/目录中的文件可用于将模块设置传递给udev,udev将用于modprobe管理系统引导期间模块的加载。此目录中的配置文件可以具有任何名称,前提是它们以.conf扩展名结尾。比如:
/etc/modprobe.d/thinkfan.conf
# On thinkpads, this lets the thinkfan daemon control fan speed
options thinkpad_acpi fan_control=1
注意:如果从initramfs加载了任何受影响的模块,那么您需要在mkinitcpio.conf中添加相应的.conf文件或使用钩子,以便它将包含在initramfs中。
要查看默认initramfs的内容使用。FILES modconf lsinitcpio /boot/initramfs-linux.img

2.6.3 使用内核命令行

如果模块直接编译进内核,也可以通过启动管理器(GRUB, LILO 或 Syslinux)的内核行加入参数:
例如:
thinkpad_acpi.fan_control=1

2.7 别名的操作

别名是模块的备用名称。例如:alias my-mod really_long_modulename意味着您可以使用modprobe my-mod而不是modprobe really_long_modulename。您也可以使用shell样式的通配符,因此alias my-mod* really_long_modulename意味着modprobe my-mod-something具有相同的效果。创建别名:
/etc/modprobe.d/myalias.conf
alias mymod really_long_module_name
有些模块具有别名,以方便其它程序自动加载模块。禁用这些别名可以阻止自动加载,但是仍然可以手动加载。

/etc/modprobe.d/modprobe.conf
# Prevent autoload of bluetooth
alias net-pf-31 off

# Prevent autoload of ipv6
alias net-pf-10 off

2.8 黑名单

在内核模块的上下文中,黑名单是一种阻止内核模块加载的机制。例如,如果不需要关联的硬件,或者加载该模块会导致问题,这可能很有用:例如,可能有两个内核模块尝试控制同一块硬件,并将它们加载到一起会导致冲突。

一些模块作为initramfs的一部分加载。
mkinitcpio -M 将打印出所有自动检测到的模块.
  为防止initramfs加载其中一些模块,将它们列入“/etc/modprobe.d”下的“.conf”文件中(例如/etc/modprobe.d/modprobe.conf),并在 image 生成过程中通过“modconf”挂钩添加。
mkinitcpio -v 将列出由各种钩子(例如filesystems钩子,block钩子等)拉入的所有模块。
  如果您的“HOOKS”数组中没有“modconf”挂钩(例如,您偏离了默认配置),请记住将“.conf”文件添加到“/etc/mkinitcpio.conf”中的“FILES”数组中 ),一旦你列入黑名单,模块就会重新生成initramfs,然后重新启动。
https://wiki.archlinux.org/index.php/Regenerate_the_initramfs

2.8.1 使用/etc/modprobe.d/中的文件

.conf在里面创建一个文件,/etc/modprobe.d/并使用blacklist关键字为要列入黑名单的每个模块添加一行。例如,如果要阻止pcspkr模块加载:

/etc/modprobe.d/nobeep.conf
# Do not load the pcspkr module on boot
blacklist pcspkr

注意: blacklist 命令将屏蔽一个模板,所以不会自动加载,但是如果其它非屏蔽模块需要这个模块,系统依然会加载它。
要避免这个行为,可以让 modprobe 使用自定义的 install 命令,直接返回导入失败:

/etc/modprobe.d/blacklist.conf
...
install MODULE /bin/false
...

这样就可以 "屏蔽" 模块及所有依赖它的模块。

2.8.2 使用内核命令行

提示:如果损坏的模块无法启动系统,这将非常有用。
在引导加载程序中(位于 GRUB、LILO 或 Syslinux)将模块列入黑名单。

只需添加module_blacklist=modname1,modname2,modname3到引导加载程序的内核行,如内核参数中所述。
https://wiki.archlinux.org/index.php/Kernel_parameters
注意:当您将多个模块列入黑名单时,请注意它们仅以逗号分隔。[空格]或其他任何东西都可能会破坏语法。

2.8.3 常用参数

parameter Description 描述
root= Root filesystem. See init/do_mounts.c for supported device name formats. 根文件系统。有关支持的设备名称格式,请参阅init/do_mounts.c。
rootflags= Root filesystem mount options. 根文件系统挂载选项。
ro Mount root device read-only on boot (default1). 在启动时将根设备设置为只读(默认值为1)。
rw Mount root device read-write on boot. 在启动时挂载根设备读写。
initrd= Specify the location of the initial ramdisk. 指定初始ramdisk的位置。
init= Run specified binary instead of /sbin/init as init process.
The systemd-sysvcompat package symlinks /sbin/init to /usr/lib/systemd/systemd to use systemd.
运行指定的二进制文件而不是/sbin/initinit进程。
该systemd-sysvcompat包符号连接/sbin/init到/usr/lib/systemd/systemd使用systemd。
init=/bin/sh Boot to shell. 引导到shell。
systemd.unit= Boot to a specified target. 引导到指定目标。
resume= Specify a swap device to use when waking from hibernation. 指定从休眠状态唤醒时要使用的交换设备。
nomodeset Disable Kernel mode setting. 禁用内核模式设置。
zswap.enabled Enable Zswap. 启用Zswap。
panic= Time before automatic reboot on kernel panic. 在内核崩溃上自动重启之前的时间。
debug Enable kernel debugging (events log level). 启用内核调试(事件日志级别)。
mem= Force usage of a specific amount of memory to be used. 强制使用特定数量的内存。
maxcpus= Maximum number of processors that an SMP kernel will bring up during bootup. 启动期间SMP内核将提供的最大处理器数。
selinux= Disable or enable SELinux at boot time. 在引导时禁用或启用SELinux。
netdev= Network devices parameters. 网络设备参数。
video= Override framebuffer video defaults. 覆盖帧缓冲视频默认值。

完整的内核参数
https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt
module_blacklist= [KNL] Do not load a comma-separated list of modules. Useful for debugging problem modules.

2.9 故障排除

模块无法加载
如果某个特定模块未加载且启动日志(可访问journalctl -b)表示该模块已列入黑名单,但该目录/etc/modprobe.d/未显示相应的条目,请检查另一个modprobe源文件夹以/usr/lib/modprobe.d/查找列入黑名单的条目。

如果内核模块中包含的“vermagic”字符串与当前运行的内核的值不匹配,则不会加载模块。如果已知模块与当前运行的内核兼容,则可以忽略“vermagic”检查modprobe --force-vermagic。

警告:忽略内核模块的版本检查可能会导致内核崩溃或系统因不兼容而出现未定义的行为。请务必--force-vermagic谨慎使用。

3. 内核模块与应用程序的区别

3.1 模块代码

传统计算机程序的运行生命周期相当简单。加载器为程序分配内存,然后加载程序和所需要的动态链接库。指令从一些入口开始执行(传统 C/C++ 程序以 main() 函数作为入口),语句被执行,异常被抛出,动态内存被分配和释放,程序最终运行完成。当程序退出时,操作系统识别任何内存泄露,并释放到内存池。

3.2 内核模块和普通应用程序的区别有:

> 内核模块不是应用程序,从一开始就没有 main() 函数。
> 非顺序执行:内核模块使用初始化函数将自身注册并处理请求,初始化函数运行后就结束了。内核模块处理的请求在模块代码中定义。这和常用于图形用户界面(graphical-user interface,GUI)应用的事件驱动编程模型比较类似。
> 没有自动清理:任何由内核模块申请的内存,必须要模块卸载时手动释放,否则这些内存将无法使用,直到系统重启。
> 不要使用 printf() 函数:内核代码无法访问为 Linux 用户空间编写的库。内核模块运行在内核空间,它有自己独立的地址空间。内核空间和用户空间的接口被清晰的定义和控制。内核模块可以通过 printk() 函数输出信息,这些输出可以在用户空间查看到。
> 会被中断:内核模块一个概念上困难的地方在于他们可能会同时被多个程序 / 进程使用。构建内核模块时需要小心,以确保在发生中断的时候行为一致和正确。BeagleBone 有一个单核处理器(目前为止),但是我们仍然需要考虑多进程同时访问对模块的影响。
> 更高级的执行特权:通常内核模块会比用户空间程序分配更多的 CPU 周期。这看上去是一个优势,然而需要特别注意内核模块不会影响到系统的综合性能。
> 无浮点支持:对用户空间应用,内核代码使用陷阱(trap)来实现整数到浮点模式的转换。然而在内核空间中这些陷阱难以使用。替代方案是手工保存和恢复浮点运算,这是最好的避免方式,并将处理留给用户空间代码。



更多信息:


2019-05-29

Linux-kernel-timeline


Linux kernel
ProtocolLocation
HTTP https://www.kernel.org/pub/
GIT https://git.kernel.org/
RSYNC rsync://rsync.kernel.org/pub/

1. 最新版本
2. 版本类别
  活动内核版本
  分发内核版本
3. 部分较关键历史版本时间线
4. 历史版本代码规模统计
5. 常用Linux分支最新版本的内核版本号(201905)
6. 补充参考信息,部分内容可能已过时

> 1. 最新版本(包含长期发行版本)

截至2019年5月28号

版本号 时间 版本说明
3.16.68 2019.05.22 Longterm 长期发行版本 2014.08~2020.08
3.18.140[EOL] 2019.05.16 Longterm
4.4.180 2019.05.16 Longterm 长期发行版本 2016.01~2022.02
4.9.179 2019.05.25 Longterm 长期发行版本 2016.12~2023.01
4.14.122 2019.05.25 Longterm 长期发行版本 2017.11~2020.01
4.19.46 2019.05.25 Longterm 长期发行版本 2018.10~2020.10
5.1.5 2019.05.25 stable 稳定版
5.2-rc2 2019.05.26 mainline 主线

> 2. 版本主要类别

Active kernel releases 活动内核版本

Prepatch 预备
Prepatch或“RC”内核是主线内核预发行版,主要针对其他内核开发人员和Linux爱好者。
它们必须从源代码编译,并且通常包含必须在可以放入稳定版本之前进行测试的新功能。准备内核由Linus Torvalds维护和发布。

Mainline 主线 新的主线内核每2-3个月发布一次。
主线树由Linus Torvalds维护。它是引入所有新功能的树,以及所有令人兴奋的新开发项目。

Stable 稳定 根据需要发布稳定的内核更新,通常每周一次。
在每个主线内核发布后,它被认为是“稳定的”。任何针对稳定内核的错误修复都从主线树反向移植,并由指定的稳定内核维护者应用。在下一个主线内核可用之前,通常只有少数bugfix内核版本可用 - 除非它被指定为“长期维护内核”。

Longterm 长期
通常有几个“长期维护”内核版本,用于向旧内核树的后端移植错误修复。只有重要的错误修正应用于此类内核,并且它们通常不会看到非常频繁的版本,特别是对于较旧的树。

Distribution kernels 分发内核

许多Linux发行版都提供了自己的“长期维护”内核,这些内核可能也可能不是基于内核开发人员维护的内核。这些内核版本不在kernel.org上托管,内核开发人员不支持它们。

很容易判断您是否正在运行分发内核。除非您从kernel.org下载,编译和安装了自己的内核版本,否则您正在运行分发内核。要找出内核的版本,请运行
uname -r
5.1.5-arch1-2-ARCH
如果在破折号后看到任何内容,则表明您正在运行分发内核。请使用您的分发供应商提供的支持渠道来获取内核支持。

> 3. 部分较关键历史版本时间线


版本号 时间 版本说明
0.00 1991.2-4 两个进程分别显示AAABBB
0.11 1991.12.8 基本可以正常运行的内核版本
1.0 1994.3.14 linux系统的核心开发队伍建起
2.0 1996.2.9 ipfwadm
2.2 1999.1.26 ipchains
2.4 2001.1.4 netfilter
2.6 2003.12.17 支持多处理器配置和64位计算,
它还支持实现高效率线程处理的本机POSIX线程库(NPTL)。
实际上,性能、安全性和驱动程序的改进是整个2.6.x内核的关键
2.6.15 2006 改进对IPv6的支持
2.6.30 2009.6 改善了文件系统、加入了完整性检验补丁、
TOMOYOLinux安全模块、
可靠的数据报套接字(datagramsocket)协议支持、
对象存储设备支持、FS-Cache文件系统缓存层、
nilfs文件系统、线程中断处理支持等等。
2.6.32 2009.12 增添了虚拟化内存de-duplicacion、重写了writeback代码、
改进了Btrfs文件系统、添加了ATIR600/R7003D和KMS支持、
CFQ低传输延迟时间模式、perftimechart工具、
内存控制器支持softlimits、支持S+Core架构、
支持IntelMoorestown及其新的固件接口、
支持运行时电源管理、以及新的驱动
2.6.34 2010.5 添加了Ceph和LogFS两个新的文件系统,
其中前者为分布式的文件系统,
后者是适用于Flash设备的文件系统。
LinuxKernel2.6.34的其他特性包括新的Vhostnet、
改进了Btrfs文件系统、对Kprobesjump进行了优化、
新的perf功能、RCUlockdep、
GeneralizedTTLSecurityMechanism(RFC5082)
及privateVLANproxyarp(RFC3069)支持、asynchronous挂起恢复等
2.6.35 2010.8.1 在系统的多个CPU之间分配网络处理负载,
Btrfs文件系统加入直接I/O支持,大量新的驱动等
2.6.36 2010.10 Tilera处理器架构支持、新的文件通知接口fanotify、
Intel显卡上实现KMS和KDB的整合、并行管理工作队列、
Inteli3/5平台上内置显卡和CPU的智能电源管理、
CIFS文件系统本地缓存、改善虚拟内存的层级结构,
提升桌面操作响应速度、改善虚拟内存溢出终结器的算法、
整合了AppArmor安全模型
(注:与SELinux基于文件的标注不同,AppArmor是基于路径的)
2.6.38 2011.3.15 件操作性能得以提高许多,提高了Wi-Fi的性能等等
2.6.39 2011.5 加入了IPset框架,提高规则匹配速度,更新媒体控制系统等
3.0 2011.7.21
3.2 2012.1 三星Exynos处理器驱动、VMware显卡驱动脱离
staging tree以及后者的大量变动、
Intel/Radeon/Nouveau/DRM大量更新、
Btrfs文件系统改进,等等
3.5 2012.7 EXT4文件系统元数据校验,TCP连接的检查与修复
3.12.6 2013.12
3.16 2014.8 Longterm 长期发行版本 2014.08~2020.08
3.18.11 2015.4 Longterm
3.19 2015.2 为多种触控板增加多点触控支持
3.19.8 2015.5.11 在动态电源管理风扇控制、Flash友好文件系统启动时间、
多重触摸等方面做了改进
4.4 2016.1 Longterm 长期发行版本 2016.01~2022.02
4.9 2016.12 Longterm 长期发行版本 2016.12~2023.01
4.14 2017.11 Longterm 长期发行版本 2017.11~2020.01
4.19 2018.10 Longterm 长期发行版本 2018.10~2020.10
5.0.19 2019.05.25 stable 稳定版
5.1.5 2019.05.25 stable 稳定版
5.2-rc2 2019.05.26 mainline 主线

> 4. 历史版本代码规模统计



https://web.archive.org/web/20180623215917/https://www.linuxcounter.net/statistics/kernel

> 5. 常用Linux分支最新版本的内核版本号(201905)


分支 排名 点击数 最近更新日期 长期支持 分发版本 内核版本
MX Linux 1 4345 2019-05-27
18.3 4.19.37
Manjaro 2 3382 2019-03-12
2019-05-28

18.0.4
Stable
4.19.28
5.2rc1…
Mint 3 2197 2018-12-18 2023-04 19.1 4.15
Ubuntu 5 1490 2019-04-18 2020-01 19.04 5.0.0
Fedora 7 1034 2019-04-30
30 5.0.9
Arch 16 582 2019-05-29
current 5.1.15
Gentoo 48 238 2019-05-28
stable
Unstable
4.19.44
5.1.5

> 6. 补充参考信息,部分内容可能已过时

https://www.linuxidc.com/Linux/2011-08/40049.htm
内核版本号由3 个数字组成:r.x.y。

r:目前发布的内核主版本。
x:偶数表示稳定版本;奇数表示开发中版本。
y:错误修补的次数。

major.minor.patch-build.desc
2.26.35-rc5
1、major:表示主版本号,有结构性变化时才变更。
2、minor:表示次版本号,新增功能时才发生变化;一般奇数表示测试版,偶数表示生产版。
3、patch:表示对次版本的修订次数或补丁包数。
4、build:表示编译(或构建)的次数,每次编译可能对少量程序做优化或修改,但一般没有大的(可控的)功能变化。
5、desc:用来描述当前的版本特殊信息;其信息由编译时指定,具有较大的随意性,但也有一些描述标识是常用的,比如:
<1>rc(有时也用一个字母r),表示候选版本(release candidate),rc后的数字表示该正式版本的第几个候选版本,多数情况下,各候选版本之间数字越大越接近正式版。
<2>smp,表示对称多处理器(Symmetric MultiProcessing)。
<3>pp,在Red Hat Linux中常用来表示测试版本(pre-patch)。
<4>EL,在Red Hat Linux中用来表示企业版Linux(Enterprise Linux)。
<5>mm,表示专门用来测试新的技术或新功能的版本。
<6>fc,在Red Hat Linux中表示Fedora Core。


https://www.ibm.com/developerworks/cn/linux/l-linux-kernel/index.html

Platonic-solid

导航 (返回顶部) 1. 正多面体 2. Platonic-solid 2.1 判断依据 2.2 简单证明 2.3 同心球 2.4 相关计算公式 2.5 正多面体数据表 3. Blender绘制正多面体 1. 正多面体 2. Platonic-solid...