信息安全系统设计基础第九周学习总结
生活随笔
收集整理的這篇文章主要介紹了
信息安全系统设计基础第九周学习总结
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
第十章 系統(tǒng)級I/O的實踐
學(xué)習(xí)目標(biāo):
代碼閱讀理解:
1.編譯運行代碼
2.使用man學(xué)習(xí)理解相關(guān)系統(tǒng)調(diào)用, 理解參數(shù)、返回值的含義
3.會用grep -nr xxx /usr/include 查宏定義
who1.c
who2.c
cp1.c
echostate.c
fileinfo.c
filesize.c
ls1.c
ls2.c
setecho.c
spwd.c
testioctl.c
一、自己編寫的who
1.正版who應(yīng)該是:
- 我們可以看到,who命令是查詢當(dāng)前登錄的每個用戶,輸出包括用戶名、終端類型、登錄日期及遠(yuǎn)程主機(jī)。
- man一下who,可以看到,who命令是讀取/var/run/utmp文件來得到以上信息的。
- man一下utmp,知道utmp這個文件,是二進(jìn)制文件,里面保存的是結(jié)構(gòu)體數(shù)組,這些數(shù)組是struct utmp結(jié)構(gòu)體的。
2.自己嘗試編寫
(1)偽代碼
- 打開記錄所在文件:utmp - 將文件中的記錄逐條讀取 - 每一條讀取的記錄都要在屏幕上打印 - 關(guān)閉文件(2)問題1:
- 剛開始的時候覺得是警告就沒有在意,因為之前運行代碼的時候也有警告,但是最后可以運行出來。
- 但是:
問題1解決:
- 在record.ut_time輸出時我使用的類型是字符數(shù)組%s,但是實際上:
- 它在utmp中定義的是ut_tv.tv_sec,而ut_sec是int32_t型的。所以我換用了%ld輸出。
成功版1
(3)問題2:
- 這個與正版的who運行看起來差別還是挺大的
- 第一,沒有對齊
- 第二,時間顯示看不懂
- 第三,記錄比正版who多
問題2解決
解決對齊問題:
- 對齊的問題很好解決。我使用的是\t制表符來排的,但是由于user的長度不一,導(dǎo)致錯位,可以換成固定長度,不足補0的方法顯示。
解決時間顯示問題:
- 使用man查找與time格式化相關(guān)(這一部分改了好久,最后還是去網(wǎng)上搜索的編寫who的相關(guān)內(nèi)容、time的相關(guān)內(nèi)容才得以解決)
- 判斷應(yīng)該是strftime,進(jìn)入查看用法,繼續(xù)修改try_who代碼
- 這個警告應(yīng)該是64位機(jī)的問題,運行之后和第一次的問題一樣顯示核心已轉(zhuǎn)儲,但是我到現(xiàn)在都不知道怎么在原句上解決。
- 百度了一下想仔細(xì)看一下這個localtime的問題,找到一篇特別詳細(xì)的文章:c++ 時間類型詳解(time_t和tm),我決定分開每一步的變量試一試,直接在定義的時候就限制住每一個變量,至少能知道到底是哪一個錯了,結(jié)果沒有警告,編譯運行成功:
解決顯示記錄多的問題:
- 問題原因:utmp中保存的用戶,不僅僅是已經(jīng)登陸的用戶,還有系統(tǒng)的其他服務(wù)所需要的,所以在顯出所有登陸用戶的時候,應(yīng)該過濾掉其他用戶,只保留登陸用戶。在utmp結(jié)構(gòu)中的ut_type可以區(qū)別,登陸用戶的ut_type是USER_PROCESS,加一個判斷就可以了:
- 終于和正版who至少看起來一樣了!!!
(4)改進(jìn)
- 在打開和關(guān)閉文件的時候加上失敗情況處理。
3.我的代碼
#include <stdio.h> #include <stdlib.h> #include <unistd.h> //read #include <sys/types.h> //open #include <sys/stat.h> #include <fcntl.h> #include <utmp.h> //utmp #include <time.h> //strftimeint main() {struct utmp record;int fd;int len = sizeof(record);struct tm *p;time_t t;char fortime[40];if ( (fd = open(UTMP_FILE, O_RDONLY)) == -1 ){perror( UTMP_FILE ); exit(1);}while(read(fd,&record,len)){if(record.ut_type == USER_PROCESS)//只顯示類型為USER_PROCESS的一般進(jìn)程{printf("%-10.10s",record.ut_user);printf("%-10.10s",record.ut_line);//以下為對時間的轉(zhuǎn)換操作t = record.ut_time; p = localtime(&t);strftime(fortime,40,"%F %R",p);printf("%12s",fortime);if(record.ut_host[0]!='\0');printf("\t(%s)",record.ut_host);printf("\n");}}if (close(fd) == -1){perror( UTMP_FILE ); exit(1);}return 0; }4.who——老師的代碼
*其實看別人寫的代碼比自己寫更糾結(jié)...
#include <stdio.h> #include <stdlib.h> #include <utmp.h> #include <fcntl.h> #include <unistd.h>#define SHOWHOST int show_info( struct utmp *utbufp ) {printf("%-8.8s", utbufp->ut_name); printf(" "); printf("%-8.8s", utbufp->ut_line); printf(" "); printf("%10ld", utbufp->ut_time); printf(" "); #ifdef SHOWHOST //?這個是為了測試代碼時用的嗎?printf("(%s)", utbufp->ut_host); #endifprintf("\n"); return 0; } int main() {struct utmp current_record; int utmpfd; int reclen = sizeof(current_record);/*打開UTMP_FILE讀取信息,如果打開失敗則輸出失敗信息。*/if ( (utmpfd = open(UTMP_FILE, O_RDONLY)) == -1 ){perror( UTMP_FILE ); exit(1);}/*讀取信息到存儲器中,reclen就是是讀的字節(jié)數(shù),然后再調(diào)用函數(shù)打印出來。*/while ( read(utmpfd, ¤t_record, reclen) == reclen )show_info(¤t_record);close(utmpfd);return 0; }- 這個代碼沒有做記錄的判斷,也沒有做時間的轉(zhuǎn)換
- 老師兩個who代碼是一樣的?
2.ls
3.filesize
(1)代碼
#include <stdio.h> #include <sys/stat.h>int main() {struct stat infobuf; if ( stat( "/etc/passwd", &infobuf) == -1 )perror("/etc/passwd");elseprintf(" The size of /etc/passwd is %d\n", infobuf.st_size ); }(2)功能
- 用st_size計算文件的字節(jié)數(shù)大小。
4.fileinfo
(1)代碼
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h>void show_stat_info(char *, struct stat *);int main(int argc, char *argv[]) {struct stat info; if (argc>1){if( stat(argv[1], &info) != -1 ){show_stat_info( argv[1], &info );return 0;}elseperror(argv[1]); }return 1; } 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 ); }(2)功能
#include <stdio.h> #include <sys/types.h> #include <dirent.h>void do_ls(char []);int main(int argc, char *argv[]) {/*如果操作數(shù)只有1個,表明ls后面沒有帶參數(shù),默認(rèn)為當(dāng)前目錄,.表示當(dāng)前目錄。*/if ( argc == 1 )do_ls( "." );/*如果ls后面有參數(shù),就把參數(shù)讀入argv中。*/elsewhile ( --argc ){printf("%s:\n", *++argv );do_ls( *argv );}return 0; }/*因為ls和dir功能相近,用dir來實現(xiàn)ls*/ 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);} }- 這個功能用來實現(xiàn)顯示文件信息
5.setecho與echostate
(1)代碼
setecho:
#include <stdio.h> #include <stdlib.h> #include <termios.h>#define oops(s,x) { perror(s); exit(x); }int main(int argc, char *argv[]) {struct termios info;if (argc == 1) //后面沒有帶參數(shù)的話就不做任何操作,退出exit(0);if (tcgetattr(0,&info)==-1)//tcgetattr函數(shù)用于獲取與終端相關(guān)的參數(shù)。參數(shù)fd為終端的文件描述符,返回的結(jié)果保存在termios 結(jié)構(gòu)體中,這里fd為0,是標(biāo)準(zhǔn)輸入。這句用于讀取設(shè)備屬性oops("tcgettattr", 1);if ( argv[1][0] == 'y' )//如果運行命令后面的參數(shù)第一個字母是“y”,執(zhí)行“設(shè)置打開提示符”的命令info.c_lflag |= ECHO ;/*打開提示符*/else//對其它所有的參數(shù)都執(zhí)行“設(shè)置隱藏提示符”的命令info.c_lflag &= ~ECHO ;/*隱藏提示符*/if ( tcsetattr(0,TCSANOW,&info) == -1 )//將修改后的參數(shù)寫回設(shè)備oops("tcsetattr",2);return 0; }echostate:
#include <stdio.h> #include <stdlib.h> #include <termios.h>int main() {struct termios info;int rv;rv = tcgetattr( 0, &info ); /* read values from driver */if ( rv == -1 ){perror( "tcgetattr");exit(1);}if ( info.c_lflag & ECHO )printf(" echo is on , since its bit is 1\n");elseprintf(" echo is OFF, since its bit is 0\n");return 0; }(2)功能
setecho用來改變輸入指令是否可見。
輸入y(或是以y開頭的一串字符),命令可見否則(即輸入不以y開頭的字符),命令不可見echostate顯示輸入命令是否可見。
echo is on:命令可見echo is off:命令不可見
6.spwd
(1)代碼
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h>ino_t get_inode(char *); void printpathto(ino_t); void inum_to_name(ino_t , char *, int );int main() {printpathto( get_inode( "." ) ); putchar('\n'); return 0; }void printpathto( ino_t this_inode ) {ino_t my_inode ;char its_name[BUFSIZ];if ( get_inode("..") != this_inode ){chdir( ".." ); inum_to_name(this_inode,its_name,BUFSIZ);my_inode = get_inode( "." ); printpathto( my_inode ); printf("/%s", its_name ); } }void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen) {DIR *dir_ptr; struct dirent *direntp; dir_ptr = opendir( "." );if ( dir_ptr == NULL ){perror( "." );exit(1);}while ( ( direntp = readdir( dir_ptr ) ) != NULL )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);exit(1); }ino_t get_inode( char *fname ) {struct stat info;if ( stat( fname , &info ) == -1 ){fprintf(stderr, "Cannot stat ");perror(fname);exit(1);}return info.st_ino; }(2)功能
- 列出當(dāng)前目錄
7.testioctl
(1)代碼
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h>int main() {struct winsize size;if( isatty(STDOUT_FILENO) == 0)exit(1);if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0) {perror("ioctl TIOCGWINSZ error");exit(1);}printf("%d rows %d columns\n", size.ws_row, size.ws_col);return 0; }(2)功能
- 獲得終端設(shè)備的窗口大小
- 下圖一個是我的終端全屏的,一個是還原之后的。
8.cp
(1)代碼
#include <stdio.h>//標(biāo)準(zhǔn)輸入輸出 #include <stdlib.h>//C標(biāo)準(zhǔn)函數(shù)庫 #include <unistd.h>//Unix類系統(tǒng)定義符號常量 #include <fcntl.h>//定義了很多宏和open,fcntl函數(shù)原型#define BUFFERSIZE 4096//定義存儲器容量 #define COPYMODE 0644//定義復(fù)制的長度void oops(char *, char *);int main(int argc, char *argv[]) {int in_fd, out_fd, n_chars;//三個描述符值char buf[BUFFERSIZE];//存儲器位置if (argc != 3) {//檢查argc的值是否為三,如果不是,返回標(biāo)準(zhǔn)錯誤fprintf(stderr, "usage: %s source destination\n", *argv);exit(1);}/*檢查cp的第一個參數(shù),要復(fù)制的文件,用open打開,in_fd為open返回的描述符如果返回-1,代表打開失敗,提示錯誤*/if ((in_fd = open(argv[1], O_RDONLY)) == -1)oops("Cannot open ", argv[1]);/*檢查cp的第二個參數(shù),復(fù)制的目的地址,用create在目的地址創(chuàng)建新文件,out_fd為open返回的描述符如果返回-1,代表創(chuàng)建失敗,提示錯誤*/if ((out_fd = creat(argv[2], COPYMODE)) == -1)oops("Cannot creat", argv[2]);/*cp指令的動作就是讀取一個文件的內(nèi)容到存儲器,在新的地址創(chuàng)建空白文件,再從存儲器將內(nèi)容寫入新文件。這里判斷復(fù)制是否成功:如果能讀取順利,而讀取的位數(shù)和寫的位數(shù)不同,是寫錯誤;如果讀取失敗,是讀錯誤。*/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]);/*這里執(zhí)行的是關(guān)閉文件的動作,in_fd和out_fd兩個文件描述符所指向的文件只要有一個關(guān)閉錯誤,就提示關(guān)閉錯誤。*/if (close(in_fd) == -1 || close(out_fd) == -1)oops("Error closing files", ""); }/*這個是用來輸出錯誤信息的函數(shù)*/ void oops(char *s1, char *s2) {fprintf(stderr, "Error: %s ", s1);perror(s2);//用來將上一個函數(shù)發(fā)生錯誤的原因輸出到標(biāo)準(zhǔn)設(shè)備(stderr)exit(1); }參考資料
參考資料1:深入理解計算機(jī)系統(tǒng)(第二版)
參考資料2:編寫who命令--從Linux中學(xué)習(xí)Linux
參考資料3:c++ 時間類型詳解(time_t和tm)
參考資料4:20135202閆佳歆——信息安全系統(tǒng)設(shè)計基礎(chǔ)第八周學(xué)習(xí)總結(jié)
轉(zhuǎn)載于:https://www.cnblogs.com/hyq20135317/p/4965333.html
總結(jié)
以上是生活随笔為你收集整理的信息安全系统设计基础第九周学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 概率算法1
- 下一篇: java信息管理系统总结_java实现科