操作系統第四次實驗報告——文件系統之使用LinuxAPI實現ls -lai命令

来源:https://www.cnblogs.com/MilkoSilver/archive/2020/04/30/12806078.html
-Advertisement-
Play Games

0 個人信息 張櫻姿 201821121038 計算1812 1 實驗目的 通過編程進一步瞭解文件系統。 2 實驗內容 在伺服器上用Vim編寫一個程式:實現Linux系統命令ls -lai的功能 給出運行結果截圖,對於每一列是如何獲取的,結合源代碼做解釋 3 實驗報告 3.1 ls -lai簡介 l ...


0 個人信息

  • 張櫻姿
  • 201821121038
  • 計算1812

1 實驗目的

  • 通過編程進一步瞭解文件系統。

2 實驗內容

  • 在伺服器上用Vim編寫一個程式:實現Linux系統命令ls -lai的功能
  • 給出運行結果截圖,對於每一列是如何獲取的,結合源代碼做解釋

3 實驗報告

  3.1 ls -lai簡介

ls -l   #以長格式顯示目錄下的內容列表。輸出的信息從左到右依次包括文件名,文件類型、許可權模式、硬連接數、所有者、組、文件大小和文件的最後修改時間等
ls -a   #顯示所有檔案及目錄(ls內定將檔案名或目錄名稱為“.”的視為影藏,不會列出)
ls -i   #顯示文件索引節點號(inode number),一個索引節點代表一個文件

  3.2 實現過程

    3.2.1 獲取文件信息的函數及文件信息結構體

     stat函數:

#include<sys/stat.h>
int stat(const char * path,struct stat * buf); /*將path參數(文件或目錄)的文件信息寫到buf中,buf為傳出參數*/

     stat結構體:

struct stat{
    dev_t st_dev;            //設備id號(無需用到)
    ino_t st_ino;            //索引節點號
    mode_t st_mode;          //許可權與文件類型
    nlink_t st_nlink;        //硬鏈接數
    uid_t st_uid;            //用戶id
    ggid_t st_gid;           //所在組id
    dev_t st_rdev;           //設備id,對於特殊文件才有(無需用到)
    off_t st_size;           //大小,較為常用
    blksize_t st_blocks;     //文件系統I/O的塊大小(無需用到)
    blkcnt_t st_blksize;     //分配的512B(扇區)塊數(無需用到)
    time_t st_atime;         //最後的訪問時間(無需用到)
    time_t st_mtime;         //最後的修改時間,較為常用
    time_t st_ctime;         //最後的狀態改變時間(無需用到)
}                    

       因此,需對上述相應欄位格式化處理。

    3.2.2 mode許可權與類型判斷

     判斷文件類型的巨集函數:

    S_ISREG(m)  is it a regular file?  //判斷是否是普通文件
    S_ISDIR(m)  directory?             //判斷是否是目錄
    S_ISCHR(m)  character device?      //判斷是否是字元設備
    S_ISBLK(m)  block device?          //判斷是否是塊設備
    S_ISFIFO(m) FIFO (named pipe)?     //判斷是否是管道文件
    S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)//判斷使是否是符號鏈接(軟連接)
    S_ISSOCK(m) socket? (Not in POSIX.1-1996.)       //判斷是否是SOCKET文件

     文件許可權巨集變數:

        S_IRUSR     00400     //用戶有讀許可權
        S_IWUSR     00200     //用戶有寫許可權
        S_IXUSR     00100     //用戶有執行許可權
        S_IRGRP     00040     //組有讀許可權
        S_IWGRP     00020     //組有寫許可權
        S_IXGRP     00010     //組有執行許可權
        S_IROTH     00004     //其他人有讀許可權
        S_IWOTH     00002     //其他人有寫許可權
        S_IXOTH     00001     //其他人有可執行許可權       

    3.2.3 目錄操作函數及目錄信息結構體

     opendir函數及readdir函數:

DIR * opendir(const char * name);    //打開一個目錄
struct dirent * readdir(DIR *);      //讀目錄,依次返回目錄的子項

      dirent結構體:

struct dirent{
    ino_t d_ino;    //子項的i節點
    off_t d_off;    //節點的偏移量
    unsigned short d_reclen;//長度
    unsigned char d_type;   //子項類型(常用)
    char d_name[256];       //子文件名(常用)
};

    3.2.4 表示時間的方式

     ①秒差形式,1970年1月1日0時0分0秒的秒數差,得到的類型為time_t;

    ②結構形式,tm結構體:

struct tm{
    int tm_sec;  //Second [0,60].包含閏秒
    int tm_min;  //Minutes [0,59].
    int tm_hour; //Hour [0,23].
    int tm_mday; //Day of month [1,31].
    int tm_mon;  //Month of year [0,11].(January = 0)
    int tm_year; //Year Since 1900.
    int tm_wday; //Day of week [0,6] (Sunday = 0).
    int tm_yday; //Day of year [0,365].包含閏年
    int tm_isdat;//Daylight Savings flag
}

    電腦大多數情況使用time_t,因為效率高。但是顯示時為tm結構形式。localtime()函數可以實現: time_t 到 tm 的轉換。time_t的指針做參數,返回值tm的指針。

  3.3 源代碼

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<time.h>
  5 #include<unistd.h>
  6 #include<sys/types.h>
  7 #include<dirent.h>
  8 #include<grp.h>
  9 #include<pwd.h>
 10 #include<errno.h>
 11 #include<sys/stat.h>
 12 #include<limits.h>
 13 #include<assert.h>
 14 
 15 int flag = 0;
 16 //用於分析參數
 17 void AnalPara(int argc,char *argv[],char *path)
 18 {
 19     int i = 0;
 20     for(i = 1;i < argc; ++i)
 21     {    //如果argv[i]中第一個字元是'-',則判斷是l a i中的哪些
 22         if(strncmp(argv[i],"-",1)==0)
 23         {
 24             //參數為a時,把1賦值給flag,flag所在記憶體中第一個位置為1
 25             if(strstr(argv[i],"a") != NULL)
 26             {
 27                 flag |= 1 << 0; ////-a參數顯示該隱藏文件
 28             }
 29             //參數為l時,第二個位置為1
 30             if(strstr(argv[i],"l") != NULL)
 31             {
 32                 flag |= 1 << 1;    //-l參數顯示該文件的詳細信息
 33             }
 34             //參數為i時,第三個位置為1
 35             if(strstr(argv[i],"i") != NULL)
 36             {
 37                 flag |= 1 << 2;    //-i參數顯示該文件的inode number
 38             }
 39             //位運算可使用一個變數同時標記多個參數是否傳遞
 40         }
 41         //如果argv[i]中第一個字元不是'-',則判斷所給路徑是直接路徑還是間接路徑
 42         else
 43         {
 44             //直接路徑,copy到path字元數組中
 45             if(strncmp(argv[i],"/",1) == 0)
 46             {
 47                 strcpy(path,argv[i]);
 48             }
 49             //間接路徑,將當前路徑與所給路徑連接
 50             else
 51             {
 52                 strcat(path,"/");
 53                 strcat(path,argv[i]);
 54             }
 55         }
 56     }
 57 }
 58 //用於輸出文件名
 59 void PrintfFileName(int mode,int uid,char *name)
 60 {
 61     //是目錄文件
 62     if(S_ISDIR(mode))
 63     {
 64         //文件名顯示為藍色
 65         printf("\33[1;34m%s\033[0m ",name);
 66     }
 67     //是普通文件
 68     else if(S_ISREG(mode))
 69     {
 70         if(mode & S_IXUSR||mode & S_IXGRP||mode & S_IXOTH)
 71         {
 72             if(uid==0) //屬主用戶,文件名顯示為紅色
 73                 printf("\33[41;37m%s\033[0m ",name);
 74             else       //其他用戶,文件名顯示為綠色
 75                 printf("\33[1;32m%s\033[0m ",name);
 76         }
 77         else
 78         {
 79             printf("%s ",name);
 80         }
 81     }
 82     else
 83     {
 84         printf("%s ",name);
 85     }
 86 }
 87 //用於輸出文件詳細信息
 88 void PrintMoreInfo(int mode,struct stat st)
 89 {    //文件許可權判斷
 90     char str[10] = {"----------"};
 91 
 92     if(S_ISDIR(mode)) str[0] = 'd';
 93     if(S_ISCHR(mode)) str[0] = 'c';
 94     if(S_ISBLK(mode)) str[0] = 'b';
 95 
 96     if(mode & S_IRUSR) str[1] = 'r';
 97     if(mode & S_IWUSR) str[2] = 'w';
 98     if(mode & S_IXUSR) str[3] = 'x';
 99 
100     if(mode & S_IRGRP) str[4] = 'r';
101     if(mode & S_IWGRP) str[5] = 'w';
102     if(mode & S_IXGRP) str[6] = 'x';
103 
104     if(mode & S_IROTH) str[7] = 'r';
105     if(mode & S_IWOTH) str[8] = 'w';
106     if(mode & S_IXOTH) str[9] = 'x';
107 
108     int i = 0;
109     for(; i < 10; i++)
110     {
111         printf("%c",str[i]);
112     }
113     printf(". ");
114     printf("%ld ",st.st_nlink);
115     //輸出屬主
116     struct passwd *pd = getpwuid(st.st_uid);
117     assert(pd != NULL);
118     printf("%4s ",pd->pw_name);
119     //輸出組用戶
120     struct group *gp = getgrgid(st.st_gid);
121     assert(gp != NULL);
122     printf("%4s ",gp->gr_name);
123     //輸出文件大小
124     printf("%4ld ",st.st_size);
125     //輸出最近操作時間
126     struct tm * lchangetime = localtime(&(st.st_mtime));
127     printf("%d %d %d:%d ",(lchangetime->tm_mon+1),lchangetime->tm_mday,lchangetime->tm_hour,lchangetime->tm_min);
128 }
129 
130 int main(int argc,char *argv[])
131 {
132     char path[128]={0};
133     //獲取當前路徑
134     getcwd(path,127);
135     //參數分析函數
136     AnalPara(argc,argv,path);
137     //打開該目錄並建立一個目錄流
138     DIR *dir = opendir(path);
139     if(dir == NULL)
140     {
141         char *p = path + strlen(path);
142         while(*p != '/')
143             p--;
144         p++;
145         printf("ls:can not access %s:No such file or directory\n",p);
146         exit(0);
147     }
148     //需要使用dirent結構體中的文件名和文件的inode number
149     struct dirent *dr = NULL;
150     //調用readdir函數獲取該目錄中的目錄項
151     while((dr = readdir(dir)) != NULL)
152     {    
153         //當文件名第一個字元是.時,為隱藏文件,不輸出
154         if(((flag&1)==0) && (strncmp(dr->d_name,".",1) == 0))
155         {
156             continue;
157         }
158 
159         struct stat st;
160         char temp[128] = {0};
161         strcpy(temp,path);
162         strcat(temp,"/");
163         strcat(temp,dr->d_name);
164         stat(temp,&st);
165         //-li
166         if ((flag&2)==2)
167         {
168             //有參數i
169             if((flag&4)==4)
170             {
171                 printf("%ld  ",st.st_ino);
172             }
173             //有參數l
174             PrintMoreInfo(st.st_mode,st);
175             PrintfFileName(st.st_mode,st.st_uid,dr->d_name);
176             printf("\n");
177             continue;
178         }
179         //-ai
180         if((flag&4)==4)
181         {
182             printf("%ld  ",dr->d_ino);
183             PrintfFileName(st.st_mode,st.st_uid,dr->d_name);
184             continue;
185         }
186         //-a
187         PrintfFileName(st.st_mode,st.st_uid,dr->d_name);
188     }
189     if(argc == 1||(argc >1&&flag == 0))
190         printf("\n");
191     closedir(dir);
192 }

  3.4 分析結果

    3.4.1 ls -lai運行結果:

 

 

     3.4.2 ./myls -lai運行結果:

     3.4.3 分析輸出格式:

    第一列為文件/目錄的索引編號(inode number),如果是目錄,則使用dirent結構體中的d_ino獲取;如果是文件,則使用stat結構體中的st_ino獲取。

    第二列為文件的許可權,第一位的-表示不同的文件類型(普通文件,管道文件)。後面九位分別表示,該文件的屬主,組用戶和其他用戶的讀、寫、執行三種不同的許可權。

    第三列為文件的硬鏈接數,如果是一個目錄,則第2欄位表示該目錄所含子目錄的個數。使用stat結構體中的st_nlink獲取。

    第四列為屬主用戶,使用stat結構體中的st_uid獲取。

    第五列為組用戶,使用stat結構體中的st_gid獲取。

    第六列為文件所占用的大小,以位元組為單位,如果是目錄文件,則表示該目錄的大小,而不是該目錄下所有文件的大小。使用stat結構體中的st_size獲取。

    第七列為最後修改時間,使用stat結構體中的st_mtime獲取。

    第八列為文件名,使用dirent結構體中的d_name獲取。

4 References

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題外話: 接上篇吧。上篇主要是介紹下LayUI的使用,太興奮手打代碼去了- -。 其實這個項目用了Unity這個IOC框架,畢竟人要有夢想。感興趣的可以自己去瞭解下,後面有機會會說說對於IOC和DI的個人拙見以及Unity的使用。 進入正題。 二.WebApi 一個有夢想的鹹魚做的一個有夢想的dem ...
  • netcore數據連接配置 第一種 appsettings.json ConfigureServices 第二種 ConfigureServices ...
  • C 多態性 多態性常被視為自封裝和繼承之後,面向對象的編程的第三個支柱。 Polymorphism(多態性)是一個希臘詞,指“多種形態”, 多態: 一個介面多個功能。 靜態多態性: 編譯時發生函數響應(調用); 動態多態性: 運行時發生函數響應。 靜態綁定(早期綁定): 編譯時函數和對象的連接機制。 ...
  • 目 錄 1. 現象概述... 1 2. 操作資料庫的代碼... 2 3. 引起的異常... 2 4. 異常信息分析... 3 5. 分析結論猜測... 3 1. 現象概述 .NETCore的Console和AspNetCore程式對資料庫進行操作,通過析構函數(Finalize)釋放資料庫連接資源, ...
  • 今天看AspNetCore源代碼發現日誌模塊的設計模式(提供者模式)。 設計模式的好處是,我們可以容易擴展它達到我們要求,除了要知道如何擴展它,還應該在其他地方應用它, ...
  • 哈嘍,又和大家見面了,雖然看文章的小伙伴不多,但是我相信總有一天,自己寫的這些文章或多或少會對其他人有些幫助,讓他們在相關的業務開發下能少走些彎路,那我的目的就達到了,好了,今天就正式開始我們的系列了,今天要講的是金蝶系列的API,大家都知道,金蝶的產品是比較多的,那麼我們這次要講解的就是金蝶雲星空 ...
  • 解決“另一個SqlParameterCollection中已包含SqlParameter”行之有效的方法 ...
  • 1. 安裝adb,查看自己的安卓設備 sudo apt-get install android-tools-adb adb start-server lsusb 輸出信息: Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...