2017-2018-1 20155205 《信息安全系統設計基礎》第四周學習總結


2017-2018-1 20155205 《信息安全系統設計基礎》第四周學習總結

課上實踐--myod-系統調用版本

  • 要求:

    1.參考教材第十章內容
    2.用Linux IO相關系統調用編寫myod.c 用myod XXX實現Linux下od -tx -tc XXX的功能,注意XXX是文件名,通過命令行傳入,不要讓用戶輸入文件名
    3.不要把代碼都寫入main函數中
    4.要分模塊,不要把代碼都寫入一個.c中
    5.提交測試代碼和運行結果截圖,提交調試過程截圖,要全屏,包含自己的學號信息
    6.課上上傳代碼到碼雲
    

head,tail的相關學習

相關API的分析

  • head
    • 語法:head [參數] 文件
    • 命令功能:head用來顯示檔案的開頭至標准輸出當中,默認head命令打印其相應文件的開頭10行。

 -c<字符數>:指定顯示頭部內容的字符數
-n<數字>:指定顯示頭部內容的行數

來自: http://man.linuxde.net/head

  • tail
    • 功能:顯示指定文件的后若干行。
    • 語法: tail [+ / - num ] [參數] 文件
    • tail命令中各個選項的含義為:+num 從第num行以后開始顯示。-num 從距文件尾 num行處開始顯示。如果省略 num參數,系統默認值為 10。

  • 使用tail命令的-f選項可以方便的查閱正在改變的日志文件,tail -f filename會把filename里最尾部的內容顯示在屏幕上,並且不但刷新,使你看到最新的文件內容。

偽代碼,產品代碼,測試代碼的編寫

  • myhead

偽代碼:

打開文件;
循環按字符讀入文件,每讀一個換行符計數器加一;
讀滿10個換行符停止輸出;
結束程序

產品代碼:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc,char *argv[])
{

    int fd,c=0;
    char ch;
    fd=open(argv[1],O_RDONLY,0);
    if(fd==-1)
    {
        printf("出現錯誤!");
        exit(1);
    }
    while(read(fd,&ch,1)!=0)
    {
        printf("%c",ch);
        if(ch=='\n') c++;
        if(c==10) break;
    }//方法參考p599圖10-2程序,將while循環中的write(fd,&ch,1)改為從屏幕輸出字符,並加入了判斷。
    close(fd);
    exit(0);
}

  • tail

偽代碼:

打開文件;
循環按字符第一次讀入文件,統計總共的行數;
再次讀入文件,當行數>=總行數-10時輸出字符;
結束程序

產品代碼:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc,char *argv[])
{

    int fd1,fd2,c=0,n=0;
    char ch;

    fd1=open(argv[1],O_RDONLY,0);
    if(fd1==-1)
    {
        printf("出現錯誤!");
        exit(1);
    }
    while(read(fd1,&ch,1)!=0)
      {
          if(ch=='\n') c++;
       }
    close(fd1);

    fd2=open(argv[1],O_RDONLY,0);
    while(read(fd2,&ch,1)!=0)
      {
          if(ch=='\n') n++;
          if(n>=c-10)printf("%c",ch);
       }

    close(fd2);
    exit(0);
}

教材學習中的問題和解決過程

  • 問題1:練習題10.1程序的輸出為什么是3?即打開文件和文件描述符的關系是什么?

  • 問題1解決方案:

    查閱資料后有段話解釋了我的問題:

在Linux系統中一切皆可以看成是文件,文件又可分為:普通文件、目錄文件、鏈接文件和設備文件。文件描述符(file descriptor)是內核為了高效管理已被打開的文件所創建的索引,其是一個非負整數(通常是小整數),用於指代被打開的文件,所有執行I/O操作的系統調用都通過文件描述符。程序剛剛啟動的時候,0是標准輸入,1是標准輸出,2是標准錯誤。如果此時去打開一個新的文件,它的文件描述符會是3,再調用open 就會返回4。

而且我了解到

每個進程在Linux內核中都有一個task_struct結構體來維護進程相關的 信息,稱為進程描述符(Process Descriptor),而在操作系統理論中稱為進程控制塊 (PCB,Process Control Block)。task_struct中有一個指針(struct files_struct *files; )指向files_struct結構體,稱為文件 描述符表,其中每個表項包含一個指向已打開的文件的指針,如下圖所示。

用戶程序不能直接訪問內核中的文件描述符表,而只能使用文件描述符表的索引 (即0、1、2、3這些數字),這些索引就稱為文件描述符(File Descriptor),用int 型變量保存。 當調用open 打開一個文件或創建一個新文件時,內核分配一個文件描述符並返回給用戶程序,該文件描述符表項中的指針指向新打開的文件。當讀寫文件時,用戶程序把文件描述符傳給read 或write ,內核根據文件描述符找到相應的表項,再通過表項中的指針找到相應的文件。

這就加深了我對打開文件和文件描述符的理解,也知道了家庭作業10.6的答案:因為調用了兩次open函數,所以返回值是4,然后調用close釋放了描述符4,再次調用open返回值又是4了,所以輸出是4。

自己敲代碼驗證了一下:

代碼學習中的問題和解決過程

  • 問題1:運行程序時遇到了頭文件csapp.h錯誤的情況
  • 問題1解決方案:csapp.h其實就是一堆頭文件的打包,在http://csapp.cs.cmu.edu/public/code.html 這里可以下載。《深入理解計算機系統》配套網站
    下載並解壓后(以 root 身份登錄)應該是一個code的文件夾,在其子文件夾include和src中分別可以找到csapp.h和csapp.c兩個文件,把這兩個文件拷貝到文件夾/usr/include里面,並在csapp.h文件中 #endif 之前加上一句 #include<csapp.h> ,然后編譯時在最后加上 “-lpthread” 例如:gcc main.c -lpthread 就可以編譯了。

代碼鏈接

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM