open() - Unix,Linux系統呼叫 - 技術教學
Tutorials Point


  Unix入門
  Unix Shell程式設計
  高階Unix
  Unix有用參考
  Unix有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  首頁     參考資料     討論論壇     關於TP  

open() - Unix,Linux系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

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);

描述

給定檔案的路徑名open() 返回一個檔案描述符,一個小的非負整數,用於後續的系統呼叫(read(2), write(2), lseek(2), fcntl(2) 等)。成功呼叫返回的檔案描述符將是當前程序中未開啟的最低編號的檔案描述符。

新的檔案描述符設定為在 execve(2) 中保持開啟狀態(即,fcntl(2) 中描述的 FD_CLOEXEC 檔案描述符標誌最初被停用)。檔案偏移量設定為檔案的開頭(參見 lseek(2))。

呼叫 open() 會建立一個新的開啟的檔案描述,這是系統範圍內開啟檔案表中的一個條目。此條目記錄檔案偏移量和檔案狀態標誌(可透過 fcntl() F_SETFL 操作進行修改)。檔案描述符是對這些條目之一的引用;如果隨後刪除路徑名或將其修改為引用不同的檔案,則此引用不受影響。新的開啟的檔案描述最初不與任何其他程序共享,但可以透過 fork(2) 實現共享。

引數flags必須包含以下訪問模式之一:O_RDONLYO_WRONLYO_RDWR。這些分別請求以只讀、只寫或讀寫方式開啟檔案。

此外,零個或多個檔案建立標誌和檔案狀態標誌可以按位flags中。檔案建立標誌O_CREATO_EXCLO_NOCTTYO_TRUNC檔案狀態標誌是下面列出的所有其餘標誌。這兩組標誌的區別在於,可以使用 fcntl(2) 檢索和(在某些情況下)修改檔案狀態標誌。檔案建立標誌和檔案狀態標誌的完整列表如下所示

標籤描述
O_APPEND
 檔案以追加模式開啟。在每次write() 之前,檔案偏移量將定位到檔案的末尾,就像使用lseek() 一樣。如果多個程序同時將資料追加到同一個檔案中,O_APPEND 可能會導致 NFS 檔案系統上的檔案損壞。這是因為 NFS 不支援追加到檔案,因此客戶端核心必須模擬它,而這無法在沒有競爭條件的情況下完成。
O_ASYNC
 啟用訊號驅動的 I/O:當此檔案描述符上的輸入或輸出變為可能時,生成一個訊號(預設為 SIGIO,但這可以透過 fcntl(2) 更改)。此功能僅適用於終端、偽終端、套接字和(自 Linux 2.6 起)管道和 FIFO。有關更多詳細資訊,請參見 fcntl(2)。
O_CREAT
 如果檔案不存在,則將建立它。檔案的擁有者(使用者 ID)設定為程序的有效使用者 ID。組所有權(組 ID)設定為程序的有效組 ID 或父目錄的組 ID(取決於檔案系統型別和掛載選項以及父目錄的模式,例如,請參見 ext2 檔案系統的掛載選項bsdgroupssysvgroups,如 mount(8) 中所述)。
O_DIRECT
 嘗試最大限度地減少此檔案的 I/O 對快取的影響。通常,這會降低效能,但在特殊情況下很有用,例如當應用程式自己進行快取時。檔案 I/O 直接在使用者空間緩衝區之間進行。I/O 是同步的,即在 read(2) 或 write(2) 完成時,保證資料已傳輸。在 Linux 2.4 下,傳輸大小和使用者緩衝區以及檔案偏移量的對齊必須都是檔案系統邏輯塊大小的倍數。在 Linux 2.6 下,對齊必須適合裝置的塊大小。

raw(8) 中描述了塊裝置的一種語義上相似(但已棄用)的介面。

O_DIRECTORY
 如果路徑名不是目錄,則導致開啟失敗。此標誌是 Linux 特定的,是在核心版本 2.1.126 中新增的,用於避免在對 FIFO 或磁帶裝置呼叫 opendir(3) 時出現拒絕服務問題,但不應在 opendir 的實現之外使用。
O_EXCL 當與 O_CREAT 一起使用時,如果檔案已存在,則這是一個錯誤,並且 open() 將失敗。在這種情況下,符號連結存在,無論它指向哪裡。O_EXCL 在 NFS 檔案系統上已損壞;依賴它來執行鎖定任務的程式將包含競爭條件。使用鎖定檔案執行原子檔案鎖定的解決方案是在同一檔案系統上建立唯一檔案(例如,包含主機名和 pid),使用 link(2) 建立指向鎖定檔案的連結。如果 link() 返回 0,則鎖定成功。否則,對唯一檔案使用 stat(2) 檢查其連結計數是否已增加到 2,在這種情況下,鎖定也成功。
O_LARGEFILE
 (LFS)允許開啟大小無法用off_t表示(但可以用off64_t表示)的檔案。
O_NOATIME
 (自 Linux 2.6.8 起)在讀取檔案時不更新檔案上次訪問時間(inode 中的 st_atime)。此標誌旨在供索引或備份程式使用,在其使用中可以顯著減少磁碟活動量。此標誌可能並非對所有檔案系統都有效。一個例子是 NFS,其中伺服器維護訪問時間。
O_NOCTTY
 如果路徑名指的是終端裝置——參見tty(4)——即使程序沒有一個,它也不會成為程序的控制終端。
O_NOFOLLOW
 如果路徑名是符號連結,則開啟失敗。這是 FreeBSD 的擴充套件,在版本 2.1.126 中新增到 Linux。路徑名中較早的元件中的符號連結仍將被遵循。
O_NONBLOCKO_NDELAY
 如果可能,則以非阻塞模式開啟檔案。返回的檔案描述符上的 open() 或任何後續操作都不會導致呼叫程序等待。對於 FIFO(命名管道)的處理,另請參見 fifo(7)。有關 O_NONBLOCK 與強制檔案鎖和檔案租約結合使用時的影響的討論,請參見 fcntl(2)。

O_SYNC 檔案以同步 I/O 方式開啟。結果檔案描述符上的任何 write() 都將阻塞呼叫程序,直到資料已物理寫入底層硬體。但請參見下面的限制
O_TRUNC
 如果檔案已存在並且是常規檔案,並且開啟模式允許寫入(即 O_RDWR 或 O_WRONLY),則它將被截斷為長度 0。如果檔案是 FIFO 或終端裝置檔案,則忽略 O_TRUNC 標誌。否則,O_TRUNC 的效果未指定。
開啟檔案後,可以使用 fcntl() 更改其中一些可選標誌。

引數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 其他使用者具有讀、寫和執行許可權
S_IROTH
 00004 其他使用者具有讀許可權
S_IWOTH
 00002 其他使用者具有寫許可權
S_IXOTH
 00001 其他使用者具有執行許可權
如果 O_CREAT 位於flags中,則必須指定mode,否則將忽略它。

creat() 等效於 open(),其中flags等於 O_CREAT|O_WRONLY|O_TRUNC

返回值

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_CREATO_EXCL
EFAULT pathname指向您可訪問的地址空間之外。
EISDIR pathname指向一個目錄,並且請求的訪問涉及寫入(即,設定了O_WRONLYO_RDWR)。
ELOOP 解析pathname時遇到過多符號連結,或者指定了O_NOFOLLOWpathname是符號連結。
EMFILE 程序已開啟最大數量的檔案。
ENAMETOOLONG
  pathname太長。
ENFILE 已達到系統對開啟檔案總數的限制。
ENODEV pathname指向一個裝置特殊檔案,並且不存在相應的裝置。(這是Linux核心錯誤;在這種情況下,必須返回ENXIO。)
ENOENT 未設定O_CREAT,並且指定的檔案不存在。或者,pathname中的目錄元件不存在或是不存在的符號連結。
ENOMEM 可用核心記憶體不足。
ENOSPC 要建立pathname,但是包含pathname的裝置沒有足夠空間容納新檔案。
ENOTDIR
 pathname中用作目錄的元件實際上不是目錄,或者指定了O_DIRECTORYpathname不是目錄。
ENXIO 設定了O_NONBLOCK | O_WRONLY,指定的檔案是FIFO,並且沒有程序開啟該檔案以進行讀取。或者,該檔案是裝置特殊檔案,並且不存在相應的裝置。
EOVERFLOW
  pathname指向一個常規檔案,太大而無法開啟;請參見上面的O_LARGEFILE。
EPERM 指定了O_NOATIME標誌,但呼叫者的有效使用者ID與檔案所有者不匹配,並且呼叫者沒有特權(CAP_FOWNER)。
EROFS pathname指向只讀檔案系統上的檔案,並且請求了寫訪問。
ETXTBSY
  pathname指向當前正在執行的可執行映像,並且請求了寫訪問。
EWOULDBLOCK
 指定了O_NONBLOCK標誌,並且在檔案上持有不相容的租約(參見fcntl(2))。

注意

在Linux下,O_NONBLOCK標誌表示希望開啟但並不一定有讀取或寫入的意圖。這通常用於開啟裝置以獲取用於ioctl(2)的檔案描述符。

符合標準

SVr4、4.3BSD、POSIX.1-2001。O_NOATIMEO_NOFOLLOWO_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一直困擾我的地方在於,整個介面都很愚蠢,可能是某個精神錯亂的猴子在服用某種強效精神控制藥物時設計的。”——Linus

當前,呼叫open()時無法透過指定O_ASYNC來啟用訊號驅動的I/O;使用fcntl(2)來啟用此標誌。

限制

NFS底層的協議中存在許多缺陷,影響到O_SYNCO_NDELAY等。

POSIX提供了三種不同型別的同步I/O,分別對應於標誌O_SYNCO_DSYNCO_RSYNC。目前(2.1.130)在Linux下它們都是同義詞。

參見



previous next Printer Friendly

廣告


  

廣告



廣告
© . All rights reserved.