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 就可以編譯了。