3
1

Linux の起動に必要なファイルを逆に辿る

Last updated at Posted at 2024-01-24

これは Ubuntu 22.04 LTS が起動したところ。

image.png

これが起動するまでに動いているプログラムをたどっていきます。

環境

  • Ubuntu 22.04 LTS ja

デスクトップ起動時に動作するプログラム

Ubuntu 22.04 ではデスクトップマネージャに Gnome が使われていて、gnome-session-properties で起動時のプログラムが指定できます。

image.png

しかしながら、SSH 鍵エージェントなんかよりももっと沢山、デスクトップの上で起動していますよね。
ここらへんとか
image.png
ここらへんとか。
image.png

日本語変換は Mozc ですし 左にあるメニューは Ubuntu Dock です。これらはどうやって呼び出されているのでしょう?

Ubuntu Dock

これは gnome シェル拡張(extention)としてプレインストールされています。

image.png

この extention の実態は
/usr/share/gnome-shell/extensions/ubuntu-dock@ubuntu.com

にあります。

これは Gnome-session が呼び出されたときに extention も呼び出されているのかな?

gdm3

これはデスクトップ画面が表示される前のログイン UI。

image.png

このログイン UI は gdm3 によって提供されています。gdm3 はサービスとして起動していて、ログオン後のサービスの状況を見てみると以下のようになっています。

$ sudo service gdm3 status
● gdm.service - GNOME Display Manager
     Loaded: loaded (/lib/systemd/system/gdm.service; static)
     Active: active (running) since Sun 2024-01-14 22:23:12 JST; 1 week 2 days ago
   Main PID: 1193 (gdm3)
      Tasks: 3 (limit: 76595)
     Memory: 6.9M
        CPU: 33ms
     CGroup: /system.slice/gdm.service
             └─1193 /usr/sbin/gdm3

 1月 14 22:23:12 nanbuwks-B550M-S2H systemd[1]: Starting GNOME Display Manager...
 1月 14 22:23:12 nanbuwks-B550M-S2H systemd[1]: Started GNOME Display Manager.
 1月 14 22:23:12 nanbuwks-B550M-S2H gdm-autologin][1230]: gkr-pam: no password is available for user
 1月 14 22:23:12 nanbuwks-B550M-S2H gdm-autologin][1230]: pam_unix(gdm-autologin:session): session opened for user nanbuwks(uid=1000) by (uid=0)
 1月 14 22:23:13 nanbuwks-B550M-S2H gdm-autologin][1230]: gkr-pam: gnome-keyring-daemon started properly

pstree で見ると、gdm3 から gnome-session が呼ばれているのがわかります。

image.png

さて、gdm3 の設定は、/etc/gdm3 ディレクトリにある各ファイルに記述されています。

例えば、/etc/gdm3/Init/Default の一部は以下のようになっていて、ログオン後の処理が記述されています。

image.png

更に gdm3 から Weyland やデスクトップマネージャの呼び出しがなされていて、一例として Weyland に関する設定は /etc/gdm3/custom.conf 中に書かれています。

# Uncomment the line below to force the login screen to use Xorg
#WaylandEnable=false

XDG

デスクトップ画面を作るための設定は、/etc/gdm3 による設定以外にも多くの設定箇所があります。多くのデスクトップ環境では、XDG オートスタート設定を使うようになっています。h

XDG についての設定類は環境変数 XDG_CONFIG_DIRS で設定されています。

XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu-xorg:/etc/xdg

さきほど、Mozc や Dash はどこから呼び出されるのかについて話題にしましたが、例えば mozc の起動設定などは以下のように設定されています。

$ cat /etc/xdg/autostart/ibus-mozc-launch-xwayland.desktop 
[Desktop Entry]
Name=Launch Xwayland on startup of wayland session
Comment=This ensures that ibus-x11, needed for ibus-mozc, is started
Type=Application
Exec=sh -c 'if [ "$XDG_SESSION_TYPE" = "wayland" ]; then xrefresh; fi'
TryExec=xrefresh
OnlyShowIn=GNOME;
NoDisplay=true

/etc/rc*.d/

今まではログイン画面から後の処理を見ていました。さて、ログイン画面が出現する前は以下のスプラッシュが表示されますね。

image.png

このスプラッシュは裏で動いている各種表示を隠しています。ESC キーでスプラッシュを消すと、起動中の詳細が表示されます。

image.png

この [ OK ] と表示されているのは /etc/rc*.d/ 中にある起動スクリプトの結果です。
例えば /etc/rc5.d/S01gdm3 では、 gdm3 の起動が記述されています。

image.png

/etc/rc*.d/ 内にあるスクリプトは、 systemd が呼び出しているようです。
更に実は先の[ OK ]と表示しているのも systemd が介在しています。 systemd のソース job.c に以下のように記されています。

static const struct {
        int log_level;
        const char *color, *word;
} job_done_messages[_JOB_RESULT_MAX] = {
        [JOB_DONE]        = { LOG_INFO,    ANSI_OK_COLOR,         "  OK  " },
        [JOB_CANCELED]    = { LOG_INFO,                                    },
        [JOB_TIMEOUT]     = { LOG_ERR,     ANSI_HIGHLIGHT_RED,    " TIME " },
        [JOB_FAILED]      = { LOG_ERR,     ANSI_HIGHLIGHT_RED,    "FAILED" },
        [JOB_DEPENDENCY]  = { LOG_WARNING, ANSI_HIGHLIGHT_YELLOW, "DEPEND" },
        [JOB_SKIPPED]     = { LOG_NOTICE,  ANSI_HIGHLIGHT,        " INFO " },
        [JOB_INVALID]     = { LOG_INFO,                                    },
        [JOB_ASSERT]      = { LOG_WARNING, ANSI_HIGHLIGHT_YELLOW, "ASSERT" },
        [JOB_UNSUPPORTED] = { LOG_WARNING, ANSI_HIGHLIGHT_YELLOW, "UNSUPP" },
        [JOB_COLLECTED]   = { LOG_INFO,                                    },
        [JOB_ONCE]        = { LOG_ERR,     ANSI_HIGHLIGHT_RED,    " ONCE " },
};

systemd

更に遡ると、[ OK ] が出てこない起動表示が現れています。

image.png

ここらへんは /etc/systemd/system/ の中にある設定を実行しています。

image.png

また、上の方にある udevd.service などは、/lib/systemd 内にある systemd-udevd などが呼び出されているみたいです。

/sbin/init

systemd の実態は lib/systemd/systemd にあります。

ここらへんは /sbin/init から呼び出されます。
実は /sbin/init は systemd そのものです。

$ ls -alh init
lrwxrwxrwx 1 root root 20  8月 22 06:11 init -> /lib/systemd/systemd

init はプロセス番号が1番で動作して、一番最初に動作しているプログラムのように見えます。

$ ps auxww | grep init
root           1  0.0  0.0 168516 13008 ?        Ss    1月14   0:16 /sbin/init splash

しかしながら、最初と言っても /sbin/init は ルートファイルシステムがマウントされたあとに最初に呼び出されるものであるという条件がつきます。

これは果たしてどういったことなのでしょうか?

/init

/sbin/init はどこから呼び出されるかと言うと Linux カーネルの最初のプロセスとして動作する /init です。

しかしながら init というファイルは / に存在しません。

$ ls /init
ls: '/init' にアクセスできません: そのようなファイルやディレクトリはありません

これはどういうことかというと、/init は別のファイルシステム中にあるためです。 /init が起動すると、ルートファイルシステムをマウントする処理を行います。 ルートファイルシステムがマウントされる前に/init 起動しておく必要があり、/init は初期に使用する別のファイルシステムに格納されています。

grub

これは、/boot/grub/grub.cfg から Linux のブートの指定部分を抜き出したものです。

image.png

歴史上の理由でココらへんのファイルは /boot に格納されています。

cf., https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

ここの最後に initrd というのがありますね。これは、ルートファイルシステムが動作する前に、Linux カーネルを仮のファイルシステムで動かすものとして initrd または initramfs がります。どちらでもいいのですが、 Ubuntu では initrd が使われているようです。

initrd は RAM ディスクのイメージであり、 initrd または initramfs にアクセスするためのデバイスドライバはカーネルに静的にリンクされていて、RAMディスクとLinuxカーネルをメモリに展開し、Linux カーネルに RAM ディスクのアドレスを与えて起動すると Linux が動作し始めます。

RAMディスクイメージ

initrd 中にある RAM ディスクイメージを展開してみましょう。

/boot 内にある initrd.img-6.3.13-060313-generic を使いました。

$ file initrd.img-6.3.13-060313-generic 
$ unzstd initrd.img-6.3.13-060313-generic -o initrd.img

結構なサイズになりますね。

$ ls -alh
合計 260M
drwxrwxr-x   3 nanbuwks nanbuwks 4.0K  1月 24 22:41 .
drwxr-xr-x 259 nanbuwks nanbuwks 132K  1月 24 22:22 ..
-rw-r--r--   1 nanbuwks nanbuwks 214M  1月 24 22:22 initrd.img
-rw-r--r--   1 root     root      60M  1月 24 22:22 initrd.img-6.3.13-060313-generic

ファイルを抽出します。


$ mkdir initrdfiles
$ cd initrdfiles/
$ cat ../initrd.img | cpio -idv

中身は・・・

$ ls -alh
合計 40K
drwxrwxr-x 8 nanbuwks nanbuwks 4.0K  1月 24 22:42 .
drwxrwxr-x 3 nanbuwks nanbuwks 4.0K  1月 24 22:41 ..
lrwxrwxrwx 1 nanbuwks nanbuwks    7  1月 24 22:42 bin -> usr/bin
drwxr-xr-x 3 nanbuwks nanbuwks 4.0K  1月 24 22:42 conf
drwxr-xr-x 8 nanbuwks nanbuwks 4.0K  1月 24 22:42 etc
-rwxr-xr-x 1 nanbuwks nanbuwks 7.2K  1月 24 22:42 init
lrwxrwxrwx 1 nanbuwks nanbuwks    7  1月 24 22:42 lib -> usr/lib
lrwxrwxrwx 1 nanbuwks nanbuwks    9  1月 24 22:42 lib32 -> usr/lib32
lrwxrwxrwx 1 nanbuwks nanbuwks    9  1月 24 22:42 lib64 -> usr/lib64
lrwxrwxrwx 1 nanbuwks nanbuwks   10  1月 24 22:42 libx32 -> usr/libx32
drwxr-xr-x 2 nanbuwks nanbuwks 4.0K  1月 24 22:42 run
lrwxrwxrwx 1 nanbuwks nanbuwks    8  1月 24 22:42 sbin -> usr/sbin
drwxr-xr-x 7 nanbuwks nanbuwks 4.0K  1月 24 22:42 scripts
drwxr-xr-x 8 nanbuwks nanbuwks 4.0K  1月 24 22:42 usr
drwxr-xr-x 3 nanbuwks nanbuwks 4.0K  1月 24 22:42 var

/usr/sbin などもあって、シェルが使えることがわかります。

/init の仕組み

https://github.com/torvalds/linux/blob/master/init/main.c
によると、以下のようにカーネルソースに /init がハードコーディングされていて、オプション設定でオーバーライドしない限りは カーネル立ち上がり時に /init を実行するようです。

image.png

さて、先ほどRAMディスクの / にあった init ですが、


-rwxr-xr-x 1 nanbuwks nanbuwks 7.2K  1月 24 22:42 init

内部はシェルスクリプトになっていて、最後にはこのようになっています。

# Chain to real filesystem
# shellcheck disable=SC2086,SC2094
exec run-init ${drop_caps} "${rootmnt}" "${init}" "$@" <"${rootmnt}/dev/console" >"${rootmnt}/dev/console" 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."

そして、${rootmnt}${init} の値として以下のように指定されています。

.
.
.
export init=/sbin/init
export readonly=y
export rootmnt=/root
.
.
.

run-init は、${rootmnt} で与えられたファイルシステムを / としてマウントし直し、${init} で指定した /sbin/init プログラムをプロセス番号1番として動作させる働きがあります。

そしてここに来るまでに、${rootmnt} で示された /root に、本来のルートファイルシステムが /root としてマウントされている状態になっています。

ということで、/sbin/init すなわち serviced が プロセス番号1番として起動し、サービスや /etc/rc* を実行、gdm3 で Weiland や gnome-session と共にログオンしてデスクトップが使えるようになります。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1