open - システムコールの説明 - Linux コマンド集 一覧表
名前
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 ファイル・ディスクリプタ・フラグは最初は無効である)。 ファイル・オフセット (file offset) はファイルの先頭に設定される ( lseek (2)参照)。
open ()を呼び出すと、「オープンファイル記述」 "(open file description)" が作成される。ファイル記述とは、システム全体の オープン中のファイルのテーブルのエントリである。 このエントリは、ファイル・オフセットとファイル状態フラグ ( fcntl () 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
, and
O_TRUNC
である。
ファイル状態フラグ
は以下のリストのうち上記以外の残りのものである。
二種類のフラグの違いは、ファイル状態フラグの方は
fcntl
(2) を使ってその内容を取得したり (場合によっては) 変更したりできる点にある。
ファイル作成フラグとファイル状態フラグの全リストを以下に示す:
- O_APPEND
- ファイルを追加 (append) モードでオープンする。 毎回の write ()の前に lseek ()を行ったかのように、ファイル・ポインターをファイルの最後に移動する。 NFS ファイル・システムで、 O_APPEND を使用すると、複数のプロセスがひとつのファイルに同時にデータを追加した場合、 ファイルが壊れてしまうことがある。 これは NFS が追加モードをサポートしていないため、 クライアントのカーネル (kernel) がそれをシミュレートしなければならないのだが、 競合状態を避けることはできないからである。
- O_ASYNC
- シグナル駆動 I/O (signal-driven I/O) を有効にする: このファイル・ディスクリプタへの 入力または出力が可能になった場合に、シグナルを生成する (デフォルトは SIGIO であるが、 fcntl (2) によって変更可能である)。 この機能が使用可能なのは端末、疑似端末、ソケットのみであり、 (Linux 2.6 以降では) パイプと FIFO に対しても使用できる。 さらに詳しい説明は fcntl (2) を参照すること。
- O_CREAT
- ファイルが存在しなかった場合は作成 (create) する。 ファイルの所有者 (ユーザー ID) は、プロセスの実効ユーザー ID に設定される。 グループ所有権 (グループ ID) は、プロセスの実効グループ ID または親ディレクトリのグループ ID に設定される (これは、ファイルシステムタイプ、マウントオプション、 親ディレクトリのモードに依存する。 例えば、 mount (8) で説明されている ext2 ファイルシステムのマウントオプション bsdgroups と sysvgroups を見よ)。
- O_DIRECT
-
このファイルに対する I/O のキャッシュの効果を最小化しようとする。
このフラグを使うと、一般的に性能が低下する。
しかしアプリケーションが独自にキャッシングを行っているような
特別な場合には役に立つ。
ファイルの I/O はユーザー空間バッファに対して直接行われる。
I/O は同期で行われる。
すなわち
read
(2) および
write
(2) が完了した時点で、データの転送が完了したことが保証される。
Linux 2.4 では、転送サイズ、
ユーザーバッファのアラインメント、ファイルオフセットは、
ファイルシステムの論理ブロックサイズの倍数でなければならない。
Linux 2.6 では、512 バイトごとの境界に配置されていれば充分である。
ブロックデバイスに対する似通った意味のインターフェースが raw (8) で説明されている (但し、このインタフェースは非推奨である)。 - O_DIRECTORY
- pathname がディレクトリでなければオープンは失敗する。 このフラグは Linux 特有であり、 opendir (3) が FIFO やテープデバイスに対してコールされた場合の サービス不能 (denial-of-service) 攻撃を避けるために カーネル 2.1.126 で追加された。 しかしこれは opendir の実装以外では使用するべきではない。
- O_EXCL
- O_CREAT と一緒に使用された場合、 ファイルが既に存在した場合はエラーとなり、 open ()は失敗する。 この場合、シンボリックリンクであっても存在するうちに入り、 それがどこを指しているかにはよらない。 O_EXCL は NFS ファイル・システムでは機能しない、 このフラグでロック (lock) 機能を実現するプログラムは、 競合条件を含むだろう。 ロックファイルを使用した分解不能 (atomic) のロック機能の解決には 同じファイル・システムに他と名前の重ならないファイル (例えばホスト名と pid の組み合わせ) を作成し、 link (2) を使用してそのロックファイルへのリンクを作成する。 link () コールの返り値が 0 ならばロックに成功している。 あるいは、そのファイルに stat (2) を使用してリンク数 (link count) が 2 になっているかをチェックする。 そうなっていれば、同じくロックに成功しているということである。
- O_LARGEFILE
- (LFS) off_t ではサイズを表せない (だだし off64_t ではサイズを表せる) ファイルをオープン可能にする。
- O_NOATIME
- (Linux 2.6.8 以降) ファイルに対して read (2) が実行されたときに、最終アクセス時刻 (inode の st_atime) を更新しない。 このフラグはインデックス作成やバックアッププログラムで使うことを意図している。 これを使うとディスクに対する操作を大幅に減らすことができる。 このフラグは全てのファイルシステムに対して有効であるわけではない。 その一例が NFS であり、サーバがアクセス時刻を管理している。
- O_NOCTTY
- pathname が端末 (terminal) デバイス \(em tty (4) 参照 \(em を指している場合に、たとえそのプロセスが制御端末を持っていなくても、 オープンしたファイルは制御端末にはならない。
- O_NOFOLLOW
- pathname がシンボリック・リンクだった場合、オープンは失敗する。 これは FreeBSD の拡張で、Linux には 2.1.126 より追加された。 pathname の前のコンポーネント (earlier component; 訳註: 最後のディレクトリセパレータより前の部分) が シンボリック・リンクである場合には、それが指す先が参照される。
- O_NONBLOCK または O_NDELAY
-
可能ならば、ファイルは非停止 (non-blocking) モードでオープンされる。
open
()も、返したファイル・ディスクリプタに対する以後のすべての操作も
呼び出したプロセスを待たせることはない。
FIFO (ネームド・パイプ) を扱う場合には
fifo
(7) も参照すること。
強制ファイルロック (mandatory file lock) やファイルリース (file lease)
と組み合わせた場合の、
O_NONBLOCK
の効果についての議論は、
fcntl
(2) を参照すること。
- O_SYNC
- ファイルは同期 (synchronous) I/O モードでオープンされる。 open ()が返したファイル・ディスクリプタに対して write ()を行うと、必ず呼び出したプロセスをブロックし、 該当ハードウェアに物理的に書き込まれるまで返らない。 以下の「制限」の章も参照。
- O_TRUNC
-
ファイルが既に存在し、通常ファイルであり、
書き込み可モードでオープンされている
(つまり、O_RDWR または O_WRONLY の) 場合、
長さ 0 に切り詰め (truncate) られる。
ファイルが FIFO または端末デバイスファイルの場合、
O_TRUNC フラグは無視される。
それ以外の場合、O_TRUNC の効果は未定義である。
これらの選択フラグのいくつかはファイルをオープンした後でも fcntl ()を使用して変更することができる。
引き数 mode は新しいファイルを作成する場合に使用するアクセス許可 (permission) を指定する。 それはプロセスの 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 他人に実行の許可がある。
flags に O_CREAT が指定されている場合は、 mode を指定しなければならない。 それ以外の場合は無視される。
creat ()は flags に O_CREAT|O_WRONLY|O_TRUNC を指定して open ()を行うのと等価である。
返り値
open ()と creat ()は新しいファイル・ディスクリプタを返す。 エラーが発生した場合は -1 を返す (その場合は errno が適切に設定される)。
注意
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 フィールドが現在時刻に設定される。
エラー
- EACCES
- ファイルに対する要求されたアクセスが許されていないか、 pathname のディレクトリ部分の何れかのディレクトリに検索許可がなかった。 またはファイルが存在せず、親ディレクトリへの書き込み許可がなかった。 ( path_resolution (2)も参照すること。)
- EEXIST
- pathname は既に存在し、 O_CREAT と O_EXCL が使用された。
- EFAULT
- pathname の指す領域がアクセス可能なアドレス空間にない。
- 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
- 大きすぎてオープンできない通常のファイルを参照した; 上記の O_LARGEFILE を参照。
- EPERM
- O_NOATIME フラグが指定されたが、呼び出し元の実効ユーザー ID が ファイルの所有者と一致せず、かつ呼び出し元に特権 ( CAP_FOWNER )がない。
- EROFS
- pathname が読み込み専用のファイルシステム上のファイルを参照しており、 書き込みアクセスが要求された。
- ETXTBSY
- pathname が現在実行中の実行イメージを参照しており、書き込みが要求された。
- EWOULDBLOCK
- O_NONBLOCK フラグが指定されたが、そのファイルには矛盾するリースが設定されていた ( fcntl (2)参照)。
注意
Linux では、O_NONBLOCK フラグは、 open を実行したいが read または write を実行する意図は 必ずしもないことを意味する。 これは ioctl (2) のためのファイルディスクリプタを取得するために、 デバイスをオープンするときによく用いられる。
準拠
SVr4, 4.3BSD, POSIX.1-2001. O_NOATIME , O_NOFOLLOW , O_DIRECTORY フラグは Linux 特有のものである。 これらのフラグの定義を使うためには、 _GNU_SOURCE マクロを定義する必要があるかもしれない。
O_RDONLY | O_TRUNC の影響は未定義であり、その動作は実装によって異なる。 多くのシステムではファイルは実際に切り詰められる。
O_DIRECT フラグは SGI IRIX で導入され、 (ユーザーバッファの) アラインメントの制限は Linux 2.4 と同じである。 IRIX には適切な配置とサイズを取得するための fcntl(2) コールがある。 FreeBSD 4.x もこのフラグを導入したが、アラインメントに制限はない。 このフラグが Linux でサポートされたのは、 カーネルバージョン 2.4.10 である。 古い Linux カーネルは、このフラグを単に無視する。 このフラグの定義を有効にするには _GNU_SOURCE を定義しておく必要があるかもしれない。
バグ
「O_DIRECT でいつも困るのは、インタフェース全部が本当にお馬鹿な点だ。
たぶん危ないマインドコントロール剤で
頭がおかしくなったサルが設計したんじゃないかな」 \(em Linus
現在のところ、
open
()の呼び出し時に
O_ASYNC
を指定してシグナル駆動 I/O を有効にすることはできない。
このフラグを有効にするには
fcntl
(2) を使用すること。
制限
NFS を実現しているプロトコルには多くの不備があり、特に
O_SYNC
と
O_NDELAY
に影響する。
POSIX では、フラグ O_SYNC
, O_DSYNC
, O_RSYNC
に対応する
3 種類の同期 I/O を提供している。
Linux では、今のところ (カーネル 2.1.130) これらは同じものである。