檔案描述符

檔案描述符

核心(kernel)利用檔案描述符(file descriptor)來訪問檔案。檔案描述符是非負整數。打開現存檔案或新建檔案時,核心會返回一個檔案描述符。讀寫檔案也需要使用檔案描述符來指定待讀寫的檔案。

基本信息

簡介

檔案描述符檔案描述符
檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向核心為每一個進程所維護的該進程打開檔案的記錄表。當程式打開一個現有檔案或者創建一個新檔案時,核心向進程返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於UNIX、Linux這樣的作業系統。
習慣上,標準輸入(standardinput)的檔案描述符是0,標準輸出(standardoutput)是1,標準錯誤(standarderror)是2。儘管這種習慣並非Unix核心的特性,但是因為一些shell和很多應用程式都使用這種習慣,因此,如果核心不遵循這種習慣的話,很多應用程式將不能使用。
POSIX定義了STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO來代替0、1、2。這三個符號常量的定義位於頭檔案unistd.h。
檔案描述符的有效範圍是0到OPEN_MAX。一般來說,每個進程最多可以打開64個檔案(0—63)。對於FreeBSD5.2.1、MacOSX10.3和Solaris9來說,每個進程最多可以打開檔案的多少取決於系統記憶體的大小,int的大小,以及系統管理員設定的限制。Linux2.4.22強制規定最多不能超過1,048,576。
檔案描述符是由無符號整數表示的句柄,進程使用它來標識打開的檔案。檔案描述符與包括相關信息(如檔案的打開模式、檔案的位置類型、檔案的初始類型等)的檔案對象相關聯,這些信息被稱作檔案的上下文。
如何創建檔案描述符
進程獲取檔案描述符最常見的方法是通過本機子例程open或create獲取或者通過從父進程繼承。後一種方法允許子進程同樣能夠訪問由父進程使用的檔案。檔案描述符對於每個進程一般是唯一的。當用fork子例程創建某個子進程時,該子進程會獲得其父進程所有檔案描述符的副本,這些檔案描述符在執行fork時打開。在由fcntl、dup和dup2子例程複製或拷貝某個進程時,會發生同樣的複製過程。
對於每個進程,作業系統核心在u_block結構中維護檔案描述符表,所有的檔案描述符都在該表中建立索引。

特點

優點

檔案描述符的好處主要有兩個:
基於檔案描述符的I/O操作兼容POSIX標準。
在UNIX、Linux的系統調用中,大量的系統調用都是依賴於檔案描述符。
例如,下面的代碼就示範了如何基於檔案描述符來讀取當前目錄下的一個指定檔案,並把檔案內容列印至Console中。
此外,在Linux系列的作業系統上,由於Linux的設計思想便是把一切設備都視作檔案。因此,檔案描述符為在該系列平台上進行設備相關的編程實際上提供了一個統一的方法。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
intmain(void){intfd;intnumbytes;charpath[]="file";charbuf[256];/*
*O_CREAT:如果檔案不存在則創建
*O_RDONLY:以唯讀模式打開檔案
*/
fd=open(path,O_CREAT|O_RDONLY,0644);
if(fd<0){perror("open()");
exit(EXIT_FAILURE);}memset(buf,0x00,256);
while((numbytes=read(fd,buf,255))>0){printf("%dbytesread:%s",numbytes,buf);
memset(buf,0x00,256);
}close(fd);
exit(EXIT_SUCCESS);}

缺點

檔案描述符的概念存在兩大缺點:
在非UNIX/Linux作業系統上(如WindowsNT),無法基於這一概念進行編程。
由於檔案描述符在形式上不過是個整數,當代碼量增大時,會使編程者難以分清哪些整數意味著數據,哪些意味著檔案描述符。因此,完成的代碼可讀性也就會變得很差。

定義數量

如何在不同平台上定義檔案描述符的數量
檔案描述符極限以及可分配給進程的最大大小由資源限制來定義。這些值應當按照在WebLogicServer文檔中建議的、特定於作業系統的檔案描述符值來設定:
對於WLS8.1:調整硬體、作業系統和網路性能
對於WLS7.0:調整硬體、作業系統和網路性能
對於WLS6.1:調整硬體、作業系統和網路性能
Unix和Linux都有檔案描述符。不過,二者的主要區別在於如何設定檔案描述符的硬極限值、預設值和配置過程。
Solaris
/usr/bin/ulimit實用程式定義允許單個進程使用的檔案描述符的數量。它的最大值在rlim_fd_max中定義,在預設情況下,它設定為65,536。只有root用戶才能修改這些核心值。
Linux
管理用戶可以在etc/security/limits.conf配置檔案中設定他們的檔案描述符極限,如下例所示。
softnofile1024
hardnofile4096
系統級檔案描述符極限還可以通過將以下三行添加到/etc/rc.d/rc.local啟動腳本中來設定:
#Increasesystem-widefiledescriptorlimit.
echo4096>/proc/sys/fs/file-max
echo16384>/proc/sys/fs/inode-max
Windows
在Windows作業系統上,檔案描述符被稱作檔案句柄。在Windows2000伺服器上,打開檔案的句柄極限設定為16,384。此數量可以在任務管理器的性能摘要中監視。
HP-UX
nfile定義打開檔案的最大數量。此值通常由以下公式來確定:((NPROC*2)+1000),其中NPROC通常為:((MAXUSERS*5)+64)。如果MAXUSERS等於400,則經過計算得到此值為5128。通常可以將此值設高一些。maxfiles是每個進程的軟檔案極限,maxfiles_lim是每個進程的硬檔案極限。
AIX
檔案描述符極限在/etc/security/limits檔案中設定,它的預設值是2000。此極限可以通過ulimit命令或setrlimit子例程來更改。最大大小由OPEN_MAX常數來定義。

解決方法

對於ANSIC規範中定義的標準庫的檔案I/O操作。ANSIC規範給出了一個解決方法,就是使用FILE結構體的指針。事實上,UNIX/Linux平台上的FILE結構體的實現中往往都是封裝了檔案描述符變數在其中。
在UNIX/Linux平台上,對於控制台(Console)的標準輸入,標準輸出,標準錯誤輸出也對應了三個檔案描述符。它們分別是0,1,2。在實際編程中,如果要操作這三個檔案描述符時,建議使用<unistd.h>頭檔案中定義的三個宏來表示:STDIN_FILENO,STDOUT_FILENO以及STDERR_FILENO。與檔案描述符相關的操作
檔案描述符的生成
open(),open64(),creat(),creat64()
socket()
socketpair()
pipe()
與單一檔案描述符相關的操作
read(),write()
recv(),send()
recvmsg(),sendmsg()
sendfile()
lseek(),lseek64()
fstat(),fstat64()
fchmod()
fchown()
與複數檔案描述符相關的操作
select(),pselect()
poll()
與檔案描述符表相關的操作
close()
dup()
dup2()
fcntl(F_DUPFD)
fcntl(F_GETFDandF_SETFD)
改變進程狀態的操作
fchdir()
mmap()
與檔案加鎖的操作
flock()
fcntl(F_GETLK,F_SETLKandF_SETLKW)
lockf()
與套接字相關的操作
connect()
bind()
listen()
accept()
getsockname()
getpeername()
getsockopt(),setsockopt()
shutdown()

熱門詞條

聯絡我們