OPEN
Section: Linux Programmer's Manual (2)
Updated: 2009-09-20
Index
JM Home Page
roff page
名前
open, creat - ファイルやデバイスのオープン、作成を行う
書式
#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);
int creat(const char *pathname, mode_t mode);
説明
ファイルの
pathname
を与えると、
open()
はファイル・ディスクリプタを返す。
ファイル・ディスクリプタは、この後に続くシステムコール
(read(2), write(2), lseek(2), fcntl(2) など)
で使用される小さな非負の整数である。
このシステムコールが成功した場合に返されるファイル・ディスクリプタは
そのプロセスがその時点でオープンしていないファイル・ディスクリプタの
うち最小の数字のものとなる。
デフォルトでは、新しいファイル・ディスクリプタは
execve(2)
を実行した後もオープンされたままとなる (つまり、
fcntl(2)
に説明がある
FD_CLOEXEC
ファイル・ディスクリプタ・フラグは最初は無効である;
後述の Linux 固有のフラグ
O_CLOEXEC
を使うとこのデフォルトを変更することができる)。
ファイル・オフセット (file offset) はファイルの先頭に設定される
(lseek(2)
参照)。
open()
を呼び出すと、「オープンファイル記述」
(open file description)
が作成される。ファイル記述とは、システム全体の
オープン中のファイルのテーブルのエントリである。
このエントリは、ファイル・オフセットとファイル状態フラグ
(fcntl(2)
F_SETFL
操作により変更可能) が保持する。
ファイル・ディスクリプタはこれらのエントリの一つへの参照である。
この後で
pathname
が削除されたり、他のファイルを参照するように変更されたりしても、
この参照は影響を受けない。
新しいオープンファイル記述は最初は他のどのプロセスとも
共有されていないが、
fork(2)
で共有が起こる場合がある。
引き数
flags
には、アクセスモード
O_RDONLY, O_WRONLY, O_RDWR
のどれかひとつが入っていなければならない。
これらはそれぞれ読み込み専用、書き込み専用、読み書き用に
ファイルをオープンすることを要求するものである。
さらに、
flags
には、ファイル作成フラグ (file creation flag) とファイル状態フラグ
(file status flag) を 0 個以上「ビット単位の OR (bitwise-or)」で
指定することができる。
ファイル作成フラグ
は
O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC
である。
ファイル状態フラグ
は以下のリストのうち上記以外の残りのものである。
二種類のフラグの違いは、ファイル状態フラグの方は
fcntl(2)
を使ってその内容を取得したり (場合によっては) 変更したりできる点にある。
ファイル作成フラグとファイル状態フラグの全リストを以下に示す:
- O_APPEND
-
ファイルを追加 (append) モードでオープンする。
毎回の
write(2)
の前に
lseek(2)
を行ったかのように、ファイル・ポインターをファイルの最後に移動する。
NFS ファイル・システムで、
O_APPEND
を使用すると、複数のプロセスがひとつのファイルに同時にデータを追加した場合、
ファイルが壊れてしまうことがある。
これは NFS が追加モードをサポートしていないため、
クライアントのカーネル (kernel) がそれをシミュレートしなければならないのだが、
競合状態を避けることはできないからである。
- O_ASYNC
-
シグナル駆動 I/O (signal-driven I/O) を有効にする:
このファイル・ディスクリプタへの
入力または出力が可能になった場合に、シグナルを生成する
(デフォルトは
SIGIO
であるが、
fcntl(2)
によって変更可能である)。
この機能が使用可能なのは端末、疑似端末、ソケットのみであり、
(Linux 2.6 以降では) パイプと FIFO に対しても使用できる。
さらに詳しい説明は
fcntl(2)
を参照すること。
- O_CLOEXEC (Linux 2.6.23 以降)
-
新しいファイル・ディスクリプタに対して close-on-exec フラグを有効にする。
このフラグを指定することで、プログラムは
FD_CLOEXEC
フラグをセットするための
fcntl(2)
F_SETFD
操作を別途呼び出す必要がなくなる。
また、ある種のマルチスレッドのプログラムはこのフラグの使用は
不可欠である。なぜなら、個別に
FD_CLOEXEC
フラグを設定する
fcntl(2)
F_SETFD
操作を呼び出したとしても、あるスレッドがファイルディスクリプタを
オープンするのと同時に別のスレッドが
fork(2)
と
execve(2)
を実行するという競合条件を避けるのには十分ではないからである。
- O_CREAT
-
ファイルが存在しなかった場合は作成 (create) する。
ファイルの所有者 (ユーザー ID) は、プロセスの実効ユーザー ID に設定される。
グループ所有権 (グループ ID) は、プロセスの実効グループ ID
または親ディレクトリのグループ ID に設定される
(これは、ファイルシステムタイプ、マウントオプション、
親ディレクトリのモードに依存する。
mount(8)
で説明されているマウントオプション
bsdgroups
と
sysvgroups
を参照)。
-
mode
は新しいファイルを作成する場合に使用するアクセス許可 (permission) を指定する。
flags
に
O_CREAT
が指定されている場合、
mode
を指定しなければならない。
O_CREAT
が指定されていない場合、
mode
は無視される。
有効なアクセス許可は、普段と同じようにプロセスの
umask
によって修正され、作成されたファイルの許可は
(mode & ~umask)
となる。
このモードは、新しく作成されたファイルに対するそれ以降のアクセス
にのみ適用される点に注意すること。
読み取り専用のファイルを作成する
open()
コールであっても、
読み書き可能なファイル・ディスクリプタを返すことがありうる。
mode
のために以下のシンボル定数が提供されている :
- S_IRWXU
-
00700 ユーザー (ファイルの所有者) に読み込み、書き込み、
実行の許可がある。
- S_IRUSR
-
00400 ユーザーに読み込みの許可がある。
- S_IWUSR
-
00200 ユーザーに書き込みの許可がある。
- S_IXUSR
-
00100 ユーザーに実行の許可がある。
- S_IRWXG
-
00070 グループに読み込み、書き込み、実行の許可がある。
- S_IRGRP
-
00040 グループに読み込みの許可がある。
- S_IWGRP
-
00020 グループに書き込みの許可がある。
- S_IXGRP
-
00010 グループに実行の許可がある。
- S_IRWXO
-
00007 他人 (others) に読み込み、書き込み、実行の許可がある。
- S_IROTH
-
00004 他人に読み込みの許可がある。
- S_IWOTH
-
00002 他人に書き込みの許可がある。
- S_IXOTH
-
00001 他人に実行の許可がある。
- O_DIRECT (Linux 2.4.10 以降)
-
このファイルに対する I/O のキャッシュの効果を最小化しようとする。
このフラグを使うと、一般的に性能が低下する。
しかしアプリケーションが独自にキャッシングを行っているような
特別な場合には役に立つ。
ファイルの I/O はユーザー空間バッファに対して直接行われる。
O_DIRECT
フラグ自身はデータを同期で転送しようとはするが、
O_SYNC
のようにデータと必要なメタデータの転送が保証されるわけではない。
同期 I/O を保証するためには、
O_DIRECT
に加えて
O_SYNC
を使用しなければならない。
「注意」の節 (下記) の議論も参照。
ブロックデバイスに対する似通った意味のインターフェースが
raw(8)
で説明されている (但し、このインタフェースは非推奨である)。
- O_DIRECTORY
-
pathname がディレクトリでなければオープンは失敗する。
このフラグは Linux 特有であり、
opendir(3)
が FIFO やテープデバイスに対してコールされた場合の
サービス不能 (denial-of-service) 攻撃を避けるために
カーネル 2.1.126 で追加された。
しかしこれは
opendir(3)
の実装以外では使用するべきではない。
- O_EXCL
-
この呼び出しでファイルが作成されることを保証する。
このフラグが
O_CREAT
と一緒に指定され、
pathname
のファイルが既に存在した場合、
open()
は失敗する。
O_CREAT
が指定されなかった場合の
O_EXCL
の動作は未定義である。
これら二つのフラグが指定された際、シンボリックリンクは辿られない。
pathname
がシンボリックリンクの場合、
シンボリックリンクがどこを指しているかに関わらず
open()
は失敗する。
O_EXCL
は、Linux 2.6 以降で NFSv3 以降を使っている NFS でのみサポートされている。
NFS の
O_EXCL
サポートが提供されていない環境では、このフラグに頼って
ロック処理を実行するプログラムは競合状態 (race condition) に出会う
可能性がある。
ロックファイルを使用して不可分 (atomic) なファイルロックを実現し、
NFS が
O_EXCL
をサポートしているかに依存しないようにしたい場合、
移植性のある方法は、同じファイルシステム上に他と名前の重ならない
ファイル (例えばホスト名と PID を組み合わせた名前) を作成し、
link(2)
を使用してそのロックファイルへのリンクを作成することである。
link(2)
コールの返り値が 0 ならばロックに成功している。
あるいは、そのファイルに
stat(2)
を使用してリンク数 (link count) が 2 になっているかをチェックする。
そうなっていれば、同じくロックに成功しているということである。
- O_LARGEFILE
-
(LFS)
off_t
ではサイズを表せない (だだし
off64_t
ではサイズを表せる) ファイルをオープン可能にする。
この定義を有効にするためには、
_LARGEFILE64_SOURCE
マクロを定義しなければならない。
32ビットシステムにおいて大きなファイルにアクセスする方法を得たい場合、
(O_LARGEFILE
を使うよりも)
_FILE_OFFSET_BITS
機能検査マクロをセットする方が望ましい方法である
(feature_test_macros(7)
を参照)。
- O_NOATIME (Linux 2.6.8 以降)
-
ファイルに対して
read(2)
が実行されたときに、最終アクセス時刻 (inode の st_atime) を更新しない。
このフラグはインデックス作成やバックアッププログラムで使うことを意図している。
これを使うとディスクに対する操作を大幅に減らすことができる。
このフラグは全てのファイルシステムに対して有効であるわけではない。
その一例が NFS であり、サーバがアクセス時刻を管理している。
- O_NOCTTY
-
pathname
が端末 (terminal) デバイス
---
tty(4)
参照
---
を指している場合に、たとえそのプロセスが制御端末を持っていなくても、
オープンしたファイルは制御端末にはならない。
- O_NOFOLLOW
-
pathname がシンボリック・リンクだった場合、オープンは失敗する。
これは FreeBSD の拡張で、Linux には 2.1.126 より追加された。
pathname の前のコンポーネント (earlier component;
訳註: 最後のディレクトリセパレータより前の部分) が
シンボリック・リンクである場合には、それが指す先が参照される。
- O_NONBLOCK または O_NDELAY
-
可能ならば、ファイルは非停止 (nonblocking) モードでオープンされる。
open()
も、返したファイル・ディスクリプタに対する以後のすべての操作も
呼び出したプロセスを待たせることはない。
FIFO (ネームド・パイプ) を扱う場合には
fifo(7)
も参照すること。
強制ファイルロック (mandatory file lock) やファイルリース (file lease)
と組み合わせた場合の、
O_NONBLOCK
の効果についての議論は、
fcntl(2)
を参照すること。
- O_SYNC
-
ファイルは同期 (synchronous) I/O モードでオープンされる。
open()
が返したファイル・ディスクリプタに対して
write(2)
を行うと、必ず呼び出したプロセスをブロックし、
該当ハードウェアに物理的に書き込まれるまで返らない。
以下の「注意」の章も参照。
- O_TRUNC
-
ファイルが既に存在し、通常ファイルであり、
書き込み可モードでオープンされている
(つまり、
O_RDWRまたはO_WRONLY
の) 場合、長さ 0 に切り詰め (truncate) られる。
ファイルが FIFO または端末デバイスファイルの場合、
O_TRUNC
フラグは無視される。
それ以外の場合、
O_TRUNC
の効果は未定義である。
これらの選択フラグのいくつかはファイルをオープンした後でも
fcntl(2)
を使用して変更することができる。
creat()
は
flags
に
O_CREAT|O_WRONLY|O_TRUNC
を指定して
open()
を行うのと等価である。
返り値
open()
と
creat()
は新しいファイル・ディスクリプタを返す。
エラーが発生した場合は -1 を返す
(その場合は
errno
が適切に設定される)。
エラー
- EACCES
-
ファイルに対する要求されたアクセスが許されていないか、
pathname
のディレクトリ部分の何れかのディレクトリに検索許可がなかった。
またはファイルが存在せず、親ディレクトリへの書き込み許可がなかった。
(path_resolution(7)
も参照すること。)
- EEXIST
-
pathname
は既に存在し、
O_CREAT と O_EXCL
が使用された。
- EFAULT
-
pathname
の指す領域がアクセス可能なアドレス空間にない。
- EFBIG
-
EOVERFLOW
参照。
- EINTR
-
遅いデバイス
(例えば FIFO、
fifo(7)
参照) のオープンが完了するのを待って停止している間に
システムコールがシグナルハンドラにより割り込まれた。
signal(7)
参照。
- EISDIR
-
pathname
はディレクトリを参照しており、書き込み要求が含まれていた
(つまり
O_WRONLY
または
O_RDWR
が設定されている)。
- ELOOP
-
pathname
を解決する際に遭遇したシンボリック・リンクが多過ぎる。
または O_NOFOLLOW が指定されており、
pathname
がシンボリックリンクだった。
- EMFILE
-
プロセスがオープンしているファイル数がすでに最大数に達している。
- ENAMETOOLONG
-
pathname
が長過ぎる。
- ENFILE
-
オープンできるファイルの合計数がシステム制限に達している。
- ENODEV
-
pathname
がデバイス・スペシャル・ファイルを参照しており、対応するデバイスが存在しない。
(これは Linux カーネルのバグであり、この場合には
ENXIO
が返されるべきである)
- ENOENT
-
O_CREAT
が設定されておらず、かつ指定されたファイルが存在しない。
または、
pathname
のディレクトリ部分が存在しないか壊れた (dangling) シンボリック・リンクである。
- ENOMEM
-
カーネルに利用できるメモリが不足している
- ENOSPC
-
pathname
を作成する必要があるが、
pathname
を含んでいるデバイスに新しいファイルのための空き容量がない。
- ENOTDIR
-
pathname
に含まれるディレクトリ部分のどれかが実際にはディレクトリでない。
または O_DIRECTORY が指定されており、
pathname
がディレクトリでない。
- ENXIO
-
O_NONBLOCK | O_WRONLY
が設定されており、指定したファイルが FIFO で
そのファイルを読み込みのためにオープンしているプロセスが存在しない。
または、ファイルがデバイス・スペシャル・ファイルで
対応するデバイスが存在しない。
- EOVERFLOW
-
pathname
が参照しているのが、大き過ぎてオープンできない通常のファイルである。
通常、このエラーが発生するは、32 ビットプラットフォーム上で
-D_FILE_OFFSET_BITS=64
を指定せずにコンパイルされたアプリケーションが、ファイルサイズが
(2<31)-1
ビットを超えるファイルを開こうとした場合である。
上記の
O_LARGEFILE
も参照。
これは POSIX.1-2001 で規定されているエラーである。
2.6.24 より前のカーネルでは、Linux はこの場合にエラー
EFBIG
を返していた。
- EPERM
-
O_NOATIME
フラグが指定されたが、呼び出し元の実効ユーザー ID が
ファイルの所有者と一致せず、かつ呼び出し元に特権
(CAP_FOWNER)
がない。
- EROFS
-
pathname
が読み込み専用のファイルシステム上のファイルを参照しており、
書き込みアクセスが要求された。
- ETXTBSY
-
pathname
が現在実行中の実行イメージを参照しており、書き込みが要求された。
- EWOULDBLOCK
-
O_NONBLOCK
フラグが指定されたが、そのファイルには矛盾するリースが設定されていた
(fcntl(2)
参照)。
準拠
SVr4, 4.3BSD, POSIX.1-2001.
フラグ
O_DIRECTORY,
O_NOATIME,
O_NOFOLLOW
は Linux 特有のものであり、
これらのフラグの定義を得るためには、
_GNU_SOURCE
を定義する必要があるかもしれない。
O_CLOEXEC
フラグは POSIX.1-2001 では規定されていないが、
POSIX.1-2008 で規定されている。
O_DIRECT
は POSIX では規定されていない。
O_DIRECT
の定義を得るには
_GNU_SOURCE
を定義しなければならない。
注意
Linux では、
O_NONBLOCK
フラグは、
open を実行したいが read または write を実行する意図は
必ずしもないことを意味する。
これは
ioctl(2)
のためのファイルディスクリプタを取得するために、
デバイスをオープンするときによく用いられる。
「アクセスモード」の値
O_RDONLY, O_WRONLY, O_RDWR
は、
flags
に指定できる他の値と違い、個々のビットを指定するものではなく、
これらの値は
flags
の下位 2 ビットを定義する。
O_RDONLY, O_WRONLY, O_RDWR
はそれぞれ 0, 1, 2 に定義されている。
言い換えると、
O_RDONLY | O_WRONLY
の組み合わせは論理的に間違いであり、確かに
O_RDWR
と同じ意味ではない。
Linux では、特別な、非標準なアクセスモードとして 3 (バイナリでは 11) が
予約されており
flags
に指定できる。
このアクセスモードを指定すると、ファイルの読み出し/書き込み許可をチェックし、
読み出しにも書き込みにも使用できないディスクリプタを返す。
この非標準のアクセスモードはいくつかの Linux ドライバで使用されており、
デバイス固有の
ioctl(2)
操作にのみ使用されるディスクリプタを返すために使われている。
O_RDONLY | O_TRUNC
の影響は未定義であり、その動作は実装によって異なる。
多くのシステムではファイルは実際に切り詰められる。
NFS を実現しているプロトコルには多くの不備があり、特に
O_SYNC と O_NDELAY
に影響する。
POSIX では、3 種類の同期 I/O が提供されており、
O_SYNC,
O_DSYNC,
O_RSYNC
フラグがこれに対応するものである。
今のところ (カーネル 2.6.31)、
Linux では
O_SYNC
だけが実装されているが、
glibc は
O_DSYNC
と
O_RSYNC
に
O_SYNC
と同じ数値を割り当てている。
ほとんどの Linux のファイルシステムは、実際には POSIX の
O_SYNC
の動作ではなく
O_DSYNC
の動作だけを実装している。
POSIX の
O_SYNC
では、
open()
がユーザ空間に返る際に、書き込みに関する全てのメタデータの
更新がディスクに書き込まれている必要がある。
一方、
O_DSYNC
では、
open()
が返るまでに、実際のファイルのデータとそのデータを取得するために
必要なメタデータだけがディスクに書き込まれていればよい。
open()
はスペシャル・ファイルをオープンすることができるが、
creat()
でスペシャル・ファイルを作成できない点に注意すること。
代わりに
mknod(2)
を使用する。
UID マッピングを使用している NFS ファイル・システムでは、
open()
がファイル・ディスクリプタを返した場合でも
read(2)
が EACCES で拒否される場合がある。
これはクライアントがアクセス許可のチェックを行って
open()
を実行するが、読み込みや書き込みの際には
サーバーで UID マッピングが行われるためである。
ファイルが新しく作成されると、
ファイルの
st_atime,
st_ctime,
st_mtime
フィールド
(それぞれ最終アクセス時刻、最終状態変更時刻、最終修正時刻である。
stat(2)
参照) が現在時刻に設定される。
さらに親ディレクトリの
st_ctime
と
st_mtime
も現在時刻に設定される。
それ以外の場合で、O_TRUNC フラグでファイルが修正されたときは、
ファイルの
st_ctime
と
st_mtime
フィールドが現在時刻に設定される。
O_DIRECT
O_DIRECT
フラグを使用する場合、ユーザ空間バッファの長さやアドレス、
I/O のファイルオフセットに関してアラインメントの制限が課されることがある。
Linux では、アラインメントの制限はファイルシステムやカーネルのバージョンに
よって異なり、全く制限が存在しない場合もある。
しかしながら、現在のところ、指定されたファイルやファイルシステムに対して
こうした制限があるかを見つけるための、アプリケーション向けのインタフェースで
ファイルシステム非依存のものは存在しない。
いくつかのファイルシステムでは、制限を確認するための独自のインタフェースが
提供されている。例えば、
xfsctl(3)
の
XFS_IOC_DIOINFO
命令である。
Linux 2.4 では、転送サイズ、
ユーザーバッファのアラインメント、ファイルオフセットは、
ファイルシステムの論理ブロックサイズの倍数でなければならない。
Linux 2.6 では、512 バイトごとの境界に配置されていれば充分である。
O_DIRECT
フラグは SGI IRIX で導入された。SGI IRIX にも Linux 2.4 と同様の
(ユーザーバッファの) アラインメントの制限がある。
また、IRIX には適切な配置とサイズを取得するための
fcntl(2)
コールがある。
FreeBSD 4.x も同じ名前のフラグを導入したが、アラインメントの制限はない。
O_DIRECT
が Linux でサポートされたのは、カーネルバージョン 2.4.10 である。
古い Linux カーネルは、このフラグを単に無視する。
O_DIRECT
フラグをサポートしていないファイルシステムもあり、その場合は、
O_DIRECT
を使用すると
open()
は
EINVAL
で失敗する。
アプリケーションは、同じファイル、
特に同じファイルの重複するバイト領域に対して、
O_DIRECT
と通常の I/O を混ぜて使うのは避けるべきである。
ファイルシステムがこのような状況において一貫性の問題を正しく
扱うことができる場合であっても、全体の I/O スループットは
どちらか一方を使用するときと比べて低速になるであろう。
同様に、アプリケーションは、同じファイルに対して
mmap(2)
と直接 I/O
(O_DIRECT)
を混ぜて使うのも避けるべきである。
NFS で
O_DIRECT
を使った場合の動作はローカルのファイルシステムの場合と違う。
古いカーネルや、ある種の設定でコンパイルされたカーネルは、
O_DIRECT
と NFS の組み合わせをサポートしていないかもしれない。
NFS プロトコル自体はサーバにフラグを渡す機能は持っていないので、
O_DIRECT
I/O はクライアント上のページキャッシュをバイパスするだけになり、
サーバは I/O をキャッシュしているかもしれない。
クライアントは、
O_DIRECT
の同期機構を保持するため、サーバに対して I/O を同期して行うように依頼する。
サーバによっては、こうした状況下、特に I/O サイズが小さい場合に
性能が大きく劣化する。
また、サーバによっては、I/O が安定したストレージにまで行われたと、
クライアントに対して嘘をつくものもある。
これは、サーバの電源故障が起こった際にデータの完全性が保たれない
危険は少しあるが、性能面での不利な条件を回避するために行われている。
Linux の NFS クライアントでは
O_DIRECT
I/O
でのアラインメントの制限はない。
まとめると、
O_DIRECT
は、注意して使うべきであるが、強力なツールとなる可能性を持っている。
アプリケーションは
O_DIRECT
をデフォルトでは無効になっている性能向上のためのオプションと
考えておくのがよいであろう。
-
「O_DIRECT でいつも困るのは、インタフェース全部が本当にお馬鹿な点だ。
たぶん危ないマインドコントロール剤で
頭がおかしくなったサルが設計したんじゃないかな」 --- Linus
バグ
現在のところ、
open()
の呼び出し時に
O_ASYNC
を指定してシグナル駆動 I/O を有効にすることはできない。
このフラグを有効にするには
fcntl(2)
を使用すること。
関連項目
chmod(2),
chown(2),
close(2),
dup(2),
fcntl(2),
link(2),
lseek(2),
mknod(2),
mmap(2),
mount(2),
openat(2),
read(2),
socket(2),
stat(2),
umask(2),
unlink(2),
write(2),
fopen(3),
feature_test_macros(7),
fifo(7),
path_resolution(7),
symlink(7)
Index
- 名前
-
- 書式
-
- 説明
-
- 返り値
-
- エラー
-
- 準拠
-
- 注意
-
- O_DIRECT
-
- バグ
-
- 関連項目
-
This document was created by
man2html,
using the manual pages.
Time: 03:26:50 GMT, April 25, 2010