天天看點

資訊安全系統設計基礎第十周學習總結

第十章 系統級I/O

第七節 I/O重定向

I/O重定向操作符: >

ls > foo.txt

這句代碼的含義就是使外殼加載和執行ls程式,并且将标準輸出重定向到磁盤檔案foo.txt。

I/O重定向函數: dup2

傳回值:成功傳回描述符,錯誤傳回-1

這個函數執行的操作是,拷貝描述符表表項oldfd,覆寫描述表表項newfd,如果後者被打開,則在拷貝前關閉它。

第八節 标準I/O

1.标準I/O庫:

ANSI C定義了一組進階輸入輸出函數,稱為标準I/O庫,包含:

  • fopen、fclose,打開和關閉檔案
  • fread、fwrite,讀和寫位元組
  • fgets、fputs,讀和寫字元串
  • scanf、printf,複雜的格式化的I/O函數

2.流——類型為FILE的流是對檔案描述符和流緩沖區的抽象

标準I/O庫将一個打開的檔案模型化為一個流。

每個ANSI C程式開始的時候都有三個打開的流:stdin、stdout、stderr,對應于标準輸入、标準輸出和标準錯誤 。

第九節 套接字

網絡套接字上最好不要使用标準I/O函數,而是使用RIO函數,原因:

如果沒有清楚緩存區,輸入函數後面不能接輸出函數,輸出函數後面也不能接輸入函數,而對套接字使用lseek是非法的,打開兩個流有很麻煩,是以!在網絡套接字上不要使用标準I/O函數來進行輸入和輸出!

錯誤處理

附錄A中主要講了這本書中的錯誤處理方式,有一個方法——錯誤處理包裝函數,這個思想很有意思,相當于給基本函數再套上一層皮,然後run這個皮,發現了錯誤就終止,完全正确的話就跟沒有這層皮一樣。

1.錯誤處理風格

(1)Unix風格

遇到錯誤後傳回-1,并且将全局變量errno設定為指明錯誤原因的錯誤代碼;

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

(2)Posix風格

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

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

(3)DNS風格

有兩個函數,gethostbyname和gethostbyaddr,失敗時傳回NULL指針,并設定全局變量h_errno。

2.錯誤處理包裝函數

Unix風格

成功時傳回void,傳回錯誤時包裝函數列印一條資訊,然後退出。

Posix風格

成功時傳回void,錯誤傳回碼中不會包含有用的結果。

DNS風格

參考資料

1.《深入了解計算機系統》

實踐代碼

stdio.h 标準輸入輸出

stdlib.h C标準函數庫

unistd.h Unix類系統定義符号常量

fcntl.h  定義了很多宏和open,fcntl函數原型

sys/types.h 基本系統資料類型

dirent.h unix類目錄操作的頭檔案,包含了許多UNIX系統服務的函數原型,例如opendir函數、readdir函數。

termios.h 在Posix規範中定義的标準接口

cp

if ((in_fd = open(argv[1], O_RDONLY)) == -1)

oops("Cannot open ", argv[1]);

if ((out_fd = creat(argv[2], COPYMODE)) == -1)

oops("Cannot creat", argv[2]);

while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)

if (write(out_fd, buf, n_chars) != n_chars)

oops("Write error to ", argv[2]);

if (n_chars == -1)

oops("Read error from ", argv[1]);

cp的參數有兩個,分别是要複制的檔案,和目的目錄,檢查cp的第一個參數,即要複制的檔案,用open打開,in_fd為open傳回的描述符,如果傳回-1,代表打開失敗,提示錯誤。檢查cp的第二個參數,複制的目的位址,用create在目的位址建立新檔案,out_fd為open傳回的描述符,如果傳回-1,代表建立失敗,提示錯誤。cp指令的動作就是讀取一個檔案的内容到存儲器,在新的位址建立空白檔案,再從存儲器将内容寫入新檔案。

ls(1)

void do_ls( char dirname[] )

{

DIR *dir_ptr;

struct dirent *direntp;

if ( ( dir_ptr = opendir( dirname ) ) == NULL )

fprintf(stderr,"ls1: cannot open %s\n", dirname);

else

while ( ( direntp = readdir( dir_ptr ) ) != NULL )

printf("%s\n", direntp->d_name );

closedir(dir_ptr);

}

Ls函數打開一個檔案夾*dir,然後将其中的其中包含的檔案名輸出。不輸入檔案夾名字時預設為目前檔案夾。

who

這個函數是,從UTMP_FILE檔案中讀取想要的資訊到存儲器中,然後再用标準輸出函數列印到螢幕上,最後關閉檔案。

echostate 、setecho

這個代碼是用來檢查指令行中的提示符是否顯示的,如果顯示,輸入的指令都可見,不顯示則表示輸入的指令不可見,結合setecho代碼一起。

                info.c_lflag |= ECHO ;/*打開提示符*/

                info.c_lflag &= ~ECHO ;/*隐藏提示符*/

fileinfo

這個功能用來實作顯示檔案資訊,建立了一個stat資料結構。

void show_stat_info(char *fname, struct stat *buf)

    printf("   mode: %o\n", buf->st_mode);         

    printf("  links: %d\n", buf->st_nlink);        

    printf("   user: %d\n", buf->st_uid);          

    printf("  group: %d\n", buf->st_gid);          

    printf("   size: %d\n", (int)buf->st_size);         

    printf("modtime: %d\n", (int)buf->st_mtime);        

    printf("   name: %s\n", fname );               

filesize

用st_size成員來計算檔案的位元組數大小。

spwd

void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen)

dir_ptr = opendir( "." );

if ( dir_ptr == NULL ){

perror( "." );

exit(1);

if ( direntp->d_ino == inode_to_find )

strncpy( namebuf, direntp->d_name, buflen);

namebuf[buflen-1] = '\0';   

closedir( dir_ptr );

return;

fprintf(stderr, "error looking for inum %d\n", (int) inode_to_find);

列出目前所在目錄

testioctl

列出檔案的行數與列數。

printf("%d rows %d columns\n", size.ws_row, size.ws_col);

return 0;

編譯完成後的檔案清單:

a

a.out

cp1.c

cp1

echostate.c

error

fileinfo.c

filesize.c

foo.txt

ls1

ls1.c

ls2

ls2.c

setecho.c

spwd.c

test

testioctl.c

who1.c

who1

who2.c

who2