OSが提供するライブラリについて

ryichk
·

標準Cライブラリ

C言語には、国際標準化機構(International Organaization for Standardization, ISO)によって定められた標準ライブラリがある。

Linuxでもこの標準Cライブラリが提供されている。

通常はGNUプロジェクトが提供するglibc(以降、libcと表記)を標準Cライブラリとして使用する。

C言語で書かれたほとんどのプログラムは、libcをリンクしている。

プログラムがどのようなライブラリをリンクしているかは`ldd`コマンドで調べられる。

上の添付は、`echo`コマンドについて`ldd`を実行した結果である。

libc.so.6が標準Cライブラリを指す。

システムコールのラッパー関数

libcはシステムコールのラッパー関数も提供している。

システムコールは、C言語などの高級言語から直接呼び出すことはできない。

アーキテクチャ依存のアセンブリコードを使って呼び出す必要がある。

例えば、x86_64アーキテクチャのCPUとarm64アーキテクチャのCPUでは、アセンブリコードレベルでシステムコールの発行方法が異なるので、libcがなければシステムコールを発行するたびにアーキテクチャ依存のアセンブリコードを書いて高級言語からそれを呼び出さないといけなくなってしまう。

libcは、プログラム作成の手間を削減し、別アーキテクチャへの移植性も担保するために、内部的にシステムコールを呼び出すだけの関数を提供している。

このシステムコールのラッパー関数は、アーキテクチャ毎に存在しており、高級言語で書くユーザプログラムは、各言語に対して用意されているラッパー関数を呼び出すだけで済む。

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

ライブラリは、静的ライブラリと共有ライブラリの2種類に分類できる。

どちらも同じ機能を提供するが、プログラムへの組み込み方が異なる。

プログラム生成時に、まずソースコードをコンパイルしてオブジェクトファイルを作成する。そして、オブジェクトファイルが使うライブラリをリンクして、実行ファイルを作る。

静的ライブラリは、リンク時にライブラリ内の関数を実行ファイルに組み込む。

共有ライブラリは、リンク時に「このライブラリのこの関数を呼び出す」という情報だけを実行ファイルに埋め込む。そして、プログラムの起動時、あるいは実行中にライブラリをメモリ上にロードし、プログラムはその中の関数を呼び出す。

共有ライブラリには次のようなメリットがある。

  • システム全体としてのサイズを小さく抑えられる

  • ライブラリに問題があった場合は共有ライブラリを修正版に置き換えるだけで良い

そのため、共有ライブラリが好んで使われてきたが、最近はやや事情が変わってきたらしい。

例えば、Go言語は基本的にライブラリをすべて静的リンクしている。

それには次の理由がある。

  • メモリやストレージの大容量化によってサイズの問題が相対的に小さくなってきた

  • プログラムが1つの実行ファイルだけで動けば、別の環境でも同じく動作する

  • 実行時に共有ライブラリをリンクしないので起動が高速

  • 共有ライブラリのDLL地獄を回避できる

    (共有ライブラリは、バージョンアップしても後方互換性が維持されることが期待されるが、時として微妙に互換性が失われてしまうことがある。それによって一部のプログラムが動かなくなることがあり、そのような問題は解決が難しいことが多いためDLL地獄と呼ばれたりしているらしい)

参照

[試して理解]Linuxのしくみ ―実験と図解で学ぶOS、仮想マシン、コンテナの基礎知識【増補改訂版】

@ryichk
wanna be a good hacker.