1. 程式人生 > >Linux基礎篇十 ——檔案操作

Linux基礎篇十 ——檔案操作

提起檔案操作我們就不得不說起兩個重要的部分,檔案描述符和檔案指標,相信很多人都會分不清這兩個看起來十分相似的東西,但是,實際上他們兩的差別是十分大的。我們先來看看他們到底是什麼。

檔案描述符:在linux系統中開啟檔案就會獲得檔案描述符,它是個很小的正整數。每個程序在PCB中儲存著一份檔案描述符表檔案描述符就是這個表的索引,每個表項都有一個指向已開啟檔案的指標。

檔案指標:C語言中使用檔案指標做為I/O的控制代碼。檔案指標指向程序使用者區中的一個被稱為FILE結構的資料結構。FILE結構包括一個緩衝區和一個檔案描述符。而檔案描述符是檔案描述符表的一個索引,因此從某種意義上說檔案指標就是控制代碼的控制代碼(在Windows系統上,檔案描述符被稱作檔案控制代碼)。

每個程序在PCB中都儲存著一份檔案描述符表,檔案描述符就是這個表的索引,已開啟的檔案在核心中用file結構體表示,檔案描述符表中的指標指向file結構體。在file結構體中維護File Status Flag(file結構體的成員f_flags)和當前讀寫位置(file結構體的成員f_pos)。每個file結構體都指向一個file_operations結構體,這個結構體的成員都是函式指標,指向實現各種檔案操作的核心函式。

eg:在使用者程式中read一個檔案描述符,read通過系統呼叫進入核心,然後找到這個檔案描述符所指向的file結構體,找到file結構體所指向的file_operations

結構體,呼叫它的read成員所指向的核心函式以完成使用者請求。

每個file結構體都有一個指向dentry結構體的指標我們傳給openstat等函式的引數的是一個路徑,例如/home/akaedu/a,需要根據路徑找到檔案的inode為了減少讀盤次數,核心快取了目錄的樹狀結構,稱為dentry cache,其中每個節點是一個dentry結構體,只要沿著路徑各部分的dentry搜尋即可

每個dentry結構體都有一個指標指向inode結構體inode結構體儲存著從磁碟inode讀上來的資訊。

inode結構體有一個指向super_block結構體的指標。super_block結構體儲存著從磁碟分割槽的超級塊讀上來的資訊


#include <stdio.h>
#include <errno.h>
#include <string.h>
#define _PATH_ "./log"
int main()
{
FILE *fp = fopen(_PATH_, "w");
if( NULL == fp ){
printf("%s open file %s error, error code is : %d\n",__FUNCTION__, _PATH_, error);
return 1;
}
char *str = "this is a test\n";
int i=0;
while( i<100 ){
fwrite(str, 1, strlen(str),fp);
i++;
}
fclose(fp);
return 0;
}
上面的例子裡我們使用的是fwrite,接下來再讓我們看一個write符來操作檔案的例子
#include <unistd.h>
#include <stdio.h>
int glob = 6; 
char buf[] = "a write to stdout\n";
int
main(void)
{
int var;
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
perror("write error");
printf("before fork\n"); /* we don't flush stdout */
if ((pid = fork()) < 0) {
perror("fork error");
}else if (pid == 0) { /* child */
glob++; /* modify variables */
var++;
}else {
sleep(2); /* parent*/
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,var);
exit(0);
}
**write是不帶緩衝的(系統呼叫不帶緩衝)

**標準I/O是緩衝的,標準輸出到終端是行緩衝,否則就變成了全緩衝。

有時將結構定位到標準輸出和檔案裡出現的結果是不同的,但是我們不必感到困惑,只不過是父程序的緩衝區的內容還沒被刷新出來之前就被子程序複製了,所以子程序也會在

程式結束的時候在檔案裡刷新出重複的內容。

**父子程序的使用相同的描述符共享操作同一個檔案。

fork之後處理的⽂件描述符有兩種常見的情況:
⽗程序等待⼦程序完成。在這種情況下,⽗程序⽆需對其描述符做任何處理。當⼦程序終⽌後,⼦程序對⽂件偏移量的修改已執⾏的更新。
⽗⼦程序各⾃執⾏不同的程式段這種情況下,在fork之後,⽗⼦程序各⾃關閉他們不需要使⽤的⽂件描述符,這樣就不會⼲擾對⽅使⽤⽂件描述符。