Linux OS 開発環境/ツール

【PC】Linuxビルドのノウハウ(残課題)

Linuxのカーネルビルドに関する残課題を1つ1つ解決していきます。

この記事で解決できること

  • Linuxのカーネルビルドに関するノウハウを知ることが出来る。

関連記事

【PC】Linuxビルドのノウハウ(ビルドとインストール)

【PC】Linuxビルドのノウハウ(残課題)

【WSL】WindowsでLinuxを動かす

【Yocto】組み込みLinuxの主流はYocto

【Linuxコマンド】便利な小技たち(TIPS)

【ネットワーク】WindowsからUbuntu14.04に接続する方法2つ

【Linuxコマンド】パッチを使いこなしたい

【UNIX時間】2038年問題について整理する

 

patchとinc.patchの違い

patch、inc.patch。両方落としてみたが、どっちも普通のパッチだった。patchのリンクにマウスを持っていくと「Download to previous mainline」と表示される。inc.patchのリンクにマウスを持っていくと「Download incremental patch」と表示される。まだ違いが分かってない。

違いを理解せず、先に進んだのだった。

そもそも、私はパッチを使いこなせていないので、そこから始めたい。しかしパッチのことを調べ始めると、それだけでこの記事が埋まってしまいそうなので、別の記事(【Linuxコマンド】パッチを使いこなしたい)にまとめた。

ここでは「Download to previous mainline」と「Download incremental patch」の違いについてのみ調査する。

The Linux Kernel Archivesを開いた。確か3日前ぐらいは5.1.16がstableだったのに今日見たら5.2がstableになってる。

patchをダウンロードしてみるとpatch-5.1.16.xzというファイルだった。

inc.patchをダウンロードしてみるとpatch-5.1.15-16.xzいうファイルだった。

xzファイルをWindowsで解凍するには7-zipが要るみたい(Windows環境でtar.xzを解凍(展開)する方法)。まだこのPCには7-zipを入れてないのでTeraTerm経由でパッチをLinuxパソコンにscp転送した(なんとなく5.2のパッチもダウンロードした)。

【 xz 】コマンド/【 unxz 】コマンド――ファイルを圧縮/伸張するを読み、unxzというコマンドで解凍できることを知る。

無事解凍できた。

patchは「Download to previous mainline」。これは古いメインラインへのパッチと読み取れる。

patch-5.1.16を開きMakefileのdiffを見た。これは5.1.0から5.1.16への差分だ。

diff --git a/Makefile b/Makefile
index 26c92f892d24..46a0ae537182 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 1
-SUBLEVEL = 0
+SUBLEVEL = 16
EXTRAVERSION =
NAME = Shy Crocodile

@@ -636,7 +636,7 @@ ifeq ($(may-sync-config),1)
# Read in dependencies to all Kconfig* files, make sure to run syncconfig if
# changes are detected. This should be included after arch/$(SRCARCH)/Makefile
# because some architectures define CROSS_COMPILE there.
--include include/config/auto.conf.cmd
+include include/config/auto.conf.cmd

$(KCONFIG_CONFIG):
@echo >&2 '***'

inc.patchは「Download incremental patch」。これは増分パッチと読み取れる。patch-5.1.15-16を開きMakefileのdiffを見た。これは5.1.15から5.1.16への差分だ。

diff --git a/Makefile b/Makefile
index d7b3c8e3ff3e..46a0ae537182 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 1
-SUBLEVEL = 15
+SUBLEVEL = 16
EXTRAVERSION =
NAME = Shy Crocodile

patch-5.2のMakefileのdiffも見てみた。これは5.1.0から5.2.0への差分だ。

diff --git a/Makefile b/Makefile
index 26c92f892d24..3e4868a6498b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
-PATCHLEVEL = 1
+PATCHLEVEL = 2
SUBLEVEL = 0
EXTRAVERSION =
-NAME = Shy Crocodile
+NAME = Bobtail Squid
(以下省略)

なんか法則が分かってきた。

patch-5.1.15-16 は 5.1.15→5.1.16の差分
patch-5.1.16 は 5.1.0→5.1.16の差分
patch-5.2 は 5.1.0→5.2.0の差分

サイズを見てもそんな感じ。

-rw-r--r-- 1 pavement1234 pavement1234 100804 7月 10 01:31 patch-5.1.15-16
-rw-r--r-- 1 pavement1234 pavement1234 1997684 7月 10 01:31 patch-5.1.16
-rw-r--r-- 1 pavement1234 pavement1234 64241504 7月 10 01:26 patch-5.2

The Linux Kernel HOWTO5. カーネルへのパッチあてを読む。更にLinuxのバージョンを確認する方法を読む。今後トラブったらこの辺を参考にしよう。

The Linux Kernel Archive(本家)のトップページにあるHTTP、GIT、RSYNCの飛び先がどうなってるか?

HTTPを調べる

まずはHTTPから調べてみる。開くとこんな感じ。

../(1つ上のディレクトリ)を開く。MIRRORS.kernel.orgってのが出てくる。なんか有用な感じのサイトが盛りだくさん。これはこれで今度掘ってみたい。

さて、pubの階層には7つのディレクトリがあるlinuxが一番深く、softwareが次に深い。以前すべてのディレクトリを掘ってみたが、Gitに移行していてHTTPはサポートされていない感じ。

以前、気になったことがあったのでまとめておく。

①planb、puperrescure

まずはdist。懐かしのknoppix(CD/DVD起動のLinux。すごい前に流行った気がする。)は分かるがplanbsuperrescureとは何だろう。

distはディストリビューションのことだろう。

まずPlan-Bを発見。RedHat系のLinuxですね。Knoppixと同様にデータレスキュー用途みたい。しかし状態:休止したとありますね。しかし、たまたま今回見つけたDistro Watch.comってデータベースとしてすごい感じ。

続いてsuperrescue。Distro Watch.comで調べてみるとSuperRescue CDを発見。カンタンにヒットしました。こいつもRedHat系、かつ、データレスキュー用途、かつ、休止した。Plan Bと同じ運命を辿ったみたい。

②開発ツールたちの最新版を入手する方法を知りたい

linux/devel。binutilsとはGNUのバイナリユーティリティ。GNU Binutilsに詳しく書いてある。ar(アーカイバ)、as(アセンブラ)、ld(リンカ)、objdump(オブジェクトのダンプ情報表示)、readelf(EFLファイルの内容を表示)などが含まれる。gccはコンパイラ。gdbはデバッガ。なんかどれもバージョンが古そうな感じではある。開発ツールたちの最新版を入手する方法が知りたい。

まずはGNU Binutils

最新版は2.32。2019年2月2日更新。http://ftp.gnu.org/gnu/binutils/(Index of /gnu/binutils)にUPされてます

ソースコードはGITにUPされており、git clone git://sourceware.org/git/binutils-gdb.gitで落とせますし、the gitweb interfaceを開くとWEBでサマリーが見れます。

次にGCC, the GNU Compiler Collection。最新版はv9.1。2019年5月3日更新。ソースはSVN管理されていてGCC: Anonymous read-only SVN accessにある通り、svn checkout svn://gcc.gnu.org/svn/gcc/trunk SomeLocalDirでチェックアウトできる。

またGCC GIT mirrorにミラーサイトが構築されてます。gcc.gnu.org/gitを開くとWEBでサマリーも見れます。

最後にGDB: The GNU Project Debugger。最新版はv8.3。2019年5月11日更新。Download GDBを開くとダウンロード先のHTTP、FTPアドレスが書いてあります。

http://ftp.gnu.org/gnu/gdb/(Index of /gnu/gdb)を開くとUPされてます。

これでbinutils、gcc、gdbの最新版入手方法がわかりました。ちなみに組込用途で使われるクロスコンパイラはLinaroが有名。PC Linuxの開発環境に関する調査が落ち着いたら組込Linuxに調査移行するので、そのときに調べます。

③crypto、backport、rt、usb、perf

linux/kernel。ここにカーネルソースたちが入ってます。カーネルソース以外に目についたのはcrypto(暗号化)、backport(アプリの後方互換性を担保するために新しい機能を古いカーネルに移植し続けてるヤツ)、rt(リアルタイム)、usb(詳細は見てないがUSBの何か)、perf(性能測定ツール)などを調べる。

まずcryptoLinux Kernel Crypto APIを見るとLinux標準のCrypto(暗号)APIがあるみたい。Crypto API (Linux)を見たらユーザスペースとのインタフェースとしてAF_ALG(netlink)cryptodev(dev/crypto)が記載されていた。AF_ALGはLinuxカーネル2.6.38からマージされており、OpenSSLもサポートされるみたい。cryptodevはOpenBSD系みたいですがLinuxカーネルにはマージされなかったみたいCryptodev-linux moduleに情報が載ってる。更に詳細を調べ始めると深みにハマりそうなのでここまでにする。

参考にしたThe Linux Kernel documentationはなんかすごく良いのでまた使うことにする。

次にbackportLinux backportを見るとこんなことが書いてある。要は古いカーネルで最新のドライバを動作させることを可能にするってことみたい。またbackportプロジェクトは2007年にワイヤレス互換性ドライバ(compat-wireless)のために始まったみたい。backportについては興味アリなのでまた調べてみようと思う。

Main Page
The Backports Project enables old kernels to run the latest drivers.
"Backporting" is the process of making new software run on something old. A version of something new that's been modified to run on something old is called a "backport".
The Backports Project develops tools to automate the backporting process for Linux drivers. These tools form the backports suite.

History
The Backports Project started in 2007 as compat-wireless. It was renamed to compat-drivers as the project's scope broadened beyond just wireless network drivers. Nowadays, the project is known simply as backports.
As of the 3.10-based release, over 830 device drivers had been backported.
Recent versions of backports support mainline kernels back to version 3.0. The older backports-3.14 supports all kernel versions back to version 2.6.26.

次はrtRaspberry Pi 3 (Raspbian Jessie)にRT Preemptカーネルを導入を読んだ。このrtはRT preemptパッチを指すらしい。更にubuntuにrt-preemptカーネルを導入するを読むと、本気でリアルタイム性を高めるならRTAI、RT-Linuxというのもあるみたいだが導入が難しいみたい。low-latencyカーネルというものもあるみたいだが精度はそれほどないみたい。RT preemptはその中間。つまり精度の高い順に書くと(RTAI/RT-Linux > RT preempt > low-latencyカーネル)となるみたい。リアルタイム性を高める改良に興味アリなので、そのうち調べてみる。

次はusbUSB Host Stack Debuggingを見ると、初期にLinusが書いたUSBホストスタックのことみたい。コンパクトなので理解がしやすく、USBデバッグに役立つとのこと。いつか調べるかも。

次はperfLinux 性能解析ツールperfを使ってみたを調べてみた。こんな感じみたいだがperfはボリューム大な感じなので、今回はここまでとする。

perf(Performance analysis tools for Linux)とはLinuxカーネル2.6.31以降で使用可能なLinuxの性能解析ツールです。ざっくりいえば下記

実行されるプログラムと OS とのイベントを見れる
OS とハードウェアのイベントを見れる

カーネルのカウンタで計測されるイベントだったりプロセッサで計測されるイベントが知れる
例えばL1のヒット状況やTLBの様子なども観察できます。
(CPUサイクル数、分岐の数、分岐予測ミス数、キャッシュ参照数、キャッシュミス数など豊富な機能)

次いでだがlinux/kernel/firmwareってそういえば何だろうと思い追加で調べてみました。Linux Firmware APIを読むと、request_firmwareでファームの呼び出しを行ったりする標準APIのことみたい。φ(.. )メモシテオコウ Linux:firmwareの読み込み処理めもを見ると、ちょっと詳しく書いてあります。

④comma、nfc、ofono、wireless

linux/network。connman(コマンドベースのネットワークマネージャ)、nfc
(近距離無線)、ofono(オープンソースの携帯電話)、wireless(無線)、と気になるキーワード4連発。

まずはcommanConnManを読むと有線と無線のネットワークを制御するコマンドみたい。

使用方法

ConnMan には標準のコマンドラインクライアント connmanctl が付属しています。connmanctl は2つのモードで動作します:

コマンドモードでは、connmanctl に引数を付けてコマンドを実行します。systemctl と似ています。
インタラクティブモードでは、connmanctl に何も引数を付けずに起動します。プロンプトが connmanctl> に変化し、ユーザーがコマンドを入力するのを待機します。python のインタラクティブモードに似ています。インタラクティブモードではタブ補完を使うことができ、簡単に接続できます。

有線
ConnMan は自動的に有線接続を管理します。

Wi-Fi
Wi-Fi の有効化と無効化
Wi-Fi が有効になっているかどうか確認するには connmanctl technologies を実行して Powered: True/False と表示された行をチェックしてください。Wi-Fi を有効にするには connmanctl enable wifi を実行し、無効にする場合は connmanctl disable wifi を実行します。ノートパソコンの場合 Fn キーを使って Wi-Fi の電源を入れてください。もしくは ip link set <interface> up を実行してみてください。

次にnfcNFCをリード・ライトするためにRaspbianをビルドするを読みました。更にLinux NFC Subsystemというものがあるそうだ を読み、Linux NFC Subsystem(PDF)にたどり着いた。2011年段階ではNXP等のベンダ依存がありPOSIX仕様からも逸脱していたみたい。なので、netlinkとかソケットとかを使って標準化を進めたいという意向があったようだ。現状どうなっているかはこの資料から知る由もないが、いつか調べてみよう。

次にofonooFonoを読んだ。携帯電話(GSM/UMTS)アプリ用のフリーソフト。D-BusのAPIを使用する。GPLv2。ということが読み取れた。Universal Mobile Telecommunications Systemあたりを読むと3G回線の細かい話が書いてある。興味はあるが今回はここまで。

(原文)
oFono is a free software project for mobile telephony (GSM/UMTS) applications. It is built on 3GPP standards and uses a high-level D-Bus API for use by telephony applications. oFono is free software released under the terms of the GNU General Public License v2.[4]

(和訳)
oFonoは、携帯電話(GSM / UMTS)アプリケーション用のフリーソフトウェアプロジェクトです。 これは3GPP規格に基づいて構築されており、テレフォニーアプリケーションで使用するための高レベルのDバスAPIを使用しています。 oFonoは、GNU一般公衆利用許諾契約書v2の条項に基づいてリリースされたフリーソフトウェアです[4]。

次にwirelessLinux Wirelessを読んだ。このページが昔から好きで良く読んでいる。mac80211、cfg80211、nl80211と呼ばれる無線LANサブシステムを中心とした解説である。本記事の最後にLinux Wirelessがまた出てくるので一旦終了。

⑤abi-tools、dracut、efilinux、syslinux、crusoe、mce、dtc、fs、kbd、cpufreq、hotplug、ipvsadm、kexec、ksymoops、module-init-tools、modutils、bridge-utils、nfs-utils、mdadm、rt-tests

linux/utils。abi-toolsはアプリケーションバイナリインタフェースのことか?今回はスルー。dracutはDracutの歩き方Add StarItisangoを見るとわかるがinitrdをカスタマイズするツールみたい。efilinuxはUEFIブートローダ。Ubuntuのセキュアブートへの対応 あたりに関連情報が載っている。syslinuxは軽量なブートローダ。SYSLINUXでマルチブート【基本編】をいつか読んでみよう。crusoeはx86互換プロセッサ。Crusoeに概要が書いてある。mceはマシンチェック例外。dtcはデバイスツリーコンパイラ、fsはファイルシステム。kbdはキーボード。cpufreqは周波数スケーリング。hotplugはプラグandプレイ。ipvsadmはロードバランサ。kexecはカーネル上でカーネルを起動させるやつ。ksymoopsはカーネルパニック時のoopsメッセージを少しわかりやすく表示するもの。module-init-toolsmodutilsは古いローダブルモジュール管理ツール、bridge-utilsはブリッジ構成ツール(複数のネットワークインターフェースをまとめてブリッジ化するやつ)、nfs-utilsはNFS管理ツール、mdadmはソフトウェアRAID、rt-testsはリアルタイムカーネルのテスト。

とりあえず上のコメントで概要の説明ができてる項目は割愛。イマイチ理解できてないヤツだけを少し補足することにする(量が多いし)。

まずcpufreqCPU 周波数スケーリングを読んだ。OSやアプリからCPUクロックを調整できるみたい。

CPU 周波数スケーリングを使うことで電力を節約するためにオペレーティングシステムが CPU の周波数を調整することが出来るようになります。CPU の周波数はユーザースペースのプログラムを使って手動で変更したり、システムの負担や、ACPI イベントにあわせて自動的に調整することが可能です。
CPU 周波数スケーリングは Linux カーネル内に実装されており、そのインフラストラクチャは cpufreq と呼ばれています。カーネル 3.4 から必要なモジュールが自動でロードされるようになり推奨の ondemand governor がデフォルトで有効になっています。しかしながら、cpupower, acpid, Laptop Mode Tools などのユーザースペースツールや、デスクトップ環境から提供されている GUI ツールを使って高度な設定をすることも可能です。

次にhotplug9.11. ホットプラグ機能、hotplugを読んだ。udevの仕組みを使って/dev/xxxにデバイスを登録する仕組みと理解。

9.11.1. 前書き
hotplug カーネルサブシステムはデバイスの追加と削除を、udevd の助けを借りて適切なドライバを読み込んだり関連するデバイスファイルを作成することで、動的に取り扱います。現代的なハードウェアと仮想化を使えば、ほとんどすべてのデバイスはホットプラグ対応と言ってよいでしょう。具体的に言えば、USB/PCMCIA/IEEE 1394 周辺機器から SATA ハードドライブ、さらには CPU やメモリにいたるまでのほとんどすべてがホットプラグに対応しています。 カーネルは必要なドライバとデバイス ID を関連付けるデータベースを持っています。このデータベースは起動中にさまざまなバスで検出された周辺機器用のすべてのドライバを読み込んだりする際、追加的なホットプラグデバイスが接続された際に使われます。デバイスの使用準備が整ったら、メッセージが udevd に送信され、udevd は対応するエントリを /dev/ 内に作成します。

次にipvsadm。今回これが一番理解できなかったが、ipvsadm(8) 日本語訳 を読んで少しだけ理解した。更にLinuxでL4のロードバランサを簡単に作る手順を読み、もうちょっと理解した。要はTCP、UDP(レイヤ4)の負荷を、パケット転送方式、ロードバランスアルゴの調整で実現するサーバ管理ツールと理解しました。

Ipvsadm(8)はLinuxカーネル内の仮想サーバテーブルを設定、保守、調査をするために使われます。Linux Virtual Server (LVS) は2台以上のノードからな るク ラスタに基づいたスケーラブルなネットワークサービスを構築するために用いることができます。クラスタのアクティブノードはサービスのリクエスト を、 実際にサービスを実行するサーバホストの集まりに送信します。サポートされている機能として二つのプロトコル(TCPとUDP),3つのパケッ ト 転 送 方 式(NAT, トンネリング、ダイレクトルーティング), そして8つのロードバランスアルゴリズム(ラウンドロビン、重み付きラウンドロビン、最小接続、重み付き最 小接続、所在ベース最小接続、レプリケーションつきの所在ベース最小接続、宛先ハッシュ、送信元ハッシュ)があります。

次にkexeckexecを読んだ。実行中のカーネルの上で新たにカーネルをブートさせるってことですね。

kexecは現在起動中のカーネル上で新しいカーネルのライブブートを可能にする、Linuxカーネルのメカニズムである。"kexec" という名前はkernel executionの略称と、UNIX/Linuxカーネル呼び出しのexecに由来する。kexecは実質的に、システムファームウェア(BIOSやUEFI)が実行するブートローダのステップとハードウェアの初期化フェイズをスキップし、メインメモリに直接新しいカーネルをロードしてすぐにその実行を開始する。これにより完全なブートと関連する長時間処理を避けられるためダウンタイム(英語版)を最小化することができ、システムの高可用性を満たせるようになる[1][2][3]。

次にksymoopsoopsメッセージの解析方法を読んだ。カーネルパニックが発生したときに試してみようかな。

準備するファイルは、
・panic時に出力されるOopsメッセージ
・KernelをBuild時に生成されるSystem.map
使用方法は、 # ksymoops ?m [System.map] [oops_message]

次にmodule-init-toolsmodutilsmodutils パッケージは kernel 2.6 では不要 (2006/04/07)を読んだ。

modutils パッケージは kernel 2.4 以前のもので kernel 2.6 では,module-init-tools パッケージになります

だそうだ。更にmodule-init-toolsを読んでようやくわかった。insmodとかmodprobeたちだ。

depmod - 存在しているモジュール内に含まれるシンボル名に基づいて、モジュールの依存関係を記述したファイル (dependency file) を生成します。 これは modprobe が、必要なモジュールを自動的にロードするために利用します。
insmod - 稼動中のカーネルに対してロード可能なモジュールをインストールします。
insmod.static - スタティックライブラリによってコンパイルされた insmod コマンド。
lsmod - その時点でロードされているモジュールを一覧表示します。
modinfo - カーネルモジュールに関連付いたオブジェクトファイルを調べて、出来る限りの情報を表示します。
modprobe - depmod によってモジュールの依存関係を記述したファイル (dependency file) が生成されます。 これを使って関連するモジュールを自動的にロードします。
rmmod - 稼動中のカーネルからモジュールをアンロードします。

次にbridge-utilsネットワークブリッジを読んだ。要はbrctlのことだ。

ブリッジは複数のネットワークセグメントをまとめるのに使われる一種のソフトウェアです。ブリッジは仮想ネットワークスイッチのように動作し、透過的に働きます (他のマシンはブリッジの存在を知る必要がありません)。

次にnfs-utils5分で終わらせるNFSファイル共有を読んだ。サーバとクライアント間で超簡単にディレクトリ共有できる感じ。今度実験してみよう。

次にmdadmソフトウェアRAID の初期設定と運用 - mdadmを読んだ。ソフトウェアでRAIDを構築できるんですね。今度実験してみよう。

最後にrt-testsrtカーネルのリアルタイム性能テスト(cyclictest)を読んだ。要はcyclictestが含まれているみたい。

⑤crda、iw、rfkill、wireless-regdb、i2c-tools、tuna

次にsoftware。ボリューム大きいので、だいぶ消化不良を起こしそう。networkのcrdaiwrfkillwireless-regdbあたりは無線LAN通信に深くかかわるモジュール。i2c-toolsはI2Cデバイスを扱うために重要。tunaはチューニング関連。

crdaiwrfkillwireless-regdbは所謂Linux Wireless一派でありLinux WirelessのDocumentationに詳しく書いてある。

crda。下に出てくるwireless-regdbを呼び出すエージェント。nl80211を前提として動作するみたい。

(原文)
Central Regulatory Domain Agent
CRDA acts as the udev helper for communication between the kernel and userspace for regulatory compliance. It relies on nl80211 for communication. CRDA is intended to be run only through udev communication from the kernel. The user should never have to run it manually except if debugging udev issues.

(和訳)
中央規制ドメインエージェント
CRDAは、規制順守のためにカーネルとユーザースペースの間の通信のためのudevヘルパーとして機能します。 それはコミュニケーションのためにnl80211に頼ります。 CRDAはカーネルからのudev通信を通してのみ実行されることを意図しています。 udevの問題をデバッグする場合を除いて、ユーザーは手動で実行する必要はありません。

iw。無線制御コマンド。Wireless Extensionという古い規格に準拠するiwconfig系は推奨されておらず、nl80211系のiwが推奨されてる。

(原文)
iw is a new nl80211 based CLI configuration utility for wireless devices. It supports all new drivers that have been added to the kernel recently. The old tool iwconfig, which uses Wireless Extensions interface, is deprecated and it's strongly recommended to switch to iw and nl80211.
Like the rest of the Linux kernel, iw is still under development. Features are added 'as we go'. The only documentation for iw is this page and output from 'iw help'. Please help expand this page.
There is a page listing use cases with iwconfig and iw: replacing iwconfig.

(和訳)
iwは、ワイヤレスデバイス用の新しいnl80211ベースのCLI設定ユーティリティです。 最近カーネルに追加されたすべての新しいドライバをサポートします。 Wireless Extensionsインタフェースを使用する古いツールiwconfigは推奨されていません。iwとnl80211に切り替えることを強くお勧めします。
Linuxカーネルの他の部分と同様に、iwはまだ開発中です。 機能は「進むにつれて」追加されます。 iwの唯一のドキュメントはこのページと 'iw help'からの出力です。 このページを広げるのを手伝ってください。
iwconfigとiwのユースケースをリストしたページがあります。iwconfigを置き換えるものです。

rfkill。要は無線をOFFにするスイッチ。

(原文)
rfkill is a small userspace tool to query the state of the rfkill switches, buttons and subsystem interfaces. Some devices come with a hard switch that lets you kill different types of RF radios: 802.11 / Bluetooth / NFC / UWB / WAN / WIMAX / FM. Some times these buttons may kill more than one RF type. The Linux kernel rfkill subsystem exposes these hardware buttons and lets userspace query its status and set its status through a /dev/rfkill. Given that at times some RF devices do not have hardware rfkill buttons rfkill the Linux kernel also exposes software rfkill capabilities that allows userspace to mimic a hardware rfkill event and turn on or off RF.

(和訳)
rfkillは、rfkillのスイッチ、ボタン、およびサブシステムインタフェースの状態を問い合わせるための小さなユーザースペースツールです。 802.11 / Bluetooth / NFC / UWB / WAN / WIMAX / FMなど、一部のデバイスには、さまざまな種類のRF無線を停止できるハードスイッチが付属しています。 時々これらのボタンは複数のRFタイプを殺すかもしれません。 Linuxカーネルのrfkillサブシステムは、これらのハードウェアボタンを公開し、ユーザースペースにそのステータスの照会と/ dev / rfkillによるステータスの設定を許可します。 時にはいくつかのRFデバイスがハードウェアrfkillボタンrfkillを持っていないことを考えると、Linuxカーネルはユーザースペースがハードウェアrfkillイベントを模倣しRFをオンまたはオフにすることを可能にするソフトウェアrfkill機能も公開します。

wireless-regdb。要は各国の無線法要求に従い利用可能な周波数などを定義したデータベース。CRDAから呼ばれる。

次にi2c-toolsI2C Toolsを読んだ。更にPackage i2c-toolsを読むとこんなコマンドがサポートされていることがわかる。

次にtunaRed Hat Enterprise MRG 1.3 Tuna User Guideをざっと読んだ。システムをレビューし、CPU、IRQ、Taskなどをチューニングできたり、Cyclic Testというのを実行してオシロスコープ状に性能表示できるみたい。

理解が浅い項目を残しておくとまた分からなくなるので、調べておいてよかった。

GITを調べる

HTTP、GIT、RSYNCと書いてあるリンクのうち、GITを調べてみる。開くとこんな感じ。/pub/scm/xxxという感じにカテゴライズされなってる。scmとはソフトウェア構成管理(software configuration management)の略ですね。前回調べたHTTPは数年前から更新が止まっており、GITがソフトウェア管理のリポジトリになってるみたい。

①全体像

HTTPには存在しないvirt(仮想化)とpublic-inbox(メーリングリスト)が気になる。

pub/scm/bluetooth
pub/scm/boot
pub/scm/devel
pub/scm/docs
pub/scm/editors
pub/scm/fs
pub/scm/git
pub/scm/java
pub/scm/libs
pub/scm/linux
pub/scm/network
pub/scm/public-inbox
pub/scm/utils
pub/scm/virt

ちなみにpublic-inboxとはメールをGIT管理するソフトウェアだそうだ。

https://public-inbox.org/
メーリングリスト管理ソフトウェア
ウェブページ、Atomフィード、NNTPで読むことができる
Git、Unicorn、kgioなんかのメーリングリストで使われている
メールをGit管理している
OSS
AGPL

②コンポーネント毎の詳細

まず、/pub/scm/bluetoothにあるbluez.gitを見てみた。about, summary, refs, log, tree, commit, diff, stats, homepageのタブに分かれている。最初に表示されるのはsummaryタブ。

about

概要が書かれたタブ。ライセンサー、コンパイル&インストール方法、コンフィグ&オプションなどが書かれてる。

summary

branch, tag, age, cloneの4パートに分かれている。branchはgitのブランチ。bluezは1つだが複数あるものも多い。詳しくは3.1 Git のブランチ機能 - ブランチとはなどを参照。tagはgitのtag。目印みたいなもの。詳しくはgit tagの使い方まとめなどを参照。

ageはどのぐらい前にコミットされたのか。

cloneのアドレスを指定してgit cloneする。

refsはbranchとtagの詳細。

logはageの詳細。

treeはコンポーネントのディレクトリ・ファイル構成。ls -lみたいな感じ。

ファイル毎のlogstatを見れる。plainを押すと行番号などの装飾がないプレーンテキストが見れる。

commitはコミットのログとdiffの内容が見れる。

diffはDiffstatとdiff詳細が見れる。

commitタブdiffタブの画面右端にあるdiff optioncontextを増やしていくと、diff行の前後の行数を指定できる。例えば3を指定するとトータル7行(前3+diff行+後3)の表示になる。spaceは空白を含む(include)、含まない(ignore)を指定できるようだがイマイチ効果が分からなかった。modeをunifiedにするとunfied形式でdiffが見れる。ssdiffにするとWinMergeみたいに左右のペインでコード比較。stat onlyはstatの情報のみ表示。

statsは週毎にどのautherが何回コミットしたのかのサマリーが見れる。競争心の強い人はこの数字を見て燃えてくるかもしれない。

homepageはコンポーネントのホームページがあれば表示されるみたい。例えばBluetoothのbluezはこんな感じ。

他のコンポーネントも似たようなものなので、詳細は割愛(強いて言えばvirtとpublic-inboxはHTTPに無かったのでいつか調べたい)。

RSYNCを調べる

①そもそもrsyncって何だ?

まずThe Linux Kernel ArchiveのTOPページのRSYNCにはrsync://rsync.kernel.org/pub/というアドレスが書いてある。rsyncはプロトコルであろう。【 rsync 】コマンド(その1)――ファイルやディレクトリを同期するを読んでみた。

「rsync」は、リモート環境とファイルやディレクトリを「同期(sync)する」というコマンドです。ローカル環境のみでも使用できます。「変更があった分だけ更新する」という機能があるので、ディレクトリ単位のバックアップで特に便利に使えます。

なるほど。差分バックアップのやつだ。

更にrsyncのサンプル例集を調べてみた。スラッシュのあるなしで同期対象が変わるらしい。これWindowsのバックアップツールで見たことがあるが、FastCopy ver 3.82はrsync的な動作をしてるのだと思う。

FastCopy ver 3.82

主要機能
Windows系最速(?) のファイルコピー&バックアップ&削除ツールです。
UNICODE でしか表現できないファイル名やMAX_PATH(260文字) を越えたファイルもコピー(&削除)できます。
Read/Write/ベリファイ別スレッド動作&非同期I/O&ダイレクトI/Oにより、デバイスの限界に近いパフォーマンスを出します。
Include/Exclude フィルタ(UNIXワイルドカード形式)が指定可能です。
MFC 等のフレームワークを使わず、Win32API だけで作っていますので、軽量&コンパクト&軽快に動作します。

rsyncを使いこなすと色々便利そう。そのうち調べてみよう。

scpコマンド

【 scp 】コマンド――リモートマシンとの間でファイルをコピーするを読んだ。いくつかコマンド打ち込んだがエラー発生。ちょっとメンドクサイ感じだし、横道に逸れた調査なので今回はパス(次回試してみたいネタではある)。

①まずは調べる

scpコマンドを使ってリモートにファイルを転送したいを読んだ。まず漢字は避けるべきらしい。

Windowsコマンドプロンプトで、WindowsからLinuxに転送するにはこんな感じ。

 command
>scp C:\test\xxx.txt pavement1234@192.168.---.---:/home/pavement1234/xxx.txt
pavement1234@192.168.---.---'s password:
xxx.txt 100% 7 0.0KB/s 00:00

Windowsコマンドプロンプトで、LinuxからWindowsに転送するにはこんな感じ。

 command
>scp pavement1234@192.168.100.140:/home/pavement1234/yyy.txt C:\test\yyy.txt
pavement1234@192.168.100.140's password:
yyy.txt 100% 9 0.0KB/s 00:00

LinuxからWindowsにscp接続することも考えたが、そもそもWindows側にscp接続の準備ができてないことに思い至った。Windowsにsshd、sftp-serverの実行環境を構築するを読むとWindows側にsshdを立てる必要がある。なんかWindows側に凝った環境を構築することにあまり興味が湧かなかったのでパスしようと思う。

TeraTermでLinuxからWindowsにファイル転送

TeraTermで効率良くファイル転送を読んだところ、WindowsからLinuxにファイル転送する場合、TeraTermウィンドウにファイルをドラッグ&ドロップすればよいみたい。(LinuxからWindowsにファイル転送する方法も書いてあった。これも次回ネタ。)

①TeraTermでWindows→Linuxにファイル転送(ドラッグ&ドロップ)

WindowsからLinuxにTeraTermでSSH接続します。

TeraTerm画面にファイルをドラッグ&ドロップすると、以下のダイアログが出ます。SCPのラジオボタンをONにし、送信先のディレクトリを指定し(以下はカレントディレクトリを示すチルダ”~”を指定した)、「OK」を押すとファイルが転送されます。

②TeraTermでWindows→Linuxにファイル転送(SSH SCP)

TeraTermのメニューから「ファイル」→「SSH SCP」を指定する。

画面上半分の「From」にWindowsのファイル名を指定。「To」にLinuxのディレクトリ名を指定。「Send」を押すとファイルが転送されます。

③TeraTermでLinux→Windowsにファイル転送(SSH SCP)

今回の本命です。TeraTermのメニューから「ファイル」→「SSH SCP」を指定する。

画面下半分の「From」にLinuxのファイル名を指定。「To」にWindowsのフォルダ名を指定。

「Receive」を押すとファイルが転送されます。

apt

・aptはapt-getとapt-cacheの統合を目指したコマンドである。
・apt dist-upgradeは新規パッケージをインストールする場合がある。既存パッケージを削除する場合がある。
・apt upgradeは新規パッケージをインストールする場合がある。既存パッケージは削除しない。
・apt-get upgradeは新規パッケージをインストールしない。既存パッケージも削除しない。
・基本的にはapt upgradeを使うのが良い。
・aptの高速化版apt-fastがある。GitHubでソースを入手できる。
・Ubuntu/Debianのパッケージファイル(*.deb)をインストール、削除したりできる。

 

コマンド 内容
sudo apt update リポジトリ一覧を更新(リポジトリ追加・削除時には必ず実行すること)
sudo apt upgrade パッケージを更新(通常のパッケージ更新時はこのコマンドを使用する)
sudo apt full-upgrade パッケージを更新(保留されているパッケージを更新するときに使用する)
sudo apt autoremove 更新に伴い必要なくなったパッケージを削除(apt実行時にこのコマンドを実行するよう表示されたら実行する)
sudo apt install {パッケージ名やdebファイルのパス} パッケージやdebファイルをインストール
sudo apt remove {パッケージ名} パッケージを削除
sudo apt remove --purge {パッケージ名} パッケージを完全削除
sudo apt show {パッケージ名} パッケージの詳細情報を表示
sudo apt list {パッケージ名} パッケージを検索(完全一致)
sudo apt search {パッケージ名} パッケージを検索(部分一致)
sudo dpkg -l インストール済みのパッケージ一覧を表示
sudo dpkg -L {パッケージ名} パッケージのインストール先を表示
cat /var/log/apt/history.log aptコマンドの使用履歴を表示
sudo apt autoclean キャッシュされているが、インストールはされていないdebファイルを削除
sudo apt clean キャッシュされている全てのdebファイルを削除
apt moo Super Cow Powersを発動。スーパー牛さんパワー。イースターエッグ。
echo "{パッケージ名} hold" | dpkg --set-selections パッケージをアップデート対象から除外
echo "{パッケージ名} install" | dpkg --set-selections パッケージをアップデート対象に戻す

カーネルコンフィギュレーションを変更したい

①まず.configをバックアップした

元の設定に戻せるようにバックアップ。

 command
$ cd /usr/src/linux-3.14.79
$ cp .config .config_backup

②階層を掘ってみる

まずカーネルコンフィギュレーションメニューを開く。

 command
$ cd /usr/src/linux-3.14.79
$ make menuconfig

初回メニュー構築に時間がかかりますが、2回目以降は瞬時に開きます。

画面上部にメニューの設定方法が書いてあります。

Arrow keys navigate the menu.

<Enter> selects submenus ---> (or empty submenus ----).

Highlighted letters are hotkeys.

Pressing
<Y> includes,
<N> excludes,
<M> modularizes features.
Press
<Esc><Esc> to exit,
<?> for Help,
</> for Search.  これ結構便利

Legend:
[*] built-in [ ] <M> module
< > module capable

例えば、64-bit kernelが選択された状態で ? を入力すると、コンフィギュレーションの詳細情報が見れます。

そして、いつかやりたいと思っていたカーネルコンフィギュレーションの階層を全て見るをやってみました。networkとdriverが想像を超える量でした。

③カーネルコンフィギュレーションを変更してみる

色々変えるのは、そのうち試すとして、今回は2箇所変更して保存する手順をやってみます。

先ほどと同様にカーネルコンフィギュレーションメニューを開く。

 command
$ cd /usr/src/linux-3.14.79
$ make menuconfig

先頭の[*] 64-bit kernelを選択した状態でスペースを押すと…。

[ ] 64-bit kernelという具合に選択が解除される。

次に< > Intel System On Chip IOSF Sideband supportを選択した状態でスペースを1回押すと…。 <M> Intel System On Chip IOSF Sideband supportという具合にローダブルモジュールになる。もう1回スペースを押すと…。 <*> Intel System On Chip IOSF Sideband supportになる。 右を押して<Exit>にカーソルを合わせ、エンターキーを押すと…。 保存するか聞いてくるので<Yes>にカーソルが合った状態でエンターを押す。 コンソールに戻る(make menuconfigから抜ける)。

今保存した.config.config_backupを比較すると、CONFIG_64BITがOFFになりCONFIG_X86_32がyになるなど、色々変更されていることがわかる。

$ diff .config .config_backup
5,6c5,6
< # CONFIG_64BIT is not set
< CONFIG_X86_32=y
---
> CONFIG_64BIT=y
> CONFIG_X86_64=y
9,10c9,10
< CONFIG_OUTPUT_FORMAT="elf32-i386"
< CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
---
> CONFIG_OUTPUT_FORMAT="elf64-x86-64"
> CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
18a19
> CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
33,34c34,35
< # CONFIG_ZONE_DMA32 is not set
< # CONFIG_AUDIT_ARCH is not set
(以下略)

 

カーネルコンフィギュレーションの変更を元に戻すため、バックアップファイルを復元して終わりました。

カーネルのMakefileを開いてみる

make installなどmakeのオプションをもっと調べたいと考え、カーネルソースコードに含まれるMakefileを開いてみた、

1490行もあり全部を真剣に見るのはツライので、HELPを表示してみた。こまったらコレを見ればいいな。

$ make help
Cleaning targets:
clean - Remove most generated files but keep the config and
enough build support to build external modules
mrproper - Remove all generated files + config + various backup files
distclean - mrproper + remove editor backup and patch files

Configuration targets:
config - Update current config utilising a line-oriented program
nconfig - Update current config utilising a ncurses menu based program
menuconfig - Update current config utilising a menu based program
xconfig - Update current config utilising a QT based front-end
gconfig - Update current config utilising a GTK based front-end
oldconfig - Update current config utilising a provided .config as base
localmodconfig - Update current config disabling modules not loaded
localyesconfig - Update current config converting local mods to core
silentoldconfig - Same as oldconfig, but quietly, additionally update deps
defconfig - New config with default from ARCH supplied defconfig
savedefconfig - Save current config as ./defconfig (minimal config)
allnoconfig - New config where all options are answered with no
allyesconfig - New config where all options are accepted with yes
allmodconfig - New config selecting modules when possible
alldefconfig - New config with all symbols set to default
randconfig - New config with random answer to all options
listnewconfig - List new options
olddefconfig - Same as silentoldconfig but sets new symbols to their default value

Other generic targets:
all - Build all targets marked with [*] * vmlinux - Build the bare kernel
* modules - Build all modules
modules_install - Install all modules to INSTALL_MOD_PATH (default: /)
firmware_install- Install all firmware to INSTALL_FW_PATH
(default: $(INSTALL_MOD_PATH)/lib/firmware)
dir/ - Build all files in dir and below
dir/file.[oisS] - Build specified target only
dir/file.lst - Build specified mixed source/assembly target only
(requires a recent binutils and recent build (System.map))
dir/file.ko - Build module including final link
modules_prepare - Set up for building external modules
tags/TAGS - Generate tags file for editors
cscope - Generate cscope index
gtags - Generate GNU GLOBAL index
kernelrelease - Output the release version string
kernelversion - Output the version stored in Makefile
image_name - Output the image name
headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH
(default: /usr/src/linux-3.14.79/usr)

Static analysers
checkstack - Generate a list of stack hogs
namespacecheck - Name space analysis on compiled kernel
versioncheck - Sanity check on version.h usage
includecheck - Check for duplicate included header files
export_report - List the usages of all exported symbols
headers_check - Sanity check on exported headers
headerdep - Detect inclusion cycles in headers
coccicheck - Check with Coccinelle.

Kernel packaging:
rpm-pkg - Build both source and binary RPM kernel packages
binrpm-pkg - Build only the binary kernel package
deb-pkg - Build the kernel as a deb package
tar-pkg - Build the kernel as an uncompressed tarball
targz-pkg - Build the kernel as a gzip compressed tarball
tarbz2-pkg - Build the kernel as a bzip2 compressed tarball
tarxz-pkg - Build the kernel as a xz compressed tarball
perf-tar-src-pkg - Build perf-3.14.79.tar source tarball
perf-targz-src-pkg - Build perf-3.14.79.tar.gz source tarball
perf-tarbz2-src-pkg - Build perf-3.14.79.tar.bz2 source tarball
perf-tarxz-src-pkg - Build perf-3.14.79.tar.xz source tarball

Documentation targets:
Linux kernel internal documentation in different formats:
htmldocs - HTML
pdfdocs - PDF
psdocs - Postscript
xmldocs - XML DocBook
mandocs - man pages
installmandocs - install man pages generated by mandocs
cleandocs - clean all generated DocBook files

Architecture specific targets (x86):
* bzImage - Compressed kernel image (arch/x86/boot/bzImage)
install - Install kernel using
(your) ~/bin/installkernel or
(distribution) /sbin/installkernel or
install to $(INSTALL_PATH) and run lilo
fdimage - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)
fdimage144 - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)
fdimage288 - Create 2.8MB boot floppy image (arch/x86/boot/fdimage)
isoimage - Create a boot CD-ROM image (arch/x86/boot/image.iso)
bzdisk/fdimage*/isoimage also accept:
FDARGS="..." arguments for the booted kernel
FDINITRD=file initrd for the booted kernel
kvmconfig - Enable additional options for guest kernel support

i386_defconfig - Build for i386
x86_64_defconfig - Build for x86_64

make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build
make V=2 [targets] 2 => give reason for rebuild of target
make O=dir [targets] Locate all output files in "dir", including .config
make C=1 [targets] Check all c source with $CHECK (sparse by default)
make C=2 [targets] Force check of all c source with $CHECK
make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections
make W=n [targets] Enable extra gcc checks, n=1,2,3 where
1: warnings which may be relevant and do not occur too often
2: warnings which occur quite often but may still be relevant
3: more obscure warnings, can most likely be ignored
Multiple levels can be combined with W=12 or W=123

Execute "make" or "make all" to build all targets marked with [*] For further info see the ./README file

 

make-kpkg

本編でmake-kpkgを結局つかわなかったので、make-kpkgでビルドを試してみた。

①make-kpkgって何だっけ?

make-kpkgが何だったのかスッカリ忘れてしまいました。Ubuntu で kernel をソースコードからビルドする (make-kpkg 編) を読みようやく思い出しました。そうだカーネルイメージをdebパッケージ化する方法だ。

こんな感じでビルドするみたい。

 command
$ sudo make-kpkg --initrd kernel_image kernel_headers

ビルド完了。カーネルイメージとカーネルヘッダが出来ました。

 command
$ ls ../*.deb
linux-headers-3.14.79_3.14.79-10.00.Custom_amd64.deb
inux-image-3.14.79_3.14.79-10.00.Custom_amd64.deb

②make deb-pkgとの比較

本編で実施したmake deb-pkgで生成される①~⑤のうち、make-kpkgでは①②が生成されました。

①カーネルイメージと関連モジュールを含む linux-image-version、
②外部モジュールのビルドに必要なヘッダファイルを含む linux-headers-version、
③一部のドライバから要求されるファームウェアファイルを含む linux-firmware-image-version (Debian の配布しているカーネルソースからカーネルをビルドする場合、このパッケージは生成されないかもしれません)、
④カーネルイメージとモジュールのデバッグシンボルを含む linux-image-version-dbg、
⑤GNU glibc などのユーザ空間ライブラリに関連するヘッダを含む linux-libc-dev

make deb-pkgを覚えてしまったのでmake-kpkgを使うことは無さそうですが、1度試せたので満足です。

カーネルパッケージ(*.deb)

imageのdebパッケージをdpkgでインストールしたが、firmware、headers、デバッグシンボルを含むimage、linux-libc-devを調べたい。

debパッケージの中身を見るにはどうすればよいか

本編でカーネルビルドを実施すると、/usr/srcにdebパッケージが5つ生成されます。

linux-firmware-image-3.14.79-pavement1234_3.14.79-1_amd64.deb ③
linux-headers-3.14.79-pavement1234_3.14.79-1_amd64.deb ②
linux-image-3.14.79-pavement1234-dbg_3.14.79-1_amd64.deb ④
linux-image-3.14.79-pavement1234_3.14.79-1_amd64.deb ①
linux-libc-dev_3.14.79-1_amd64.deb ⑤

debパッケージの展開を読み、debの展開方法を知る。

①カーネルイメージ

 command
$ sudo ar vx linux-image-3.14.79-pavement1234_3.14.79-1_amd64.deb
x - debian-binary テキストファイル。中に2.0と書いてある。
x - control.tar.gz
x - data.tar.xz

control.tar.gzを展開。

 command
$ sudo tar xvf control.tar.gz
./
./postrm
./control
./prerm
./postinst
./preinst
./md5sums

data.tar.xzを展開。

 command
$ sudo tar xvf data.tar.xz
./
./lib/
./lib/modules/
./lib/modules/3.14.79-pavement1234/
./lib/modules/3.14.79-pavement1234/modules.builtin.bin
./lib/modules/3.14.79-pavement1234/modules.dep
./lib/modules/3.14.79-pavement1234/modules.symbols
./lib/modules/3.14.79-pavement1234/modules.softdep
./lib/modules/3.14.79-pavement1234/modules.symbols.bin
./lib/modules/3.14.79-pavement1234/modules.devname
./lib/modules/3.14.79-pavement1234/modules.order
./lib/modules/3.14.79-pavement1234/kernel/
(途中省略)
./lib/modules/3.14.79-pavement1234/modules.alias.bin
./lib/modules/3.14.79-pavement1234/modules.alias
./lib/modules/3.14.79-pavement1234/modules.builtin
./lib/modules/3.14.79-pavement1234/modules.dep.bin
./etc/
./etc/kernel/
./etc/kernel/prerm.d/
./etc/kernel/preinst.d/
./etc/kernel/postinst.d/
./etc/kernel/postrm.d/
./usr/
./usr/share/
./usr/share/doc/
./usr/share/doc/linux-image-3.14.79-pavement1234/
./usr/share/doc/linux-image-3.14.79-pavement1234/copyright
./usr/share/doc/linux-image-3.14.79-pavement1234/changelog.Debian.gz
./boot/
./boot/vmlinuz-3.14.79-pavement1234
./boot/config-3.14.79-pavement1234
./boot/System.map-3.14.79-pavement1234

②カーネルヘッダー

かならずこの3ファイルが展開されるのね。

 command
$ sudo ar vx linux-headers-3.14.79-pavement1234_3.14.79-1_amd64.deb
x - debian-binary テキストファイル。中に2.0と書いてある。
x - control.tar.gz
x - data.tar.xz

control.tar.gzを展開。

 command
$ sudo tar xvf control.tar.gz
./
./control
./md5sums

data.tar.xzを展開。

 command
$ sudo tar xvf data.tar.xz
./
./lib/
./lib/modules/
./lib/modules/3.14.79-pavement1234/
./usr/
./usr/src/
./usr/src/linux-headers-3.14.79-pavement1234/
./usr/src/linux-headers-3.14.79-pavement1234/tools/
(途中省略)
./usr/share/
./usr/share/doc/
./usr/share/doc/linux-headers-3.14.79-pavement1234/
./usr/share/doc/linux-headers-3.14.79-pavement1234/copyright
./usr/share/doc/linux-headers-3.14.79-pavement1234/changelog.Debian.gz
./lib/modules/3.14.79-pavement1234/build

③ファームウェア

 command
$ sudo ar vx linux-headers-3.14.79-pavement1234_3.14.79-1_amd64.deb
x - debian-binary テキストファイル。中に2.0と書いてある。
x - control.tar.gz
x - data.tar.xz

control.tar.gzを展開(②と同じ)。

 command
 

data.tar.xzを展開。

 command
$ sudo tar xvf data.tar.xz
./
./lib/
./lib/firmware/
./lib/firmware/3.14.79-pavement1234/
./lib/firmware/3.14.79-pavement1234/yamaha/
(途中省略)
./usr/
./usr/share/
./usr/share/doc/
./usr/share/doc/linux-firmware-image-3.14.79-pavement1234/
./usr/share/doc/linux-firmware-image-3.14.79-pavement1234/copyright
./usr/share/doc/linux-firmware-image-3.14.79-pavement1234/changelog.Debian.g

④デバッグ版カーネルイメージ

 command
$ sudo ar vx linux-image-3.14.79-pavement1234-dbg_3.14.79-1_amd64.deb
x - debian-binary テキストファイル。中に2.0と書いてある。
x - control.tar.gz
x - data.tar.xz

control.tar.gzを展開(③と同じ)。

 command
$ sudo tar xvf control.tar.gz
./
./control
./md5sums

data.tar.xzを展開

 command
$ sudo tar xvf data.tar.xz
./
./usr/
./usr/lib/
./usr/lib/debug/
./usr/lib/debug/lib/
./usr/lib/debug/lib/modules/
./usr/lib/debug/lib/modules/3.14.79-pavement1234/
./usr/lib/debug/lib/modules/3.14.79-pavement1234/kernel/
./usr/lib/debug/lib/modules/3.14.79-pavement1234/kernel/sound/
(途中省略)
./usr/lib/debug/lib/modules/3.14.79-pavement1234/vmlinux
./usr/lib/debug/boot/
./usr/share/
./usr/share/doc/
./usr/share/doc/linux-image-3.14.79-pavement1234-dbg/
./usr/share/doc/linux-image-3.14.79-pavement1234-dbg/copyright
./usr/share/doc/linux-image-3.14.79-pavement1234-dbg/changelog.Debian.gz
./usr/lib/debug/vmlinux-3.14.79-pavement1234
./usr/lib/debug/boot/vmlinux-3.14.79-pavement1234

⑤Cランタイム

 command
$ sudo ar vx linux-libc-dev_3.14.79-1_amd64.deb
x - debian-binary テキストファイル。中に2.0と書いてある。
x - control.tar.gz
x - data.tar.xz

control.tar.gzを展開。

 command
$ sudo tar xvf control.tar.gz
./
./control
./md5sums

data.tar.xzを展開。

 command
$ sudo tar xvf data.tar.xz
./
./usr/
./usr/include/
./usr/include/sound/
(途中省略)
./usr/share/
./usr/share/doc/
./usr/share/doc/linux-libc-dev/
./usr/share/doc/linux-libc-dev/copyright
./usr/share/doc/linux-libc-dev/changelog.Debian.gz

取り急ぎ展開できた。/lib/modules、/etc、/usr/share、/usr/lib、/lib/firmware、/usr/srcに展開されるようだ。困ったらここを見てデバッグしよう。

debパッケージ作成方法

debパッケージ作成方法をステップバイステップでまとめましたに、debパッケージの作り方が書いてある。これを読むことで、make deb-pkgで生成されたパッケージがどうやって作られているかわかるに違いない。近々debパッケージを作ってみようと思う。

/boot

/bootの中にインストールされたinitrdとか、複数あるvmlinuzから3.14.79版がどう選ばれるのかを調べたい。

①/bootにインストールされたイメージは、どうやって選ばれるのか?

Linuxがブートするまでを読んだ。/boot/grub/menu.lstに起動するOSが書いてあるとあるが、そんなファイルはない。私のLinux(Ubuntu14 )とは環境が異なるっぽい。

システムの起動Linuxのブートシーケンスの基礎まとめを読んだ。うーん...。これも違うな。

8.11. カーネルのインストールを読んだ。コレ当たりかも?

8.11.1. Debian カーネルパッケージの特徴
Debian カーネルパッケージはカーネルイメージ (vmlinuz-version) をインストールします。カーネルの設定 (config-version) とシンボルテーブル (System.map-version) は /boot/ に置かれます。シンボルテーブルは開発者がカーネルエラーメッセージの意味を理解する際の手助けになります。それどころかシンボルテーブルがなければ、カーネルの「oops」(「oops」とはカーネル空間で起こるユーザ空間プログラムのセグメンテーション違反に相当するエラーです。言い換えれば、不正なポインタを参照して値を取得したことで生成されるメッセージです) に含まれる情報は、数字で表したメモリアドレスだけになります。アドレスとシンボルや関数名を対応付けるテーブルがなければ、この情報は役に立ちません。モジュールは /lib/modules/version/ ディレクトリにインストールされます。
カーネルパッケージの設定スクリプトは自動的に initrd イメージを生成します。initrd はブートローダによってメモリに読み込まれる小さなシステムで (このため「init RAM ディスク」と名付けられています)、Linux カーネルは initrd を使って完全な Debian システムを含むデバイス (たとえば SATA ディスクのドライバ) にアクセスするために必要なモジュールを読み込みます。最後に、カーネルパッケージの post-installation スクリプトが /vmlinuz、/vmlinuz.old、/initrd.img、/initrd.img.old のシンボリックリンクを更新します。これらはそれぞれインストールされた最新の 2 つのカーネルとカーネルに対応する initrd イメージを指します。
これらの作業のほとんどは /etc/kernel/*.d/ ディレクトリの中にあるフックスクリプトが担っています。たとえば、grub との統合は、カーネルがインストールまたは削除された際に update-grub を呼び出す /etc/kernel/postinst.d/zz-update-grub と /etc/kernel/postrm.d/zz-update-grub が担っています。

カーネルインストール後、/etc/kernel/postinst.d/zz-update.grub、/etc/kernel/postrm.d/zz-update.grub、というスクリプトが/vmlinuz、/vmlinuz.old、/initrd.img、initrd.img.oldというシンボリックリンクを更新するとのこと。早速、ルートディレクトリをls -lしてみたが、リンクは古いままだった(3.13.0-24のまま)。ハズレ。

 command
$ ls -l /
合計 101
drwxr-xr-x 2 root root 4096 2月 17 2019 bin
drwxr-xr-x 5 root root 1024 8月 30 04:22 boot
drwxrwxr-x 2 root root 4096 2月 17 2019 cdrom
drwxr-xr-x 19 root root 4200 8月 27 23:03 dev
drwxr-xr-x 144 root root 12288 8月 27 23:03 etc
drwxr-xr-x 3 root root 4096 2月 17 2019 home
lrwxrwxrwx 1 root root 33 2月 17 2019 initrd.img -> boot/initrd.img-3.13.0-24-generic
lrwxrwxrwx 1 root root 33 2月 17 2019 initrd.img.old -> boot/initrd.img-3.13.0-24-generic
drwxr-xr-x 23 root root 4096 2月 17 2019 lib
drwxr-xr-x 2 root root 4096 2月 17 2019 lib32
drwxr-xr-x 2 root root 4096 2月 17 2019 lib64
drwxr-xr-x 2 root root 4096 2月 17 2019 libx32
drwx------ 2 root root 16384 2月 17 2019 lost+found
drwxr-xr-x 2 root root 4096 4月 19 2014 media
drwxr-xr-x 2 root root 4096 4月 11 2014 mnt
drwxr-xr-x 4 root root 4096 2月 24 2019 opt
dr-xr-xr-x 149 root root 0 8月 27 23:03 proc
drwx------ 2 root root 4096 2月 17 2019 root
drwxr-xr-x 24 root root 820 8月 30 04:12 run
drwxr-xr-x 2 root root 12288 2月 17 2019 sbin
drwxr-xr-x 2 root root 4096 4月 19 2014 srv
dr-xr-xr-x 13 root root 0 8月 30 04:23 sys
drwxrwxrwt 4 root root 4096 8月 30 04:17 tmp
drwxr-xr-x 12 root root 4096 2月 17 2019 usr
drwxr-xr-x 13 root root 4096 4月 22 2014 var
lrwxrwxrwx 1 root root 30 2月 17 2019 vmlinuz -> boot/vmlinuz-3.13.0-24-generic

よくわかんないので、/bootの下をpavement1234でgrepしてみることに。まずは1階層目(/boot/*)をgrepしたらたいした情報得られず。

 command
$ sudo grep pavement1234 /boot/*
grep: /boot/efi: ディレクトリです
grep: /boot/grub: ディレクトリです
grep: /boot/lost+found: ディレクトリです
バイナリファイル /boot/vmlinuz-3.14.79-pavement1234 に一致しました

次に2階層目(/boot/*/*)をチェック。/boot/glub/grub.cfgにpavement1234の記載が沢山みつかった。私がちゃんとチェックできてなかっただけですね。

 command
$ sudo grep pavement1234 /boot/*/*
grep: /boot/efi/EFI: ディレクトリです
grep: /boot/grub/fonts: ディレクトリです
/boot/grub/grub.cfg: linux /vmlinuz-3.14.79-pavement1234 root=/dev/mapper/ubuntu--vg-root ro quiet splash $vt_handoff
/boot/grub/grub.cfg: initrd /initrd.img-3.14.79-pavement1234
/boot/grub/grub.cfg: menuentry 'Ubuntu, with Linux 3.14.79-pavement1234' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-3.14.79-pavement1234-advanced-e949b89d-bd34-49f2-8e9e-742e7ff1d2df' {
/boot/grub/grub.cfg: echo 'Linux 3.14.79-pavement1234 をロード中...'
/boot/grub/grub.cfg: linux /vmlinuz-3.14.79-pavement1234 root=/dev/mapper/ubuntu--vg-root ro quiet splash $vt_handoff
/boot/grub/grub.cfg: initrd /initrd.img-3.14.79-pavement1234
/boot/grub/grub.cfg: menuentry 'Ubuntu, with Linux 3.14.79-pavement1234 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-3.14.79-pavement1234-recovery-e949b89d-bd34-49f2-8e9e-742e7ff1d2df' {
/boot/grub/grub.cfg: echo 'Linux 3.14.79-pavement1234 をロード中...'
/boot/grub/grub.cfg: linux /vmlinuz-3.14.79-pavement1234 root=/dev/mapper/ubuntu--vg-root ro recovery nomodeset
/boot/grub/grub.cfg: initrd /initrd.img-3.14.79-pavement1234
grep: /boot/grub/locale: ディレクトリです
grep: /boot/grub/x86_64-efi: ディレクトリです

/boot/grub/grub.cfgを開いてみた。DO NOT EDIT THIS FILEと書いてある。grub-mkconfigが自動生成するからいじるなと。取り急ぎvmlinuz-3.14.79-pavement1234、initrd.img-3.14.79-pavement1234を指しているエントリーをにしてみた。他に3.13.0-165、3.13.0-24のエントリーがあった。

 command
$ vi /boot/grub/grub.cfg
 

最後に/boot/grub/grub.cfgの先頭に書いてあったgrub-mkconfigについて調べてみる

上にも書いたが、grub-mkconfigが/boot/grub/grub.cfgを自動生成するようだ。

 command
$ vi /boot/grub/grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

今回のお題 - GRUB を設定する ~ GRUB 2 編を読んだ。詳細は割愛するが、どうもこういうことらしい。

GRUB 2 設定ファイルは/boot/grub/grub.cfgだが、このファイルを直接編集するのではなく/etc/default/grubと/etc/grub.d/にあるファイルに設定を書き、grub-mkconfigに-oオプションを指定して/boot/grub/grug.cfgを出力する。

/etc/default/grub、/etc/grub.d/*をくまなく調べたが、当然ながらpavement1234は直接書かれてなかった。恐らくインストール時に一時的にシェル変数にxxx-pavement1234が設定されgrub-mkconfigが実行されるのだと思う。

 command
$ ls -l /etc/grub.d
合計 76
-rwxr-xr-x 1 root root 9791 1月 17 2019 00_header
-rwxr-xr-x 1 root root 6058 4月 11 2014 05_debian_theme
-rwxr-xr-x 1 root root 11608 4月 11 2014 10_linux
-rwxr-xr-x 1 root root 10412 4月 11 2014 20_linux_xen
-rwxr-xr-x 1 root root 1992 3月 12 2014 20_memtest86+
-rwxr-xr-x 1 root root 11692 4月 11 2014 30_os-prober
-rwxr-xr-x 1 root root 1418 1月 17 2019 30_uefi-firmware
-rwxr-xr-x 1 root root 214 4月 11 2014 40_custom
-rwxr-xr-x 1 root root 216 4月 11 2014 41_custom
-rw-r--r-- 1 root root 483 4月 11 2014 README

/lib/modules/3.14.79-pavement1234/

ドライバのロード順を制御するmodule.orderとか調べたい。

①何はともあれ/lib/modules/3.14.79-pavement1234に行ってみる

/lib/modules/3.14.79-pavement1234/をls -lしてみた。なんかいっぱいあるな…。

 command
$ ls -l /lib/modules/3.14.79-pavement1234/
合計 3832
drwxr-xr-x 10 root root 4096 7月 9 18:22 kernel
-rw-r--r-- 1 root root 947199 7月 9 16:48 modules.alias
-rw-r--r-- 1 root root 930707 7月 9 16:48 modules.alias.bin
-rw-r--r-- 1 root root 7004 7月 9 16:36 modules.builtin
-rw-r--r-- 1 root root 9154 7月 9 16:48 modules.builtin.bin
-rw-r--r-- 1 root root 372523 7月 9 16:48 modules.dep
-rw-r--r-- 1 root root 548545 7月 9 16:48 modules.dep.bin
-rw-r--r-- 1 root root 241 7月 9 16:48 modules.devname
-rw-r--r-- 1 root root 153217 7月 9 16:36 modules.order
-rw-r--r-- 1 root root 160 7月 9 16:48 modules.softdep
-rw-r--r-- 1 root root 412275 7月 9 16:48 modules.symbols
-rw-r--r-- 1 root root 515568 7月 9 16:48 modules.symbols.bin

カーネルモジュールの作り方を読んだ。特にmodules.orderについて触れていなかったが、カーネルモジュールをビルドするMakefileが載ってた。uname -rでカーネルのリリース番号を出力してKDIRを動的生成してる。私のPCでuname -rを打つと3.14.79-pavement1234と出力される。これは便利。

Makefile

obj-m := test.o
KDIR := /lib/modules/$(shell uname -r)/build
VERBOSE = 0

all:
$(MAKE) -C $(KDIR) M=$(PWD) KBUILD_VERBOSE=$(VERBOSE) CONFIG_DEBUG_INFO=y modules
clean:
rm -f *.o *.ko *.mod.c Module.symvers modules.order

とりあえず馴染みがある/lib/modules/3.14.79-pavement1234配下のath10をgrepしてみた。module.alias、modules.dep、modules.order、modules.symbolsがヒット。

 command
$ grep ath10 /lib/modules/3.14.79-pavement1234/*
grep: /lib/modules/3.14.79-pavement1234/kernel: ディレクトリです
/lib/modules/3.14.79-pavement1234/modules.alias:alias pci:v0000168Cd0000003Csv*sd*bc*sc*i* ath10k_pci
バイナリファイル /lib/modules/3.14.79-pavement1234/modules.alias.bin に一致しました
/lib/modules/3.14.79-pavement1234/modules.dep:kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko: kernel/drivers/net/wireless/ath/ath.ko kernel/net/mac80211/mac80211.ko kernel/net/wireless/cfg80211.ko
/lib/modules/3.14.79-pavement1234/modules.dep:kernel/drivers/net/wireless/ath/ath10k/ath10k_pci.ko: kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko kernel/drivers/net/wireless/ath/ath.ko kernel/net/mac80211/mac80211.ko kernel/net/wireless/cfg80211.ko
バイナリファイル /lib/modules/3.14.79-pavement1234/modules.dep.bin に一致しました
/lib/modules/3.14.79-pavement1234/modules.order:kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko
/lib/modules/3.14.79-pavement1234/modules.order:kernel/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_warn ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_start ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_create ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_register ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_destroy ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_info ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_stop ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_core_unregister ath10k_core
/lib/modules/3.14.79-pavement1234/modules.symbols:alias symbol:ath10k_err ath10k_core
バイナリファイル /lib/modules/3.14.79-pavement1234/modules.symbols.bin に一致しました

modules.depは依存関係が書いてあるみたい。行数を出した(viで: set nuした)。

ath10k_pci.ko
+ath10k_core.ko
+ath.ko
+cfg80211.ko
+mac80211.ko
+cfg80211.ko

1047 kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko:: kernel/drivers/net/wireless/ath/ath.ko kernel/net/mac80211/mac80211.ko kernel/net/wireless/cfg80211.ko

1048 kernel/drivers/net/wireless/ath/ath10k/ath10k_pci.ko: kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko kernel/drivers/net/wireless/ath/ath.ko kernel/net/mac80211/mac80211.ko kernel/net/wireless/cfg80211.ko

1050 kernel/drivers/net/wireless/ath/ath.ko: kernel/net/wireless/cfg80211.ko

3785 kernel/net/wireless/cfg80211.ko:

3878 kernel/net/mac80211/mac80211.ko: kernel/net/wireless/cfg80211.ko

modules.orderでこれらがどういう位置関係になっているか見た。依存関係の下層(今回で言うとcfg802.ko)が先に呼ばれるとかではなくて、アルファベット順のように見える。

1048 kernel/drivers/net/wireless/ath/ath10k/ath10k_core.ko
1049 kernel/drivers/net/wireless/ath/ath10k/ath10k_pci.ko

1051 kernel/drivers/net/wireless/ath/ath.ko

3786 kernel/net/wireless/cfg80211.ko

3879 kernel/net/mac80211/mac80211.ko

lsmodで実際にロードされているモジュールをリスト表示でき、依存関係もわかる。私のLinux PCに搭載された無線LANモジュールはIntelなのでiwlwifiが呼ばれてる。

 command
$ lsmod
Module Size Used by
btrfs 880060 0
raid6_pq 97812 1 btrfs
xor 21411 1 btrfs
autofs4 38754 0
ctr 13049 1
ccm 17773 1
arc4 12608 2
rfcomm 69064 8
iwlmvm 194784 0
bnep 19624 2
mac80211 656781 1 iwlmvm
nls_iso8859_1 12713 1
snd_hda_codec_hdmi 46480 1
snd_hda_codec_realtek 65984 1
snd_hda_codec_generic 68348 1 snd_hda_codec_realtek
uvcvideo 80834 0
videobuf2_vmalloc 13216 1 uvcvideo
videobuf2_memops 13362 1 videobuf2_vmalloc
videobuf2_core 41043 1 uvcvideo
videodev 148362 2 uvcvideo,videobuf2_core
keucr 71407 0
hid_multitouch 17407 0
intel_rapl 18773 0
coretemp 13475 0
kvm_intel 143079 0
kvm 463071 1 kvm_intel
iwlwifi 177968 1 iwlmvm
crct10dif_pclmul 14289 0
crc32_pclmul 13113 0
cryptd 20359 0
btusb 28339 0
bluetooth 406881 22 bnep,btusb,rfcomm
joydev 17381 0
6lowpan_iphc 18702 1 bluetooth
serio_raw 13462 0
snd_hda_intel 56531 3
snd_hda_codec 137502 4 snd_hda_codec_realtek,snd_hda_codec_hdmi,snd_hda_codec_generic,snd_hda_intel
snd_hwdep 13602 1 snd_hda_codec
cfg80211 519267 3 iwlwifi,mac80211,iwlmvm
snd_pcm 107781 3 snd_hda_codec_hdmi,snd_hda_codec,snd_hda_intel
snd_seq_midi 13324 0
snd_seq_midi_event 14899 1 snd_seq_midi
snd_rawmidi 30259 1 snd_seq_midi
sparse_keymap 13948 0
toshiba_bluetooth 12852 0
snd_seq 61616 2 snd_seq_midi_event,snd_seq_midi
i915 797368 2
i2c_hid 18661 0
drm_kms_helper 48716 1 i915
snd_seq_device 14497 3 snd_seq,snd_rawmidi,snd_seq_midi
video 19425 1 i915
parport_pc 32701 0
drm 298219 3 i915,drm_kms_helper
dw_dmac 12814 0
dw_dmac_core 24251 1 dw_dmac
mac_hid 13205 0
snd_timer 29481 2 snd_pcm,snd_seq
ppdev 17635 0
i2c_designware_platform 13006 0
i2c_designware_core 14768 1 i2c_designware_platform
snd 69545 18 snd_hda_codec_realtek,snd_hwdep,snd_timer,snd_hda_codec_hdmi,snd_pcm,snd_seq,snd_rawmidi,snd_hda_codec_generic,snd_hda_codec,snd_hda_intel,snd_seq_device,snd_seq_midi
i2c_algo_bit 13413 1 i915
8250_dw 13437 0
lp 17759 0
wmi 19177 0
shpchp 37032 0
soundcore 12680 1 snd
spi_pxa2xx_platform 23056 0
parport 42313 3 lp,ppdev,parport_pc
hid_generic 12548 0
usbhid 52567 0
hid 105788 4 i2c_hid,hid_multitouch,hid_generic,usbhid
usb_storage 66305 0
psmouse 106606 0
sdhci_acpi 13376 0
sdhci 43023 1 sdhci_acpi
r8169 71677 0
mii 13934 1 r8169
ahci 34014 3
libahci 32082 1 ahci

そのうちLinux起動時にドライバがどうやって読み込まれるのかを調べてみよう(今回はやらない)。

まとめ

PC Linuxのカーネルを浅く広く弄り倒してみました。

次は1つ1つ深堀していきたいです。

関連記事

【PC】Linuxビルドのノウハウ(ビルドとインストール)

【PC】Linuxビルドのノウハウ(残課題)

【VirtualBox】仮想OS環境にUbuntu18 LTS(Linux)をインストールする手順

【WSL】WindowsでLinuxを動かす

【Yocto】組み込みLinuxの主流はYocto

【Linuxコマンド】便利な小技たち(TIPS)

【ネットワーク】WindowsからUbuntu14.04に接続する方法2つ

【Linuxコマンド】パッチを使いこなしたい

【UNIX時間】2038年問題について整理する

 

  • この記事を書いた人
  • 最新記事

ペイヴメント

ペイヴメントのエンジニア塾(当ブログ)では20年以上の経験から得られたプログラミング系ノウハウについてベテランにも満足して頂けるような内容の濃いコンテンツを初心者にも分かりやすい形で日々発信しています。【経歴】ベンチャーのソフトハウスで4年勤務後、精密機器メーカーのソフト開発部門に勤務し今に至ります。

-Linux, OS, 開発環境/ツール

Copyright© ペイヴメントのエンジニア塾 , 2020 All Rights Reserved.