Linux系統程式設計之獲取檔案資訊

2021-06-21 23:55:43 字數 4393 閱讀 4596

利用系統呼叫stat()、lstat()以及fstat(),可獲取與檔案有關的資訊,其中大部分提取自檔案i節點。以上3個系統呼叫之間僅有的區別在於對檔案的描述方式不同。

1  stat()返回所命名檔案的相關資訊。

2  lstat()與stat()類似,區別在於如果檔案屬於符號鏈結,那麼所返回的資訊針對的是符號鏈結自身(而非符號鏈結所指向的檔案)。

3  fstat()則返回由某個開啟檔案描述符所指代檔案的相關資訊。

系統呼叫stat()和lstat()不需要對所操作的檔案本身擁有任何許可權,但針對指定pathname的父目錄要有執行(搜尋)許可權。而只要為它提供有效的檔案描述符,fstat()系統呼叫總是成功的。

上述所有系統呼叫都會在緩衝區中返回乙個由statbuf指向的stat結構,其格式如下:

裝置id和i節點號

st_dev欄位標識檔案所駐留的裝置。st_ino欄位包含了檔案的i節點號。利用這兩個字段,可以在所有檔案系統中唯一表示某個檔案。

如果是針對裝置的i節點,那麼st_rdev欄位則包含裝置的主、輔id。利用巨集major()和minor(),可以提取主、輔id。在linux系統上,要使用這兩個巨集,需要定義_bsd_source巨集,然後include定義這兩個巨集的標頭檔案。

由於major()和minor()所返回的整型值大小隨uinx實現的不同而各有不用。為保證可移植性,列印時總是將返回值強制轉換為long。

檔案所有權

st_uid和st_gid欄位分別表示檔案的屬主(使用者id)和屬組(組id)。

鏈結數

st_nlink欄位包含了指向檔案的(硬)鏈結數。

檔案型別及許可權

st_mode欄位內含有位掩碼,起表示檔案型別和指定檔案許可權的雙重作用。下圖為該字段所含各位的布局情況。 

檔案型別 許可權

ugtrwxr

wxrw

xlinux使用了st_mode欄位中的4位來標識檔案型別位。st_mode欄位與常量s_ifmt相與(&),可從該字段中提取出檔案型別。將計算結果與一系列常量進行比較,即可確定檔案型別:

if((statbuf.st_mode & s_ifmt) == s_ifreg)

printf(「regularfile\n」);

在linux中可利用標準巨集將其簡化:

if(s_isreg(statbuf.st_mode))

printf(「regularfile\n」);

常  量

測  試  巨集

文  件  類  型

s_ifreg

s_isreg()

常規檔案

s_ifdir

s_isdir()

目錄s_ifchr

s_ischr()

字元裝置

s_ifblk

s_isblk()

塊裝置s_ififo

s_isfifo()

fifo或管道

s_ifsock

s_issock()

套接字s_iflnk

s_islnk()

符號鏈結

針對stat結構中的st_mode來檢查檔案型別的巨集

想從中獲取s_ifsock和s_issock()的定義,必須定義_bsd_source特性測試巨集,或將_xopen_source定義為不小於500的值。

st_mode欄位的低12位定義了檔案許可權。最低9位分別用來表示檔案屬主、屬組以及其他使用者的讀、寫、執行許可權。

檔案大小、已分配塊以及最優i/o塊大小

對於常規檔案,st_size欄位表示檔案的位元組數。對於符號鏈結,st_size欄位則表示鏈結所指路徑名的長度,以位元組為單位。對於共享記憶體物件,該字段則表示物件的大小。

st_blocks欄位表示分配給檔案的總塊數,塊大小為512位元組,其中包括了為指標塊所分配的空間。st_blocks欄位記錄了實際分配給檔案的磁碟塊數量。如果檔案內含空洞,該值將小於從相應檔案位元組數字段(st_size)的值。

st_blksize欄位所指並非底層檔案系統的塊大小,而是針對檔案系統上檔案進行i/o操作時的最優塊大小(以位元組為單位)。一般而言,st_blksize的返回值為4096。

檔案時間戳

st_time、st_mtime和st_ctime欄位,分別記錄了對檔案的上次訪問時間、上次修改時間以及檔案狀態傳送改變的上次時間。這3個字段的型別都是time_t,記錄了自新紀元(epoch)以來的秒數。

示例程式

(獲取並解釋檔案的stat資訊)

#define _bsd_source

#include #include #include #include #include #include #include #define fp_special 1

#define str_size sizeof("rwxrwxrwx")

typedef enum boolean;

static char *filepermstr(mode_t perm, int flags)

static void showstatinfo(struct stat *st)

printf("device containing i-node: major=%ld minor=%ld\n",

(long) major(st->st_dev), (long) minor(st->st_dev));

printf("i-node number: %ld\n", (long) st->st_ino);

printf("mode: %lo (%s)\n", (unsigned long) st->st_mode,

filepermstr(st->st_mode, 0));

if (st->st_mode & (s_isuid| s_isgid| s_isvtx))

printf(" special bits set: %s%s%s\n",

(st->st_mode & s_isuid) ? "set-uid " : "",

(st->st_mode & s_isgid) ? "set-gid " : "",

(st->st_mode & s_isvtx) ? "sticky " : "");

printf("number of (hard) links: %ld\n", (long) st->st_nlink);

printf("ownership: uid=%ld gid=%ld\n",

(long) st->st_uid, (long) st->st_gid);

if (s_ischr(st->st_mode) || s_isblk(st->st_mode))

printf("device number (st_rdev): major=%ld; minor=%ld\n",

(long) major(st->st_rdev), (long) minor(st->st_rdev));

printf("file size: %lld bytes\n", (long long) st->st_size);

printf("optimal i/o block size: %ld bytes\n", (long) st->st_blksize);

printf("512b blocks allocated: %lld\n", (long long) st->st_blocks);

printf("last file access: %s\n", ctime(&st->st_atime));

printf("last file modification: %s\n", ctime(&st->st_mtime));

printf("last status change: %s\n", ctime(&st->st_ctime));

}int main(int argc, char *argv)

} else

showstatinfo(&st);

exit(1);

}

以下是執行結果:

Linux系統程式設計之檔案程式設計

目錄 一 檔案程式設計 1 linux檔案 2 檔案描述符 file descriptor 3 常用api open write read lseek close 1 open 開啟檔案函式 2 close 關閉檔案 3 write 寫檔案 4 read 讀檔案 5 lseek 游標定位 linux...

系統程式設計之檔案系統程式設計

系統呼叫 所有的作業系統都提供多種服務的入口點,程式由此向核心請求服務。這些可直接進入核心的入口點被稱為系統呼叫。不同作業系統提供了自己的一套系統呼叫,所以系統呼叫無法實現跨平台使用。而且頻繁地系統呼叫,在使用者態和核心態之間切換,很耗費資源,效率不高。c標準庫提供了操作檔案的標準i o函式庫,與系...

linux系統程式設計之檔案I O

一 檔案描述符 linux系統中,所有開啟的檔案都對應乙個數字,這個數字由系統來分配,稱為檔案描述符。pcb程序控制塊裡有檔案描述符表,以陣列形式存放於核心區。乙個程序預設開啟3個檔案描述符 stdin fileno 0 stdout fileno 1 stderr fileno 2 新開啟檔案返回...