1. 程式人生 > >2017-2018-1 20155208 《信息安全系統設計基礎》第四周學習總結

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

duplicate 格式 byname ansi c 安全系統 截圖 能夠 它的 目錄下的文件

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

學習任務

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

Linux下od命令的學習

1、 od命令解釋:

用於輸出文件的八進制、十六進制或其它格式碼的字節,通常用於顯示或查看文件中,不能直接顯示在終端的字符。 常見的文件為文本文件和二進制文件。此命令主要用來查看保存在二進制文件中的值。比如,程序可能輸出大量的數據記錄,每個數據是一個單精度浮點數。這些數據記錄存放在一個文件中,如果想查看下這個數據,這時候od命令就派上用場了。在我看來,od命令主要用來格式化輸出文件數據,即對文件中的數據進行無二義性的解釋。不管是IEEE754格式的浮點數還是ASCII碼,od命令都能按照需求輸出它們的值。

2、參數

命令作用
-a 此參數的效果和同時指定"-ta"參數相同。
-A<字碼基數> 選擇要以何種基數計算字碼。
-b 此參數的效果和同時指定"-toC"參數相同。
-c 此參數的效果和同時指定"-tC"參數相同。
-d 此參數的效果和同時指定"-tu2"參數相同。
-f 此參數的效果和同時指定"-tfF"參數相同。
-h 此參數的效果和同時指定"-tx2"參數相同。
-i 此參數的效果和同時指定"-td2"參數相同。
-j<字符數目>或--skip-bytes=<字符數目> 略過設置的字符數目。
-l 此參數的效果和同時指定"-td4"參數相同。
-N<字符數目>或--read-bytes=<字符數目> 到設置的字符數目為止。
-o 此參數的效果和同時指定"-to2"參數相同。
-s<字符串字符數>或--strings=<字符串字符數> 只顯示符合指定的字符數目的字符串。
-t<輸出格式>或--format=<輸出格式> 設置輸出格式。
-v或--output-duplicates 輸出時不省略重復的數據。
-w<每列字符數>或--width=<每列字符數> 設置每列的最大字符數。
-x 此參數的效果和同時指定"-h"參數相同。
--help 在線幫助。
--version 顯示版本信息

實例效果:

執行下列命令:

echo abcdef g > tmp
 
 cat tmp
 
 od -b tmp

運行結果如圖:

技術分享

3、 用Linux IO相關系統調用編寫myod.c 用myod 實現Linux下od -tx -tc :

技術分享

運行代碼為:

#include <stdio.h>

#include <stdlib.h>

#include"head.h"


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

    int i;
    int n1=0,n2=0,n3=0,n4=0;
    for(i=1;i<argc-1;i++)
    {
        switch(argv[i][2])
        {
            case ‘c‘:n1=1;break;
            case ‘x‘:n2=1;break;
            case ‘d‘:n3=1;break;
            case ‘o‘:n4=1;break;
        }
    }
    FILE *file=fopen(argv[argc-1],"r");
    if(file==NULL){printf("Error!\n");exit(0);}
    myod(file,n1,n2,n3,n4);
    return 0;
}
#include<stdio.h>
void myod(FILE *file,int n1,int n2,int n3,int n4)
{
    char ch,line[16];
    int i;
    int j=0;
    while((ch=fgetc(file))!=EOF){
        line[j%16]=ch;
	if((j+1)%16==0){
        if(n1){for(i=0;i<16;i++)
        {
            if(line[i]==‘\n‘)
            {printf("%5s","\\n");continue;}
	    if(line[i]==‘\t‘)
            {printf("%5s","\\t");continue;}
            putchar(line[i]);
            putchar(‘ ‘);
            putchar(‘ ‘);
            putchar(‘ ‘);
            putchar(‘ ‘);
        }
        putchar(‘\n‘);}
        if(n2){for(i=0;i<16;i++)
        {
            if(line[i]==‘\n‘)
            {printf("0%-4x",‘\n‘);continue;}
	    if(line[i]==‘\t‘)
            {printf("0%-4x",‘\t‘);continue;}
            printf("%-5x",line[i]);
        }
        putchar(‘\n‘);
        }

        if(n3){for(i=0;i<16;i++)
        {
            if(line[i]==‘\n‘)
            {printf("%-5d",‘\n‘);continue;}
	    if(line[i]==‘\t‘)
            {printf("%-5d",‘\t‘);continue;}
            printf("%-5d",line[i]);
        }
        putchar(‘\n‘);
        }
        if(n4){for(i=0;i<16;i++)
        {
            if(line[i]==‘\n‘)
            {printf("%-5o",‘\n‘);continue;}
	    if(line[i]==‘\t‘)
            {printf("%-5o",‘\t‘);continue;}
            printf("%-5o",line[i]);
        }
        putchar(‘\n‘);
        }
        printf("下一行!\n");
	}
	j++;

    }
}

代碼編寫中遇到的問題

問題: 關於char *argv的使用。

解決: 通過查找資料得知 argc是命令行總的參數個數 argv[]是argc個參數,其中第0個參數是程序的全名,以後的參數 命令行後面跟的用戶輸入的參數;

char *argv[]是一個字符數組,其大小是int argc,主要用於命令行參數 argv[] 參數,數組裏每個元素代表一個參數;argc記錄了用戶在運行程序的命令行中輸入的參數的個數 ;arg[]指向的數組中至少有一個字符指針,即arg[0].他通常指向程序中的可執行文件的文件名。在有些版本的編譯器中還包括程序 文件所在的路徑;

教材學習內容總結

第十章學習

  • 輸入/輸出(I/O)是在主存和外部設備(如磁盤驅動器、終端和網絡)之間拷貝數據的過程。輸入操作是從I/O設備拷貝數據到主存,而輸出操作是從主存拷貝數據到I/O設備。

10.1 Unix I/O:

  • 打開文件 1、應用程序向內核發出請求

    2、要求內核打開相應的文件

    3、內核返回文件描述符

  • 一個小的非負整數,用來在後續對此文件的所有操作中標識這個文件叫做文件描述符,有三個已經指定了的文件描述符為:

    標準輸入——0(STDIN_FILENO)

    標準輸出——1(STDOUT_FILENO)

    標準錯誤——2(STDERR_FILENO)

  • 也就是說,在Unix生命周期一開始,0、1、2就被占用,以後的open只能從3開始,並且在UNIX下還有stdin,stdout,stderr表示同樣的含義。

10.2打開和關閉文件

  • 打開文件:int open(char *filename, int flags, mode_t mode)

  • flags參數指明了進程打算如何訪問這個文件:

    O_RDONLY:只讀

    O_WRONLY:只寫

    O_RDWR:可讀可寫

  • flags參數也可以是一個或者更多位掩碼的或:

    O_CREAT:如果文件不存在,就創建它的一個截斷的文件

    O_TRUNC:如果文件已存在,就截斷它

    O_APPEND:在每次寫操作前,設置文件的位置到文件的結尾處

  • 關閉文件

    int close(int fd)

10.3讀和寫文件

1、讀 read

函數原型:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t n);

2、寫 write

函數原型:

#include <unistd.h>
ssize_t write(int fd, void *buf, size_t n);

10.4用RIO包健壯的讀寫

  • 通過調用 rio_readn 和 rio_write函數,應用程序可以在內存和文件之間直接傳送數據。

  • rio_readn函數在遇到EOF時只能返回一個不足值;而rio_write函數絕不會返回不同值;

  • 參數解析:

    fd:文件描述符

    usrbuf:存儲器位置

    n:傳送的字節數

    返回值:

    rio_readn成功則返回傳送的字節數,EOF為0(一個不足值),出錯為-1。

    rio_writen成功則返回傳送的字節數,出錯為-1,沒有不足值。

  • RIO的帶緩沖的輸入函數

    缺點:效率不是很高,每讀取文件中的一個字節都要求陷入內核

10.5 讀取文件元數據

  • 應用程序能夠通過調用stat和fstat函數,檢索到關於文件的信息:元數據

  • 兩種輸入方式:

    stat函數以一個文件名作為輸入

    fstat函數以文件描述符作為輸入

  • stat數據結構中的st_size成員包含了文件的字節數大小,st_mode成員編碼了文件訪問許可位和文件類型。

10.6 共享文件

內核用三個相關的數據結構來表示打開的文件:
  • 描述符表:每個進程都它獨立的描述符表,每個打來的描述符表指向文件表中的一個表項。
  • 文件表:打開文件的集合是由一張文件表來表示的。
  • v-node表:所有進程共享,每個表項包含stat結構中的大多數信息

10.7 I/O重定向

  • 使用dup2函數:

    int dup2(int oldfd,int newfd);

  • dup2函數拷貝描述符表表項oldfd到描述符表表項newfd

10.8 標準I/O

  • 標準I/O庫將一個打開的文件模型化為一個流,一個流就是一個指向FILE類型的結構的指針

  • ANSI C程序開始時有三個打開的流:標準輸入stdin、標準輸出stdout和標準錯誤stderr

  • 類型為FILE的流是對文件描述符和流緩沖區的抽象

附錄A 錯誤處理

錯誤處理風格

  • Unix風格

遇到錯誤後返回-1,並且將全局變量errno設置為指明錯誤原因的錯誤代碼;

如果成功完成,就返回有用的結果。

  • Posix風格

返回0表示成功,返回非0表示失敗;

有用的結果在傳進來的函數參數中。

  • DNS風格

有兩個函數,gethostbyname和gethostbyaddr,失敗時返回NULL指針,並設置全局變量h_errno。

完成head,tail的使用,相關API的分析,偽代碼,產品代碼,測試代碼的編寫

  • head命令用來查看文件的前幾行內容,默認是查看前10行的內容,也可以設置一個數字改變查看行數

head hello.c/*當前目錄下的文件名稱*/

head -20 hello.c

  • tail命令用來查看文件的最後幾行內容,默認是查看最後10行的內容,同樣,也可以設置一個數字改變查看行數

tail -20 hello.c 運行代碼效果如圖:

技術分享

代碼:

#ifndef HEAD_H
#define HEAD_H
void main(int argc,char *argv[]);
void ihead(char *ch[],int n);
#endif
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include"head.h"
#define N 1000
void main(int argc,char *argv[])
{
	char ch[N];
	int i,find,n;
	if((find=open(argv[1],O_RDONLY))==-1)
		{
			perror(argv[1]);
			exit(1);
		}
	n=read(find,ch,N);
	ihead(ch,n);
	close(find);
}
#include<stdio.h>
#include"head.h"
void ihead(char *ch[],int n)
{
	int k,count=0;
	for(k=0;k<n,count<10;i++)
	{
		if(ch[k]!=‘\n‘) 
		printf("%c",ch[k]);
		else {
			count++;
			printf("\n");
		}
	}
}

代碼托管

技術分享

碼雲鏈接

學習進度條

代碼行數(新增/積累)博客量(新增/積累學習時間(新增/累積)
目標 5000行 30篇 400小時
第一周 5/5 1/1 8/8
第二周 120/120 1/1 12/12
第三周 100/100 1/1 15/15
第四周 80/80 1/1 9/9

參考資料

《深入理解計算機系統V3》學習指導

詳細介紹Linux指令od

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