第7章 檔案操作——教材知識點歸納
7.1檔案操作級别
linux中檔案操作可以分為5個級别,從低等級到高等級分别為:
1.硬體級别:
fdisk:将盤進行分區。
mkfs:格式化磁盤分區。
fsck:檢查系統。
碎片整理:壓縮檔案系統中的檔案
2.核心中的檔案系統函數
由k開頭,從作業系統核心層面提供檔案操作支援。
3.系統調用
使用者模式程式使用系統調用來通路核心函數。常見函數有open()、read()、lseek()、close()等,在第8章中有相關内容。
4.I/O庫函數
使用庫函數進行檔案操作,在第9章中有相關内容。
5.使用者指令
直接在終端進行檔案操作使用的指令。
7.2檔案I/O操作

教材上的圖檔充分展示了檔案操作執行的原理和操作,分為核心的以及使用者進行的操作。
7.3低級别檔案操作
磁盤可以被劃分成多個邏輯單元,稱為分區。作業系統引導程式可以從不同的分區引導不同的作業系統。有主引導記錄(MBR)。MBR可以将硬碟分為多個區,擴充分區在擴充分區區域内形成一個連結清單,對應多個分區。
fdisk将一個儲存設備進行分區。而僅僅使用fdisk完成的分區并不能使用,還需要格式化分區。格式化分區的作用是為特定的檔案系統準備分區,來存儲檔案。使用的是mkfs指令。
7.4-7.5 ext2檔案系統
Linux使用的預設檔案系統就是ext2。ext2檔案系統總共有1440個塊,每個塊大小1KB。其中B0是引導塊,檔案系統不使用,它用于容納引導作業系統時使用的引導程式。
B1是超級塊,用于容納關于整個檔案系統的資訊。
第8章 使用系統調用進行檔案操作——教材知識點歸納
8.1~8.2系統調用和I/O庫函數
作業系統中,程序以兩種不同的方式運作:核心模式(Kmode)和使用者模式(Umode)。Umode權限有限,特殊權限的操作需要在Kmode下進行。系統調用(System Call)機制允許程序進入Kmode,執行更高權限的操作。
Linux系統調用手冊頁儲存在
/usr/man/
目錄中,Ubuntu儲存在
/usr/share/man
目錄。
8.3使用系統調用進行檔案操作
系統調用由程式發出,每個系統調用是一個庫函數,彙集系統調用參數,最終向核心發出系統調用。
系統調用:
int syscall(int a, int b, int c, int d);
其中a為系統調用編号,b、c、d都是核心參數。
基礎系統調用函數:
建立以pathname為名的路徑,其權限為privilege。傳回-1為失敗,傳回1為成功。
int mkdir(char *pathname, int privilege);
移除目錄(此目錄必須為空目錄)。
int rmdir(char *pathname);
更改目前路徑到pathname。
int chdir(char *pathname);
将目前工作目錄的絕對路徑複制到參數buffer所指的記憶體空間中,參數size為buf的空間大小。
char *getcwd(char *buf,size_t size);
access函數用來判斷指定的檔案或目錄是否存在。
int access(const char *pathname, int mode);
更改某個檔案的權限。
int chmod(char *path, mode_t mode);
更改某個檔案的所有者。
int chown(char *name, int uid, int gid);
連結新檔案名到舊檔案名(硬連結)
int link(char *oldpath, char *newpath);
減少檔案連結數,如果連結數為0,就删除檔案
int unlink(char *pathname);
為檔案建立一個符号連結
int symlink(char *oldpath, char *newpath);
重命名檔案
int rename(char *oldpath, char *newpath);
更改檔案通路時間和修改時間。
int utime(char *pathname, struct utimebuf *time);
8.4常用的系統調用
常用檔案操作:
擷取檔案狀态資訊
int stat(char *filename, struct stat *buf);
打開一個檔案進行讀、寫
int open(char *file, int flags,int mode);
關閉打開的檔案描述符
int close(int fd);
讀取
int read(int fd, char buf[], int count);
寫入
int write(int fd, char buf[], int count);
8.5連結檔案
連結的含義:每個檔案都有一個路徑名稱,但Linux中允許不同的路徑對應同一個檔案,這就是連結檔案。
連結分為:硬連結、軟連結(符号連結)
硬連結:硬連結檔案共享檔案系統中相同的檔案表示資料結構。硬連結适用于非目錄檔案。
對應操作:
指令:。
ln oldpath newpath
link(char *oldpath, char *newpath)
軟連結(符号連結):newpath是LNK形的普通檔案,作為一個繞行标志,使得通路指向連結好的檔案。(.lnk檔案,我覺得可以了解為Windows系統下的快捷方式)
ln -s oldpath newpath
symlink(char *oldpath, char *newpath)
8.6stat系統調用
stat函數可以用于擷取檔案的狀态。stat函數使用時要先聲明結構體指針用于寫入,傳回值以寫入指針所指結構體的方式傳回。
struct stat {
mode_t st_mode; //檔案相應的模式。檔案,檔案夾等
ino_t st_ino; //inode節點号
dev_t st_dev; //裝置号碼
dev_t st_rdev; //特殊裝置号碼
nlink_t st_nlink; //檔案的連接配接數
uid_t st_uid; //檔案全部者
gid_t st_gid; //檔案全部者相應的組
off_t st_size; //普通檔案。相應的檔案位元組數
time_t st_atime; //檔案最後被訪問的時間
time_t st_mtime; //檔案内容最後被改動的時間
time_t st_ctime; //檔案狀态改變時間
blksize_t st_blksize; //檔案内容相應的塊大小
blkcnt_t st_blocks; //偉建内容相應的塊數量
};
通過使用stat函數,我們就可以知道對應檔案的相關資訊,通過其傳回的結構體擷取相應的資訊。對于路徑,目錄也是一個檔案,我們也可以擷取目錄的資訊,通過這些,完全可以實作一個自己的簡單ls程式 。
8.7open-close-lseek系統調用
檔案在C程式中都是以描述符的形式管理。通過檔案管理,可以對檔案進行讀取、寫入。
int lseek(int fd, int offset, int whence);
将檔案描述符的直接偏移量重新定義。
8.8~8.10 read()系統調用、write系統調用
read()将n個位元組從打開的檔案描述符讀入使用者控件中的buf[]。如果失敗則傳回-1。
write()将n個位元組從buf寫入,以打開檔案描述符方式中的寫、讀寫或追加的形式完成,傳回值為實際寫入的位元組數,通常等于n。
通過使用read()、write()系統調用,可以實作檔案的複制。
實踐内容過程、問題解決過程
實踐了三個内容:
1.編寫C程式一次建立多個目錄
2.文本檔案的讀取和寫入
實作過程:
參照書上C8.1,完成了使用mkdir建立目錄的功能。代碼如下:
#include <stdio.h>
#include <errno.h>
int main(int argc, char * argv[]){
int r;
for(int i=1;i<argc;i++){
r = mkdir(argv[i],0766);
if(r<0){
printf("error occured\n");
return -1;
}
}
return 0;
}
運作截圖:
問題與解決:
在實作的過程中遇到報錯,檢視錯誤代碼傳回為17,對應的是檔案已存在,但是沒有沒有傳入已有的檔案名?
經檢查是對argc,argv的功能了解錯誤,argv[0]存儲的是檔案本身的名稱,如果i的初始值為0,就會出錯,我剛開始時,i的初始值就是設為0,而不是從1開始,在調整後,程式正常運作并建立了目錄。
資料:
argc 是 argument count的縮寫,表示傳入main函數的參數個數;
argv 是 argument vector的縮寫,表示傳入main函數的參數序列或指針,并且第一個參數argv[0]一定是程式的名稱,并且包含了程式所在的完整路徑,是以确切的說需要我們輸入的main函數的參數個數應該是argc-1個;
文本檔案的讀取