LPIC201/202 あずき本 ch2 Linuxカーネル (1/3)

LPIC201勉強メモ資格勉強

出典: 

2.1 カーネルの構成要素

2.1.1 カーネルバージョン

確認方法

unameコマンドで確認できる

-r, --kernel-release

uname -r
3.10.0-1127.19.1.el7.x86_64

-v, --kernel-version ではない

uname -v
#1 SMP Tue Aug 25 17:23:54 UTC 2020

/proc/versionでも確認できる

cat /proc/version
Linux version 3.10.0-1127.19.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Aug 25 17:23:54 UTC 2020

uname -a と比較

uname -a
Linux lpic2-study-1 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
/proc/version uname -a (-m)
ビルド情報 o x
ハードウェアアーキテクチャ情報 x o

自分でビルドした場合はカーネルソースのMakefileからも読み取れる (後述)

読み方

3桁

2.x.y
  • xが偶数: 安定版
  • xが奇数: 開発版

2.6以降 2.6.39まで

4桁になった

2.6.x
2.6.x.y
2.6.x-rcN

偶数奇数による安定/開発の区別は無くなった

  • y: xへの修正リリース番号
  • -rcN: release candidate N

    • これが開発版

3系以降

ふたたび3桁に

3.x
3.x.y
3.x-rcN
  • y: xへの修正リリース番号
  • -rcN: release candidate N

    • これが開発版
uname -r
3.10.0-1127.19.1.el7.x86_64

今回は3.10.0なので

  • メジャーバージョン3
  • マイナーバージョン10
  • 修正リリース0

2.1.2 カーネルイメージ

ls /boot/vmlinuz*
/boot/vmlinuz-0-rescue-cd7c85585b483d2656ce72740e5b59f7
/boot/vmlinuz-3.10.0-1127.19.1.el7.x86_64
/boot/vmlinuz-3.10.0-1127.el7.x86_64

zImage/bzImage

  • カーネルビルド時にmake zImageかmake bzImageかを選択できる
  • 自己解凍機能つきの圧縮機構
  • zImageにはメモリ制限があるので巨大なカーネルはbzImageを使う

2.2 カーネルモジュール

2.2.1 カーネルモジュール

  • 一部機能をモジュールしてカーネル本体から切り離す

    • デバイスドライバ等
  • 起動時間短縮、メモリ節約
  • ホットプラグ対応(USBなど)
ls -F /lib/modules/
3.10.0-1127.19.1.el7.x86_64/  3.10.0-1127.el7.x86_64/

lsmod

現在ロードされているすべてのモジュールを一覧表示する

lsmod
Module                  Size  Used by
ip6t_rpfilter          12595  1 
ip6t_REJECT            12625  2 
nf_reject_ipv6         13717  1 ip6t_REJECT
ipt_REJECT             12541  2 
nf_reject_ipv4         13373  1 ipt_REJECT
xt_conntrack           12760  8 
...

DESCRIPTION
lsmod is a trivial program which nicely formats the contents of the
/proc/modules, showing what kernel modules are currently loaded.

/proc/modules のラッパ

cat /proc/modules
ip6t_rpfilter 12595 1 - Live 0xffffffffc04a5000
ip6t_REJECT 12625 2 - Live 0xffffffffc04a0000
nf_reject_ipv6 13717 1 ip6t_REJECT, Live 0xffffffffc049b000
ipt_REJECT 12541 2 - Live 0xffffffffc0496000
nf_reject_ipv4 13373 1 ipt_REJECT, Live 0xffffffffc0491000
xt_conntrack 12760 8 - Live 0xffffffffc0485000

modinfo

モジュールの情報表示

オプション省略で全情報出力

modinfo ip6t_rpfilter
filename:       /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/net/ipv6/netfilter/ip6t_rpfilter.ko.xz
description:    Xtables: IPv6 reverse path filter match
author:         Florian Westphal <fw@strlen.de>
license:        GPL
retpoline:      Y
rhelversion:    7.8
srcversion:     14236A8ADBEB9E1BA72CD4D
depends:        
intree:         Y
vermagic:       3.10.0-1127.19.1.el7.x86_64 SMP mod_unload modversions 
signer:         CentOS Linux kernel signing key
sig_key:        B1:6A:91:CA:C9:D6:51:46:4A:CB:7A:D9:B8:DE:D5:57:CF:1A:CA:27
sig_hashalgo:   sha256

-a: author

modinfo -a ip6t_rpfilter
Florian Westphal <fw@strlen.de>

-d: description

modinfo -d ip6t_rpfilter
Xtables: IPv6 reverse path filter match

-l: license

modinfo -l ip6t_rpfilter
GPL

-n: name

modinfo -n ip6t_rpfilter
/lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/net/ipv6/netfilter/ip6t_rpfilter.ko.xz

rmmod/insmod

疲れていないカーネルモジュールとして乱数生成器を見繕ってみる

lsmod | grep rng
virtio_rng             13029  0 
...
modinfo virtio_rng
filename:       /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz
license:        GPL
description:    Virtio random number driver
retpoline:      Y
rhelversion:    7.8
srcversion:     1D236D98CE131093B1EB6FF
alias:          virtio:d00000004v*
depends:        virtio,virtio_ring
intree:         Y
vermagic:       3.10.0-1127.19.1.el7.x86_64 SMP mod_unload modversions 
signer:         CentOS Linux kernel signing key
sig_key:        B1:6A:91:CA:C9:D6:51:46:4A:CB:7A:D9:B8:DE:D5:57:CF:1A:CA:27
sig_hashalgo:   sha256

rmmod

ロードされているモジュールをアンロード

  • remove a module から
  • 使用中、依存関係にあるものは不可能
$ rmmod virtio_rng
rmmod: ERROR: could not remove 'virtio_rng': Operation not permitted
rmmod: ERROR: could not remove module virtio_rng: Operation not permitted
# rmmod virtio_rng
(とくに出力なし)

insmod

insert a moduleから

cat /proc/modules | grep rng
(出力なし)

insmodではモジュール名ではなくモジュールファイル名を指定する

insmod -v /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz

書籍で紹介されていた -v (verbose)は無かった。ディストリ依存?

insmod: invalid option -- 'v'

管理者権限必要

$ insmod /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz
insmod: ERROR: could not insert module /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz: Operation not permitted
# insmod /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz
(出力なし)

インストール確認

cat /proc/modules | grep rng
virtio_rng 13029 0 - Live 0xffffffffc04aa000
virtio_ring 22952 5 virtio_rng,virtio_net,virtio_balloon,virtio_scsi,virtio_pci, Live 0xffffffffc016a000
virtio 14959 5 virtio_rng,virtio_net,virtio_balloon,virtio_scsi,virtio_pci, Live 0xffffffffc0162000

modprobe

NAME
       modprobe - Add and remove modules from the Linux Kernel

rmmod/insmodの賢いやつ

  • 依存関係を考慮して、必要なものも自動的にロードしてくれる

    • cf. insmodは依存関係を自分で管理する
  • 依存関係表示
modprobe --show-depends virtio_rng
insmod /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/virtio/virtio.ko.xz 
insmod /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/virtio/virtio_ring.ko.xz 
insmod /lib/modules/3.10.0-1127.19.1.el7.x86_64/kernel/drivers/char/hw_random/virtio-rng.ko.xz 

used by側から順に書かれている

modprobeではremove/installともにカーネルモジュール名を指定する

modprobe -r virtio_rng
modprobe: ERROR: could not remove 'virtio_rng': Operation not permitted
# modprobe -r virtio_rng
(出力なし)
$ modprobe virtio_rng
modprobe: ERROR: could not insert 'virtio_rng': Operation not permitted
# modprobe virtio_rng
(出力なし)

-n, --dry-run, --show: 実際には何もしない

module.depファイル

モジュールの依存関係は /lib/modules/$(uname -r)/modules.dep に記述されている

cat /lib/modules/$(uname -r)/modules.dep | grep rng
kernel/crypto/ansi_cprng.ko.xz:
kernel/crypto/jitterentropy_rng.ko.xz:
kernel/crypto/algif_rng.ko.xz:
kernel/drivers/char/hw_random/timeriomem-rng.ko.xz:
kernel/drivers/char/hw_random/intel-rng.ko.xz:
kernel/drivers/char/hw_random/amd-rng.ko.xz:
kernel/drivers/char/hw_random/via-rng.ko.xz:
kernel/drivers/char/hw_random/virtio-rng.ko.xz: kernel/drivers/virtio/virtio_ring.ko.xz kernel/drivers/virtio/virtio.ko.xz

抜粋

kernel/drivers/char/hw_random/virtio-rng.ko.xz: kernel/drivers/virtio/virtio_ring.ko.xz kernel/drivers/virtio/virtio.ko.xz

kernel/drivers/char/hw_random/virtio-rng.ko.xz depends on .../virtio_ring.ko.xz and .../virtio.ko.xz の意

modules.depファイルはdepmodコマンドで生成

depmod - Generate modules.dep and map files.

/etc/modprobe.conf, /etc/modprobe.d/

モジュールロード時のパラメータ指定等の設定ファイル

ls /etc/modprobe.d/
blacklist-floppy.conf  firewalld-sysctls.conf  tuned.conf
dccp-blacklist.conf    gce-blacklist.conf
cat /etc/modprobe.d/gce-blacklist.conf
# nouveau does not work with GCE GPU's.
blacklist nouveau

# GCE does not have a floppy device.
blacklist floppy

手元のPCのやつ

cat /etc/modprobe.d/mdadm.conf
# mdadm module configuration file
# set start_ro=1 to make newly assembled arrays read-only initially,
# to prevent metadata writes.  This is needed in order to allow
# resume-from-disk to work - new boot should not perform writes
# because it will be done behind the back of the system being
# resumed.  See http://bugs.debian.org/415441 for details.

options md_mod start_ro=1
cat /etc/modprobe.d/iwlwifi.conf
# /etc/modprobe.d/iwlwifi.conf
# iwlwifi will dyamically load either iwldvm or iwlmvm depending on the
# microcode file installed on the system.  When removing iwlwifi, first
# remove the iwl?vm module and then iwlwifi.
remove iwlwifi \
(/sbin/lsmod | grep -o -e ^iwlmvm -e ^iwldvm -e ^iwlwifi | xargs /sbin/rmmod) \
&& /sbin/modprobe -r mac80211

書式

  • alias

    • モジュールのエイリアス名定義
  • options

    • モジュールのオプション指定
  • install/remove

    • modprobe/modprobe -r 実効時にシェルコマンド実行

2.3 カーネルのコンパイル

こんなときにカーネルの再構築を行う

  • 必要なデバイスドライバが入ってない
  • H/W最適化したい
  • カーネルバージョンアップしたい

2.3.1 カーネルのコンパイルとインストール

カーネルソースの準備

  • /usr/src/, /usr/src/kernels/(RHEL, CentOS)等に格納するよう想定されている

    • LPIC的には /usr/src/linux/ symlinkが置かれていることを想定している
  • 今回はホームディレクトリ以下で作業することにする
mkdir ~/kernels
cd ~/kernels

kernel.orgからtarballを拾ってきて展開

curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.9.12.tar.xz -o linux-5.9.12.tar.xz
tar xvJf linux-5.9.12.tar.xz

カーネルのバージョンは uname -r, /proc/version のほか、Makefileからも読み取れる

head -n 5 Makefile
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 9
SUBLEVEL = 12
EXTRAVERSION =

カーネルコンフィギュレーションの反映

ソースコードの .config ファイルで記述

  • ゼロから設定するのは大変 & 古いバージョンの設定ファイルは新しいカーネルでそのままは使えない
  • 移行のために make oldconfigが用意されている
cd linux-5.9.12
ls
COPYING        Kbuild	 MAINTAINERS  arch   crypto   include  kernel  net	security  usr
CREDITS        Kconfig	 Makefile     block  drivers  init     lib     samples	sound	  virt
Documentation  LICENSES  README       certs  fs       ipc      mm      scripts	tools

現在のカーネルのオプションを引き継ぐ場合、/boot/のコンフィグをコピーしてmake oldconfigする

cp /boot/config-$(uname -r) .config
make oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  LEX     scripts/kconfig/lexer.lex.c
/bin/sh: flex: command not found
make[2]: *** [scripts/kconfig/lexer.lex.c] Error 127
make[1]: *** [oldconfig] Error 2
make: *** [__sub-make] Error 2

flex, bisonが無いと言われるのでインストールして再度

sudo yum install -y flex bison

make oldconfig
  YACC    scripts/kconfig/parser.tab.[ch]
  HOSTCC  scripts/kconfig/lexer.lex.o
  HOSTCC  scripts/kconfig/parser.tab.o
  HOSTCC  scripts/kconfig/preprocess.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/util.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --oldconfig Kconfig
.config:697:warning: symbol value 'm' invalid for CPU_FREQ_STAT
.config:941:warning: symbol value 'm' invalid for NF_CT_PROTO_GRE
.config:969:warning: symbol value 'm' invalid for NF_NAT_REDIRECT
.config:972:warning: symbol value 'm' invalid for NF_TABLES_INET
.config:1139:warning: symbol value 'm' invalid for NF_TABLES_IPV4
.config:1143:warning: symbol value 'm' invalid for NF_TABLES_ARP
.config:1184:warning: symbol value 'm' invalid for NF_TABLES_IPV6
.config:1559:warning: symbol value 'm' invalid for NET_DEVLINK
.config:2719:warning: symbol value 'm' invalid for ISDN_CAPI
.config:3664:warning: symbol value 'm' invalid for LIRC
*
* Restart config...
*
*
* General setup
*
*
* General setup
*
Compile also drivers which will not load (COMPILE_TEST) [N/y/?] (NEW) y
Local version - append to kernel release (LOCALVERSION) [] 
Build ID Salt (BUILD_SALT) [] (NEW) 
Kernel compression mode
> 1. Gzip (KERNEL_GZIP)
  2. Bzip2 (KERNEL_BZIP2)
  3. LZMA (KERNEL_LZMA)
  4. XZ (KERNEL_XZ)
  5. LZO (KERNEL_LZO)
  6. LZ4 (KERNEL_LZ4) (NEW)
  7. ZSTD (KERNEL_ZSTD) (NEW)
choice[1-7?]: 4
...

現在の設定ファイルの設定が反映され、新設のものについて果てしなく質問攻めされる

カーネルの設定

make config: 対話形式

  • make oldconfigと同じ
make config
scripts/kconfig/conf  --oldaskconfig Kconfig
.config:697:warning: symbol value 'm' invalid for CPU_FREQ_STAT
.config:941:warning: symbol value 'm' invalid for NF_CT_PROTO_GRE
.config:969:warning: symbol value 'm' invalid for NF_NAT_REDIRECT
.config:972:warning: symbol value 'm' invalid for NF_TABLES_INET
.config:1139:warning: symbol value 'm' invalid for NF_TABLES_IPV4
.config:1143:warning: symbol value 'm' invalid for NF_TABLES_ARP
.config:1184:warning: symbol value 'm' invalid for NF_TABLES_IPV6
.config:1559:warning: symbol value 'm' invalid for NET_DEVLINK
.config:2719:warning: symbol value 'm' invalid for ISDN_CAPI
.config:3664:warning: symbol value 'm' invalid for LIRC
*
* Linux/x86 5.9.12 Kernel Configuration
*
*
* General setup
*
Compile also drivers which will not load (COMPILE_TEST) [N/y/?] (NEW) 
...

メニュー形式で設定

  • make menuconfig

    • ncurses
  • make xconfig

    • X(KDE)
  • make gconfig

    • X(GNOME)

カーネルとカーネルモジュールのコンパイル

コンパイラアップデート

クソ古で怒られるので新しくする

参考: https://thr3a.hatenablog.com/entry/20180308/1520506543

gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
sudo yum install -y centos-release-scl
sudo yum install -y scl-utils
sudo yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils

「新しいの使うよ」とコマンド

sudo scl enable devtoolset-7 bash
gcc --version
gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ビルド・インストール

make
...
scripts/sign-file.c:25:30: fatal error: openssl/opensslv.h: No such file or directory
 #include <openssl/opensslv.h>
                              ^
compilation terminated.

足りないもの入れる

sudo yum install -y openssl-devel bc elfutils-libelf-devel
make

めっちゃ時間かかる

カーネルモジュールとカーネルのインストール

TODO: 手を動かす (ビルドが終わらなすぎるので試せてない)

# make modules_install
# make install

下記が実行される

  • カーネルを/boot以下にコピー (/boot/vmlinuz-${バージョン})
  • (必要ならば)初期RAMディスク作成
  • ブートローダの設定ファイルに新しいカーネル用のエントリ追加

ブートローダの設定ファイルに新しいカーネル用のエントリ追加

sudo grep "^menuentry" /boot/grub2/grub.cfg | cut -d "'" -f 2
CentOS Linux (3.10.0-1127.19.1.el7.x86_64) 7 (Core)
CentOS Linux (3.10.0-1127.el7.x86_64) 7 (Core)
CentOS Linux (0-rescue-cd7c85585b483d2656ce72740e5b59f7) 7 (Core)

grub2-set-default で0番目をデフォルトに設定

# grub2-set-default 0

設定ファイル更新

# grub2-mkconfig -o /boot/grub2/grub.cfg

システムを再起動すると新しいデフォルトになっている

DKMS: Dynamic Kernel Module Support

https://wiki.archlinux.jp/index.php/Dynamic_Kernel_Module_Support

カーネルのアップグレード時、カーネルソースツリー外のサードパーティ製カーネルモジュールを自動でリビルドしてくれる