天天看點

20191320-2021-2022-1-diocs 學習筆記4

第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操作

20191320-2021-2022-1-diocs 學習筆記4

教材上的圖檔充分展示了檔案操作執行的原理和操作,分為核心的以及使用者進行的操作。

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都是核心參數。

基礎系統調用函數:

​int mkdir(char *pathname, int privilege);​

​建立以pathname為名的路徑,其權限為privilege。傳回-1為失敗,傳回1為成功。

​int rmdir(char *pathname);​

​移除目錄(此目錄必須為空目錄)。

​int chdir(char *pathname);​

​更改目前路徑到pathname。

​char *getcwd(char *buf,size_t size);​

​将目前工作目錄的絕對路徑複制到參數buffer所指的記憶體空間中,參數size為buf的空間大小。

​int access(const char *pathname, int mode);​

​access函數用來判斷指定的檔案或目錄是否存在。

​int chmod(char *path, mode_t mode);​

​更改某個檔案的權限。

​int chown(char *name, int uid, int gid);​

​更改某個檔案的所有者。

​int link(char *oldpath, char *newpath);​

​連結新檔案名到舊檔案名(硬連結)

​int unlink(char *pathname);​

​減少檔案連結數,如果連結數為0,就删除檔案

​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;
}
      

運作截圖:

20191320-2021-2022-1-diocs 學習筆記4

問題與解決:

在實作的過程中遇到報錯,檢視錯誤代碼傳回為17,對應的是檔案已存在,但是沒有沒有傳入已有的檔案名?

經檢查是對argc,argv的功能了解錯誤,argv[0]存儲的是檔案本身的名稱,如果i的初始值為0,就會出錯,我剛開始時,i的初始值就是設為0,而不是從1開始,在調整後,程式正常運作并建立了目錄。

資料:

argc 是 argument count的縮寫,表示傳入main函數的參數個數;

argv 是 argument vector的縮寫,表示傳入main函數的參數序列或指針,并且第一個參數argv[0]一定是程式的名稱,并且包含了程式所在的完整路徑,是以确切的說需要我們輸入的main函數的參數個數應該是argc-1個;

文本檔案的讀取