🙆

「linuxのしくみ」を読む 第1章

2022/11/19に公開

第1章 Linuxの概要

カーネル

カーネルはハードウェアとプロセスの間で動作する。例えばプロセスがストレージデバイスに直接アクセスできると、プロセス1が書き込もうとした場所にプロセス2が書き込んでしまったりして意図した挙動にならないことがある。最悪デバイスが壊れて二度と使えなくなることもあるらしい。これを防ぐためには命令の実行順序を正しく制御する必要があり、それをカーネルが担う。

CPUはカーネルモードとユーザモードという権限が違うモードがある。linuxではカーネルのプログラムのみがカーネルモードで動作してデバイスにアクセスできる。プロセスはユーザモードで動作するのでデバイスにはアクセスできない。つまりプロセスはデバイスにアクセスしたい時はカーネルに依頼する。

システムコール

プロセスがカーネルに処理を依頼するための方法。システムコールでは例えば、

  • プロセスの生成、削除
  • メモリの確保、解放
  • 通信処理
  • ファイルシステム操作
  • デバイス操作
    などの処理をカーネルに依頼できる。ユーザモードで実行しているプロセスがシステムコールを発行すると、CPUにおいて例外というイベントが発生する。これをトリガーにしてCPUがカーネルモードに切り替わり、依頼内容に応じたカーネルの処理が動作する。プロセスからCPUのモード変更はシステムコールを発行する以外にできない。

straceコマンドによるシステムコールの可視化

strace -o {出力先} {実行ファイル}
で「出力先」にシステムコールのトレースが吐き出される。

ライブラリ

linuxではGNUプロジェクトが提供するglibcを標準ライブラリとして使用する。echoコマンドは、
$ ldd /bin/echo linux-vdso.so.1 (0x0000ffffa466d000) libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffa4460000) /lib/ld-linux-aarch64.so.1 (0x0000ffffa4634000)
libc.so.6がh標準Cライブラリを指す。
osレベルではC言語で書かれたプログラム群の標準Cライブラリが呼び出される。(Cだけじゃないけど)

静的ライブラリと共有ライブラリ

echoの例のように実行ファイルにリンク先の標準ライブラリを指すのが共有ライブラリ。対して静的ライブラリはリンク時に実行ファイル内にライブラリ内の関数を組み込む。その結果静的ライブラリは実行ファイルのサイズが共有ライブラリより大きくなる。
Goでは、基本的にライブラリを静的リンクしている。その結果、Goのプログラムは共有ライブラリに依存しない(実行ファイルのみで動作する)ので、別環境でも大丈夫。実行時に共有ライブラリをリンクしなくていいので起動が高速になる。-staticオプションでビルドすると静的ライブラリ。

GitHubで編集を提案

Discussion