8. Linuxのシステムプログラミングに関する知識 I

シラバス: 

1. 科目の概要

 Linuxにおいてシステムが提供するリソースを活用してプログラムを実行するシステムプログラミングについて解説する。プログラムの作成方法から始まり、プログラムからのファイル操作、パラメータの受け渡し、ライブラリの利用、メモリ管理やデータベースの利用までを説明する。

2. 習得ポイント

 本科目の学習により習得することが期待されるポイントは以下の通り。

3. IT知識体系との対応関係

「8. Linuxのシステムプログラミングに関する知識Ⅰ」とIT知識体系との対応関係は以下の通り。

[シラバス:http://www.ipa.go.jp/software/open/ossc/download/Model_Curriculum_05_08.pdf]

<IT知識体系上の関連部分>

4. OSSモデルカリキュラム固有の知識

OSSモデルカリキュラム固有の知識として、Linuxという具体的な環境におけるプログラミング手法の知識が含まれる。ファイルシステムやライブラリに関するプログラミング手法についてLinuxを通して習得することとなる。

(網掛け部分はIT知識体系で学習できる知識を示し、それ以外はOSSモデルカリキュラム固有の知識を示している)

I-8-1. エディタを用いたソースファイルの作成

Linuxのシステムへログインし、エディタを起動してソースファイルを作成するまでの手順を説明する。また代表的なエディタであるviとemacsについて、基本的な操作方法を解説する。

【学習の要点】

* Linuxシステムプログラミングは、メモリ管理、ファイルシステム、ネットワーク、プロセス、マルチスレッド、プロセス間通信といったカーネルの基本機能を操作するためのプログラム作成することである。

* ソースファイルの作成手順は、サーバにログインした後、ソースファイルを保存するディレクトリに移動する。

* エディタを起動して、ソースコードの入力・編集を行って保存する。

図I-8-1. ソースファイルの作成

【解説】

1) ソースファイルの作成手順

新たにソースファイルを作成するための手順を、以下に明記する。

* まず最初に、Linuxシステムにログインする。

システム管理者より受け取った「ログイン名」と「パスワード」を使って、システムにログインする。

* ディレクトリに移動する。

Linuxファイルシステムは、ディレクトリという概念でファイルの管理や保存を行っている。そのため、新たに作成したいファイルを保管するためのディレクトリへ事前に移動しておく。

* エディタを起動させて、ソースの入力を行う。

ファイルを作成するためには、用意されている強力なエディタを利用する方法が簡単である。

* 入力した情報をハードディスクに書き込み、エディタを終了させる。

ソースコードの入力完了後、エディタの機能を使ってハードディスクにソースコードの書き込みを行い、エディタを終了させる。

2) vi (Visual editor)エディタ

viエディタを起動させる際には、引数として'作成したいソースファイル名'を指定する。

* コマンドモード : このモードでは、以下に示すコマンドが使用可能である。

- a :挿入モードへ切り替える。カーソルの次の文字から文字の挿入が可能。

- i :挿入モードへ切り替える。カーソルの場所から文字の挿入が可能。

- o もしくは O :現在の行の前後に新しい行を追加する。

- r :現在のカーソルの場所の文字を変更する。

- x :現在のカーソルの場所の文字を削除する。

- :(コロン) :exモードへ切り替える。

* 挿入モード : ソースコード本文も入力を行う。[ESC]キーの押下でコマンドモードに戻る。

* exモード : 内容を記録したり、viエディタを終了させたりといったコマンドを実行する。

- wq :作成(修正)した内容をファイルへ書き込んでから、エディタを終了させる。

- q! :作成(修正)した内容は書き込まずに、エディタを終了させる。

3) emacs

emacsには語や段落の操作やソースコードを読み易くする構文の強調機能や、利用者の定義する一括編集コマンドを動かす「キーボード・マクロ」の実行のための機能など、多数の機能がある。

* 主モード : このモードでは、以下に示すキー操作が可能である。

- [Ctrl]+v:次の画面に進む。

- <ESC>+v:前の画面に戻る。

- [Ctrl]+p,b,n,f:カーソルを移動させる。

- [Ctrl]+k:行の削除、連続操作で完全な削除

- [Ctrl]+x [Ctrl]+f:ファイルを開く

- [Ctrl]+x [Ctrl]+s:ファイルをセーブする。

I-8-2. コンパイラの仕組みと実行ファイルの作成

C言語プログラムを題材として、コンパイラの仕組み、プリプロセッサ、コンパイラ、リンカの役割を解説する。またソースプログラムからオブジェクトファイルを生成し、実行プログラムを構築するまでの手順やコンパイラオプションの指定などを説明する。

【学習の要点】

* コンパイラとは、実行可能なオブジェクトコードを作成するツールである。

* 実際のコード変換処理の前に、プリプロセッサといったツールが実行される。

* コードの変換後には、リンカといったツールが実行されて実行ファイルが完成する。

図I-8-2. プログラム構築までの手順

【解説】

1) コンパイル時に使用するソフトウェア開発ツール

コンパイラは様々なツールを組み合わせて実行可能なコードを作成する。OSSのGNU gccコンパイラを使用した場合は、以下に示す機能をまとめて実行することができる。

* プリプロセッサ

オブジェクトコードに変換するその前に、ソースコードに一定の規則に従って処理を加えるツール。

* コンパイラ

コンピュータ上で実行可能なオブジェクトコードに変換するツール。コンパイラには最適化を行うか行わないかなど、コンパイラの処理方法を制御するオプションがある。

* リンカ

オブジェクトコードに、必要なライブラリなどを結合させて、実際に実行することが可能なファイルを生成するツール。

2) コンパイラの仕組み

人間がプログラミング言語の記述ルールに従って作成したソースコードを、コンピュータ上で実行可能なオブジェクトコードに変換することをコンパイルといい、そのためのソフトウェアをコンパイラという。コンパイラの仕組みは以下の通り。

* 字句解析

ソースコードに含まれる文字列を、字句という単位に分割する。

* 構文解析

文法的に正しいか、構文的に間違っていないかのチェックを行う。

* 意味解析

実行することが可能かどうかをチェックする。

* コード最適化

実行時により速く実行できるように無駄をなくす処理を行う。

* コード生成

オブジェクトコードの生成を行う。

3) 実行プログラム構築までの手順

GNU gccコンパイラを使用して、C言語のソースコードから実行プログラムを構築する流れを以下に明記する。

* viやemacsなどを使ってソースコードを作成する。

* gccコマンドを使って、コンパイルを行う。内部的な処理の流れは以下の通り。

- プリプロセッサが実行されて、#include文で指定されたヘッダーファイルが取り込まれる。

- プリプロセッサの実行結果に対して、字句解析と構文解析が行われる。

- 続いて、意味解析・最適化が行われて、アセンブリ言語のコードを作成する。

- アセンブラが実行可能形式のコードへ変換する。

- リンカが、スタートアップルーチンやライブラリを付加させて実行モジュールを作成する。

I-8-3. シェルスクリプトによる定形処理

シェルの種類やシェルスクリプトの概念、対話的シェルの操作方法を説明する。スクリプトを作成してから実行するまでの手順を示し、また基本的なシェルコマンドやシェルスクリプトの文法、記述方式について言及する。

【学習の要点】

* シェルスクリプトとは複雑な繰り返し処理や条件分岐を使って、複数のコマンドを逐次実行できるようにした簡易プログラムである。

* シェルスクリプトは、1行目にshebangを記述、2行目以降にプログラム本体を記述したテキストファイルとして作成する。

図I-8-3. シェルスクリプトの作成

【解説】

1) シェルスクリプトとは

複数のコマンドをまとめて実行することで、繰り返しの多い処理や一連の処理を簡単に実行できるようにした簡易プログラム。オペレータの指示をカーネルに伝えるためのシェルが、直接解釈し実行することができる。特徴は以下の通り。

* シェルごとに独自の文法が採用されている。

* 複雑な繰り返し処理や条件分岐などに対応している。

* コマンドを、そのままプログラムとして記述できる。

* 対話的なスクリプトを作成することも可能である。

* 引数を指定することで挙動が代わるスクリプトも作成することが可能である。

2) スクリプトの作成から実行まで

シェルスクリプトは、viエディタなどを使ってコマンドなどをまとめたテキストファイルとして作成する。

* 1行目にはshebangを含める。

これはこのスクリプトの実行時に、どのインタプリタを使用するかをOSに伝えるものである。

- Linuxの標準シェルであるbashの場合は、「#!/bin/bash」と明記する。

* 2行目以降に、実行させたいコマンドを並べて記述する。

- コメント行は先頭に「 # 」を記述する。

* スクリプトファイルのパーミッションを、実行可能に変更する。

* パスを指定したディレクトリに配置するか、パスを指定しながらスクリプトを実行させる。

- カレントディレクトリにある場合は、「./(スクリプトファイル名)」と指定する。

3) シェルスクリプトの構文

以下に基本的なコマンドの文法を明記する。

* 標準出力への表示

- printf文: 標準出力に対して、変数の値や文字列などをまとめて表示する。

例) printf "number is %d" $number

- echo文: 標準出力に対して、文字列を表示する。

例) echo "Hello World"

* 標準入力からの入力

- read文: 入力された文字列を指定した変数に設定する。

例) read NUMBER

* 繰り返し処理

- for ループ: 変数に指定範囲内の数値を割り当てて、繰り返す。

例) for number in $( seq 1 10 )

* 判断文

- if 文: 変数の持つ値によって処理を変更する。

例) if [ number != 0 ]; then 命令 fi

I-8-4. 低水準ファイル処理によるファイル操作

低水準ファイルアクセスを行うシステムコールを使ってファイルを操作する方法を示す。ファイル操作のモード、ファイルの生成、オープンとクローズ、ファイルの読み書きとファイルパーミッションの変更、その他ファイル操作に必要なシステムコール郡について説明する。

【学習の要点】

* ファイルのアクセスには、高水準ファイルアクセスと低水準ファイルアクセスがある。

* 低水準ファイルアクセスを行うシステムコールを呼び出すために、様々な関数が用意されている。

* 低水準入出力関数はOS依存の関数で、最低限の機能のみが用意されている。

図I-8-4. 低水準ファイルアクセス

【解説】

1) 低水準入出力関数の特徴

オペレーティングシステムに依存する関数で、かつ最低限の機能のみが用意されている。特徴を以下に示す。

* プログラムの変更が必要なため、簡単に他のOSへ移植させることができない。

* ファイルからの読込を行うと、プログラムが指定した領域に直接書き込まれる。

* 1バイトの読み込みであっても、最小単位である1024バイトをメモリ上に蓄える。ただし、次の1バイトの読み込みでは、メモリ上から読み込むため、高速な処理が可能。

2) 低水準ファイルアクセス入出力関数

以下に、低水準ファイルアクセス入出力関数を紹介する。関数の戻り値が-1であった場合は、エラーが発生したことを意味する。

* creat関数:ファイル作成を作成する。戻り値はファイルディスクリプタ。

- 引数は、作成したいファイル名へのポインタと作成時のモード。

- 作成時に指定するモードには、読み取り専用、読込書込みともに可能などが指定可。

* open関数:ファイルをオープンする。戻り値はファイルディスクリプタ。

- 引数は、作成したいファイル名へのポインタとオープン時のモード。

- オープン時に指定するモードには、読込専用、書込専用、読込書込み可などが指定可。

* read関数:ファイルからの読込み。戻り値は読み込んだサイズ。

- 引数は、ファイルディスクリプタ、読み込みたいバイト数、格納するバッファ。

- ファイルディスクリプタは、creat関数やopen関数からの戻り値。

* write関数:ファイルへの書き込み。戻り値は実際に書き込んだサイズ。

- 引数は、ファイルディスクリプタ、書き込みたい情報、書き込みたいサイズ。

* lseek関数:入出力を行いたい位置の指定。戻り値はファイル先頭からのバイト数。

- 引数は、ファイルディスクリプタ、移動したいバイス数、開始したい位置。

- 第三引数には、L_SET(先頭から)、L_XTND(終端から)などの指定が可能。

* close関数:ファイルクローズを閉じる。0が戻るとクローズ成功を意味する。

- 引数は、ファイルディスクリプタを指定する。

3) その他の低水準ファイル処理関数

その他の、低水準ファイル処理関数を紹介する。

* chmod関数、fchmod関数; ファイルのモードを変更する。

* chown関数、fchown関数、lchown関数: ユーザID、グループIDを変更する。

* umask関数: プロセスによりファイル作成時のマスク値を設定、変更する。

* access関数: ファイル操作のアクセス権を検査する。

I-8-5. 標準入出力ライブラリによるファイル操作

標準入出力ライブラリを用いてファイルを操作する方法を示す。低水準ファイル処理のそれぞれに対応する関数を紹介し、さらに書式付き入出力や利用上の留意点も示す。また一時ファイルを作成する関数についても触れる。

【学習の要点】

* 低水準関数には最低限の機能しか用意されていないが、高水準関数であれば便利な機能も用意されている。

* 高水準関数には、ファイル操作のための標準入出力ライブラリなどが用意されている。

* 高水準関数を使用した場合であっても、基本的なファイル操作の流れは同じである。

図I-8-5. 高水準関数

【解説】

4) ファイル操作に関して

低水準関数には最低限の機能しか用意されていないため、不便な面も多い。それと比べて高水準関数であれば、多少は便利な機能も用意されている。例えば、ファイルの詳細情報(i ノード・ファイルモード・UID・GID・時間情報など)を収集したい場合には、以下に示す関数などを使用するとよい。

* stat、fstat、lstat関数

個々の関数の違いは、情報を得たいファイルの指定方法である。この関数が正常に終了すると、引数で指定したstat構造体に、ファイルの情報が書き込まれる。

* stat構造体

i ノードやファイルモード、UIDとGID、さらには時間情報など、指定したファイルが持つ多くの情報を書き込みための領域。

5) 標準入出力ライブラリに関して

高水準関数を使用した場合であっても、はじめにファイルをオープンして読み込みや書き込みを行い、最後にクローズする流れは同じである。

* ファイルのオープン・クローズや入出力を行う場合には、以下の関数を使用する。

fopen,fread,fwrite,fclose

* バッファに格納されているデータを吐き出す場合には、以下の関数を使用する。

fflush

* ファイル位置子を移動させる場合には、以下の関数を使用する。

fseek

* 入出力ストリームや標準入出力から、1文字読み込んだり書き込んだりする場合には、以下の関数を使用する。

fgetc,getc,getchar,fputc,putc,putchar

6) 書式付き入出力に関して

低水準関数には書式付き出力などの機能がない。書式を考慮した入出力を行いたい場合には、以下の関数を使用する。

* 書式付き文字列の表示関数

printf、fprintf、sprintf

* 書式付き入力関数

scanf、fscanf、sscanf

7) 一時ファイルの作成に関して

* 既存のファイルと重複しない新たなファイルの名前を作成する。

tmpnam

* プログラム終了時に自動的に削除される一時的なバイナリファイルを作る。

tmpfile

I-8-6. ファイルシステムの操作

ファイルシステムの概念や構造、ファイルシステムの種類と各ファイルシステムの特徴について説明し、複数のディスクブロックをひとつのツリーとして扱う考え方とその方法を解説する。またディレクトリをプログラムから操作する方法や特殊なディレクトリについて説明する。

【学習の要点】

* ファイルシステムとは、コンピュータ内にある資源の操作や保護を実現する仕組みである。

* ファイルシステムは、木構造となっている。

* ファイルシステムの種類としては、ext2,ext3などが存在する。

図I-8-6. ファイルシステムの操作

【解説】

1) ファイルシステムの概念と構造

ファイルシステムは、ファイルやディレクトリなどコンピュータ内部にある資源を操作したり保護したりするための仕組みである。

* ファイルシステムの中に存在するもの。

データを保持するためのファイル、ディレクトリファイル、スペシャルファイルなどがある。

* ファイルシステムに関する情報の収集方法。

statfs関数により、スーパーブロック等の情報取得が可能である。

* ファイルシステムの使用方法。

ディスク上のパーティションを任意のディレクトリにmount・umountすることで、ファイルシステムへの追加や削除が可能となる。

mountするディレクトリのことをマウントポイントと呼ぶ。全てのマウントポイントの情報は、/etc/fstabファイル内に格納される。

* ファイルシステムの構造

ファイルシステムは、逆さまの木構造となっている。最上位には”/(ルート)”ディレクトリが存在し、その下には木の枝が伸びるように様々なディレクトリが用意されている。

ディスク内のパーティションがマウント済みの状態である場合、親のディレクトリや配下のディレクトリ(子供のディレクトリ、サブディレクトリなどと呼ぶ)は異なるパーティションにある可能性もある。ファイルシステムにより、データが複数のパーティションに分割されていることをユーザが意識せずに、操作を行うことが可能となる。

* ファイルシステムの種類

FAT,ext2,ext3,ReiserFS,NTFSなどが存在する。

* ファイルの管理方法

ext2/ext3ファイルシステムでは、ファイルを管理する場合にiノードと呼ばれる機能を利用している。iノードには個々のファイルの詳細情報が収められており、iノードテーブルと呼ばれる領域に納められている。個々のファイルにはiノード番号と呼ばれる情報があり、iノードテーブル内の場所を示している。

2) プログラムからの操作

プログラムから、個々のディレクトリへアクセスを行う場合には、以下に示す関数を使用する。

* ディレクトリのオープンとクローズ

opendir,closedir

* ディレクトリの読み込みと関連する関数

readdir,telldir,seekdir

3) 特殊ディレクトリ

ファイルシステムの中には、/procという名称の特殊ディレクトリが存在する。

* /procディレクトリは、実際にディスク上に作成されるディレクトリやファイルではなく、カーネルの認識している情報をファイルシステムのインタフェースを介して参照するための仮想ファイルシステムである。

I-8-7. コマンドラインオプションと環境変数のプログラムへの渡し方

シェルからプログラムへパラメータを渡す方法として、コマンドライン引数による方法と環境変数を用いる方法を説明する。渡されたパラメータをC言語プログラム内部で処理する方法やプログラムからの返り値の取扱いについて解説し、代表的な環境変数についても説明する。

【学習の要点】

* プログラムは起動時に指定されたパラメータの値により、その振る舞いが決定される。

* パラメータは、コマンドライン引数としても指定することが可能である。

* またパラメータは、環境変数として指定することも可能である。

図I-8-7. プログラムへのパラメータ

【解説】

1) プログラムへのパラメータ

プログラムは起動時に指定されたパラメータの値により、その振る舞いが決定される。個々のプログラムに対してパラメータを指定するには、以下の方法がある。

* コマンドライン引数として指定する。

コマンドライン引数として与えられた文字列は、空白を区切り文字として複数の文字列に分けられ、指定された引数の数とそれぞれの文字列へのポインタが、プログラムに与えられる。

* 環境変数として指定する。

事前に、パラメータ値を環境変数に設定しておけば、以下の関数で参照が可能となる。

- printenvコマンド : 環境変数の表示を行う。

- setコマンド : 環境変数を設定する。

- getenv取得関数 : 環境変数を検索し、この変数の示す値を返す。

- setenv設定関数 : 環境変数を作成する。

- putenv変更関数 : 環境変数の値を更新する。

- unsetenv削除関数 : 指定した環境変数を削除する。

2) C言語プログラムにおけるパラメータ処理

C言語で記述されたmain関数に対してもパラメータの指定が可能であり、これらはmain関数の引数として参照することが可能である。

* コマンドライン引数の処理方法

main関数への引数を受け取るためには、以下のように指定すればよい。

- main( int argc, char *argv[] ) {

argcがパラメータの個数を示し、argvに指定されたパラメータが順次納められている。

* 環境変数として指定されたパラメータの処理方法

getenv関数を用いて環境変数の示す値を受け取るには、getenv関数への引数として環境変数の名称を指定する。戻り値は該当する変数の持つ値へのポインタとなる。

* 各関数からの戻り値

各関数からは、必ず何らかの戻り値が存在する。戻り値を参照するには環境変数を以下の方法で参照すればよい。 例) # echo $?

3) 代表的な環境変数

Linuxが使用している代表的な環境変数には、以下に挙げる変数がある。

- USER : 現在の使用者名(ログイン名)が設定されている。

- HOME : 現在の使用者のホームディレクトリ名が設定されている。

- PATH : 使用可能なコマンドが置かれているディレクトリ名が設定されている。

- LANG : 現在使用中の言語が設定されている。

- PWD  : 現在のカレントディレクトリ名が設定されている。

- SHELL : 現在使用中のシェルの名称が設定されている。

- TERM : 標準で使用するターミナルの名称が設定されている。

I-8-8. ライブラリとプログラムの関係

プログラムをコンパイルしてできあがる実行ファイルと、実行ファイルから関数呼び出しで利用するライブラリの関係を説明する。また共有ライブラリの考え方と、実行時の動作、lddコマンドによる利用ライブラリの一覧やsizeコマンドによるメモリ利用状況の把握などを解説する。

【学習の要点】

* ライブラリとは、複数のプログラムが共通して利用するコードをまとめたファイルである。

* ライブラリ自体は単独で実行することはできない。

* 実行プログラムがライブラリをリンクする方法には、動的リンクと静的リンクとが存在する。

図I-8-8. 実行ファイルとライブラリの関係

【解説】

1) ライブラリとは

ライブラリとは、多くのプログラムが作成されている場合に、その中のどのプログラムにとっても共通な処理として必要と考えられる機能(プログラム)をまとめたもの。

* 様々なプログラムから利用できるように部品化されている。

* プログラムに限定されることはない。例えば定数の定義なども部品化されている。

* 単独のファイルとして、実行形式のプログラムとは別に提供されている。

* ライブラリ自体を単独で実行することはできない。

* 基本的に他のプログラムの一部として動作する。

* 複数のプログラマが、同じ目的や機能を持つプログラムを、個々に開発してしまう無駄を省く。

2) 実行ファイルとライブラリの関係

実行プログラムがライブラリをコールする方法には、動的リンクと呼ばれる方法と静的リンクと呼ばれる方法が存在する。

* 動的リンク

動的リンクとは、プログラムの起動時もしくは起動後のプログラム実行中に初めてライブラリを結合される方式である。共有ライブラリは動的リンクの仕組みを利用して実現される。

* 静的リンク

* 静的リンクとは、ソースコードのコンパイル後にオブジェクトファイルとライブラリとを結合させて、実行ファイルを作成する方法である。

* Linuxの場合、/lib、/usr/lib、/usr/local/libなどのフォルダに置かれるlibfoo.aやlibfoo.soといったファイルがライブラリである。ちなみに、ファイル名は常にlibという文字列で始まり、.soで終わる。静的ライブラリの場合は.aで終わる。

3) 共有ライブラリとは

様々なプログラムが同じライブラリを利用する場合、それぞれがメモリ上にコードを展開するとメモリの使用量が膨れ上がってしまう。それを避けるために、同一のコードを共有して利用できるように工夫されたライブラリのことを、共有ライブラリという。

4) ライブラリ関連コマンド

個々の実行ファイルとライブラリの関係などは、以下に示すコマンドなどにより参照可能である。

* 利用ライブラリの一覧表示

lddコマンド

* プログラムの使用メモリの状況

sizeコマンド

I-8-9. ライブラリの種類とライブラリの利用方法

ライブラリにはstaticライブラリとsharedライブラリの2種類があることを説明し、それぞれの利点と特徴、利用方法について解説する。また、ライブラリを利用したシステムプログラミングの例を示す。ライブラリで提供される関数とシステムコールの違いについての説明も行う。

【学習の要点】

* 静的ライブラリとは、プログラム(実行形式)の構築時に組み込まれるライブラリである。

* 共有ライブラリとは、プログラム実行と同時にメモリ上に展開されるライブラリである。

* 動的ライブラリとは、プログラム実行中の任意の時点で読み込まれるライブラリである。

図I-8-9. ライブラリの種類

【解説】

1) ライブラリの種類

ライブラリとは、実行させることが可能な複数個のプログラムに対して、そのプログラムにとっても共通であると判断できる部分のプログラムを集めたファイルである。ライブラリには、静的ライブラリと共有ライブラリがある。共有ライブラリには、動的ライブラリも含まれている。

* 静的ライブラリ(static library)

プログラム(実行形式)の構築時に組み込まれるライブラリ。

- ライブラリ部分は再コンパイルの必要がない。

- ライブラリとして提供するプログラムの、ソースコードを参照させたくない場合に役立つ。

* 共有ライブラリ(shared library)

プログラム実行と同時にメモリ上に展開されるライブラリ。

- 共有ライブラリのインストール後に実行開始されるプログラムは、必ずこのライブラリを利用することになる。

- すでに実行中のプログラムも、再起動しなければ古いライブラリを使い続けることが可能。

* 動的ライブラリ(dynamically loaded library)

プログラム実行中の任意の時点で読み込まれるライブラリ。

- 必要と判断されるまで、読み込まれない。

- プラグインやモジュールの実装に役立つ。

- 動的ライブラリの作成は、共有ライブラリと同様の方法で作成する。

2) ライブラリの利用方法

個々のライブラリを使用する際には、ライブラリ毎に異なる特徴を持っているので注意する。

* 静的ライブラリ

実行可能プログラムを作成するタイミングで、静的ライブラリを取り込む。コンパイルの際にgccコンパイラを使用しているのであれば、ライブラリの指定に-lオプションを指定する。

* 共有ライブラリ

/usr/libなどのディレクトリにファイルを配置して、ldconfigコマンドを実行する。実行可能プログラムをコンパイルする際に、-Lオプションで共有ライブラリを指定する。

* 動的ライブラリ

ライブラリをオープンし、シンボルを検索し、エラーを処理し、ライブラリを閉じる、という関数が存在する。それらを呼び出すことによって動的ライブラリを利用することができる。

3) ライブラリとシステムコール

* ライブラリ

基本的にOSには依存せず、かつ複数のアプリケーションプログラムの中で共通と判断される処理を提供する。内部的にシステムコールを呼び出しているものも存在する。

* システムコール

OS依存の関数である。また必要最低限なものしか用意されていない。

I-8-10. メモリ管理、ファイル管理とデータベースの利用

OSが管理するメモリの動的な利用方法、ファイルの排他処理として行うロックの方法、Berkeleyデータベースの利用など、システムプログラムから大規模なデータを管理する方法について解説する。

【学習の要点】

* 多くのデータ構造では、処理の都合で動的にメモリを確保する必要がある。

* ファイルのロックは、マルチプロセス環境においてデータの安全性確保のために重要な操作である。

* データベースを使用すると、ファイルのロックを気にせずにデータのアクセスが可能となる。

図I-8-10. メモリ管理とファイル管理

【解説】

1) メモリの管理

アプリケーションプログラムで確保可能なメモリ領域は、事前に決まっている。処理の都合で定められたサイズ以上の領域が必要な場合は、malloc関数を利用してメモリの確保を行う。

* 確保されたブロックは、初期化されない。

* 使用後には必ずfree関数などで解放する。

2) ファイルのロック

マルチプロセス環境では、複数のプロセスから1つのファイルへのアクセスを集中させることも可能であるため、データの安全性確保のためにロックファイルの作成が重要となる。

* ロックファイルの作成

使用するリソースのロックファイルを作成すると、他プロセスからはアクセスできなくなる

- ロックファイルの作成に、open関数を利用する。引数にはO_CREATとO_EXCLを指定。

- ロックファイルが新規に作成されれば、そのリソースの専有が可能となる。

- ロックファイルが存在すれば、エラーとなるため、リソースへのアクセスは不可能となる。

* リージョンのロック

目的とするリソースの特定の部分のみをロックする。別プロセスからはロックされていない部分へのアクセスが可能。

- リージョンのロックは、fcntl関数、もしくはlockf関数を使う。以下はfcntl関数の引数。

- F_GETLK引数:オープン済みリソースのロック情報を取得。

- F_SETLK引数:オープン済みリソースの一部をロックする。もしくは解除する。

- F_SETLKW引数:ロックできるまで待機する。

- 実際の読み書きはread関数とwrite関数を使用する。

3) データベース

データベースを利用すれば、ファイルのロックやリージョンのロックなどは気にせずに、データのアクセスが可能となる。さらに、サイズの異なるデータ書込みや索引機能を使ってのデータ管理も可能となる。

* dbmデータベース

滅多に書き換えられることはないのだが、頻繁に読み込みが行われるデータなどの管理には、dbmデータベースなどがソリューションとなる。dbmへのアクセスは、以下の関数を利用する。

- dbm_open : データベースのオープン。または新規作成。クローズはdbm_closeを使用。

- dbm_store : データベースにデータを入力する。

- dbm_fetch : データベースからデータを取得する。

- dbm_delete : データベースからデータを削除する。

- dbm_firstkeyとdbm_nextkey : 一緒に設定する。全項目のキー走査を行う。

* その他のデータベースには、ndbm、gdbmなどがある。