ファイヤープロジェクト
ファイル操作
2003-07-20T15:13+09:00   matsu
GNU/Linuxシステムでのファイル操作について.ここでは特にシステムコールを用いてファイル操作する方法について.
ls /dev
とか
ls /proc
などとすると,たくさんのファイルがある.これらはデバイスやそれらの情報だったりする.だから(?)Linuxではデバイスをファイルとして扱えるらしい.つまりopen,close,read,write,ioctlができる.
そんなんだから,普通のファイルを扱えるようになることは,いろんなデバイスをいじるために不可欠なのだ.
ファイルアクセスに使用されるシステムコールは,write,open,read,close,ioctlが主である.
writeはファイルディスクリプタに書き込んでくれる.
#include <unistd.h>
ssize_t write(int fd,const void *buf,size_t count);
    ssize_t
    書き込まれたバイト数,もしくは-1(エラー時).
    fd
    ファイルディスクリプタ.
    *buf
    バッファ.
    count
    表示バイト数
openはファイルディスクリプタをオープンする.標準ファイルディスクリプタ0,1,2はプログラム起動時に勝手に開かれるが,それら以外,例えばファイルに書き込みたくなったら,このopenを使用する.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname;int flags);
int open(const char *pathname;int flags,mode_t mode);
    返り値
    ファイルディスクリプタを指す整数.失敗した場合は-1を返す.
    *pathname
    ファイルのパス.
    flags
    書き込みモード.ファイルがなければ作る,など,いろいろあって,それらをOR(|)で結べる.
    mode
    ファイルを作成するとき,そのファイルにパーミッションを指定できる.整数で755とか指定すると思わぬことになる.ちゃんとmode_tで指定する.ここで指定したパーミッションとumaskを反転させたものとの論理積がファイルに実際に設定されるパーミッションである.
readはファイルディスクリプタから読み込む.
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t count);
    ssize_t
    読み込んだバイト数を返す.失敗したら-1を返す.
    fd
    ファイルディスクリプタ
    buf
    バッファ
    count
    読み込むバイト数
closeはファイルディスクリプタを閉じる.開いたら,閉じる.それが人情である.
#include <unistd.h>
int close(int fd);
    返り値
    close成功なら0,失敗なら-1を返す.
    fd
    ファイルディスクリプタ
closeの返り値をちゃんとチェックしないと,データがちゃんとファイルに書き込まれてなかった場合に,そのデータが消失してしまう可能性があるらしい.これはwriteによって,実際にディスクに書き込まれるタイミングがからむらしい.fsyncを使うと,メモリ上のフィルのないようをディスク上のものと同期できる.
#include <unistd.h>
int fsync(int fd);
    返り値
    成功したら0,失敗なら-1を返す.
    fd
    ファイルディスクリプタ
manによると,ファイルのディレクトリエントリをディスクに書き込まれることは保証しないらしい.よくわからんが,ディスクにデータを書いたが,iノードが切れてそのファイルが削除されたりディスクのサイズや日付が反映されなかったりするんだろうか.
一つのプロセスが開けるファイルディスクリプタの上限(OPEN_MAX)は決まっている.私のシステムでは/usr/include/linux/limits.hにOPEN_MAX 256とある.だから,ファイルディスクリプタを使いまくったら,closeしなけらばならない(256も使わないけど).そういえば,誰かがファイルディスクリプタを開きまくったら,rootでさえファイルディスクリプタを取得できなくなるバグがかつてあった気がする.カーネルだったかな.
ioctlは主にデバイスファイル用の関数である.いろんなデバイスがあるから,各デバイスで利用できる機能が違ってくる.それらの違いをioctlで丸めようという意図じゃないかな.
matsu(C)
Since 2002
Mail to matsu