20145203 《資訊安全系統設計基礎》第10周學習總結
視訊資源内容
1、ls-l指令可以顯示目前工作目錄下包含目錄或者檔案的詳細資訊。資訊包含七列:
①第一列:
第一位:檔案類型,-代表檔案,d代表目錄。
第二、三、四位:代表檔案建立者權限,-為無權限,r為可讀,w為可寫,x為可執行。
第五、六、七位:代表同組使用者權限。
第八、九、十位:代表其他使用者權限,其中其他使用者沒有寫權限。
②第二列:檔案的目錄、子目錄數。(目錄的該字段至少2)
③第三列:所有者
④第四列:所屬使用者組
⑤第五列:檔案大小
⑥第六列:檔案最後修改時間
⑦第七列:檔案名
2、什麼是目錄?
①目錄是一種特殊的檔案,它的内容是檔案和目錄的名字。
②目錄包含很多記錄,記錄通過結構體定義。
③每條記錄内容代表一個檔案或者目錄。
④目錄檔案至少包含兩個特殊項
‘.’ :代表目前目錄
‘..’ :代表上一級目錄
3、man -k:
常用來搜尋。例句如下:
man -k key1 | grep key2 | grep 2
搜尋同時含有k1和k2,且屬于系統調用。最後的數字意味着幫助手冊中的區段,man手冊共有8個區段,最常用的是123,含義如下:
1.Linux
2.系統調用
3.c語言
單獨用man語句的時候,想檢視其中的單獨某個區段内的解釋時,例句如下:
man 3 printf
即查找c語言中printf的用法。
4、grep -nr
這條語句可以用來查找關鍵字,全文搜尋,并且可以直接查找檔案内的内容。其中:
n:為顯示行号
r:為遞歸查找
例如,如果想查找某個宏,我們已知宏儲存在include檔案夾中,是以例句如下:
grep -nr XXX /usr/include(XXX為所要找的宏)
5、通過系統調用stat可以擷取檔案相關資訊

檔案連結數、檔案最後修改時間、檔案最後通路時間可以直接擷取。
st_mode十六位二進制數
注意:權限讀寫執行都是三位一組的,是以二進制掩碼都是三位一組用八進制表示的。
①:與:之間分别是:使用者名、密碼、使用者id、所屬的組等等。
②使用getpwuid(uid_t uid)函數可以通過使用者的id得到使用者名。
附錄A
附錄A中主要講了這本書中的錯誤處理方式
1.錯誤處理風格
(1)Unix風格
遇到錯誤後傳回-1,并且将全局變量errno設定為指明錯誤原因的錯誤代碼;
如果成功完成,就傳回有用的結果。
(2)Posix風格
傳回0表示成功,傳回非0表示失敗;
有用的結果在傳進來的函數參數中。
(3)DNS風格
有兩個函數,gethostbyname和gethostbyaddr,失敗時傳回NULL指針,并設定全局變量h_errno。
(4)錯誤報告函數
void unix_error(char *msg) /* unix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/* $end unixerror */
void posix_error(int code, char *msg) /* posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}
void dns_error(char *msg) /* dns-style error */
{
fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
exit(0);
}
void app_error(char *msg) /* application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}
2.錯誤處理包裝函數
Unix風格
成功時傳回void,傳回錯誤時包裝函數列印一條資訊,然後退出。
void Kill(pid_t pid, int signum)
{
int rc;
if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");
}
Posix風格
成功時傳回void,錯誤傳回碼中不會包含有用的結果。
void Pthread_detach(pthread_t tid) {
int rc;
if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");
}
DNS風格
struct hostent *Gethostbyname(const char *name)
{
struct hostent *p;
if ((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
實踐代碼
main函數的定義與頭檔案的含義:
int main(int argc, char *argv[]){}
argc是用來表示在指令行下輸入指令時的參數個數,包括指令本身。
argv[]是用來取得你輸入的參數。
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.c
#include <stdio.h>//标準輸入輸出
#include <stdlib.h>//C标準函數庫
#include <unistd.h>//Unix類系統定義符号常量
#include <fcntl.h>//定義了很多宏和open,fcntl函數原型
#define BUFFERSIZE 4096//定義存儲器容量
#define COPYMODE 0644//定義複制的長度
void oops(char *, char *);
int main(int argc, char *argv[])
{
int in_fd, out_fd, n_chars;//三個描述符值
char buf[BUFFERSIZE];//存儲器位置
/*cp的參數有兩個,分别是要複制的檔案,和目的目錄,這樣一共應該是有三個操作數
是以要先檢查argc的值是否為三,如果不是,傳回标準錯誤*/
if (argc != 3) {
fprintf(stderr, "usage: %s source destination\n", *argv);
exit(1);
}
/*檢查cp的第一個參數,要複制的檔案,用open打開,in_fd為open傳回的描述符
如果傳回-1,代表打開失敗,提示錯誤*/
if ((in_fd = open(argv[1], O_RDONLY)) == -1)
oops("Cannot open ", argv[1]);
/*檢查cp的第二個參數,複制的目的位址,用create在目的位址建立新檔案,out_fd為open傳回的描述符
如果傳回-1,代表建立失敗,提示錯誤*/
if ((out_fd = creat(argv[2], COPYMODE)) == -1)
oops("Cannot creat", argv[2]);
/*cp指令的動作就是讀取一個檔案的内容到存儲器,在新的位址建立空白檔案,再從存儲器将内容寫入新檔案。
這裡判斷複制是否成功:
如果能讀取順利,而讀取的位數和寫的位數不同,是寫錯誤;
如果讀取失敗,是讀錯誤。*/
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]);
/*這裡執行的是關閉檔案的動作,in_fd和out_fd兩個檔案描述符
所指向的檔案隻要有一個關閉錯誤,就提示關閉錯誤。*/
if (close(in_fd) == -1 || close(out_fd) == -1)
oops("Error closing files", "");
}
/*這個是用來輸出錯誤資訊的函數*/
void oops(char *s1, char *s2)
{
fprintf(stderr, "Error: %s ", s1);
perror(s2);//用來将上一個函數發生錯誤的原因輸出到标準裝置(stderr)
exit(1);
}
輸入:源檔案和目的檔案
輸出:./cp1 cp1.c cp2.c 指令可将
ls1.c
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
void do_ls(char []);
int main(int argc, char *argv[])
{
/*如果操作數隻有1個,表明ls後面沒有帶參數,預設為目前目錄,‘.’表示目前目錄。*/
if ( argc == 1 )
do_ls( "." );
/*如果ls後面有參數,就把參數讀入argv中。*/
else
while ( --argc ){
printf("%s:\n", *++argv );
do_ls( *argv );
}
return 0;
}
/*因為ls和dir功能相近,用dir來實作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);
}
}
輸出:./ls1指令可以顯示目前工作目錄下包含什麼目錄或檔案。
ls2.c
ls2前半部分和ls1一樣,所不同的隻是多出來了一部分,用來顯示檔案的詳細資訊,比如使用者名,群組名,大小,建立時間,讀寫權限等。
輸出:./ls2指令可以顯示目前工作目錄下包含目錄或者檔案的詳細資訊。
who.c
作用:從UTMP_FILE檔案中讀取想要的資訊到存儲器中,然後再用标準輸出函數列印到螢幕上,最後關閉檔案。
#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);
#endif
printf("\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就是是讀的位元組數,然後再調用函數列印出來。*/
while ( read(utmpfd, ¤t_record, reclen) == reclen )
show_info(¤t_record);
close(utmpfd);
return 0;
}
輸出:./who 指令可以輸出正在本系統中的使用者的資訊。
echostate.c
作用:用來檢查指令行中的提示符是否顯示的,如果顯示,輸入的指令都可見,不顯示則表示輸入的指令不可見,具體例子結合setecho代碼一起
#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");
else
printf(" echo is OFF, since its bit is 0\n");
return 0;
}
輸出:./echostate 即可顯示指令行中的提示符是否顯示。
setecho
作用:改變echo的狀态,設定指令行中的提示符是否顯示。
#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 )
exit(0);
if ( tcgetattr(0,&info) == -1 )
oops("tcgettattr", 1);
if ( argv[1][0] == 'y' )
info.c_lflag |= ECHO ;/*打開提示符*/
else
info.c_lflag &= ~ECHO ;/*隐藏提示符*/
if ( tcsetattr(0,TCSANOW,&info) == -1 )
oops("tcsetattr",2);
return 0;
}
輸入:./setecho no(yes)
輸出:當echo is on的時候,輸入的指令是可見的,當設定為off的時候,輸入指令不可見
fileinfo.c
作用:用來實作顯示檔案資訊,建立了一個stat資料結構。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
void show_stat_info(char *, struct stat *);
/先判斷指令是否有操作數,有的話才能繼續進行下去,如果沒有報錯就列印出來相關檔案資訊,報錯就用perror将報錯資訊列印出來。/
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;
}
else
perror(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 );
}
輸入:./fleinfo.c cp1.c
輸出:顯示cp1.c檔案的相關資訊
filesize.c
作用:用st_size成員來計算檔案的位元組數大小。
#include <stdio.h>
#include <sys/stat.h>
/*先判斷是否有錯誤,沒有的話就調用*/
int main()
{
struct stat infobuf;
if ( stat( "/etc/passwd", &infobuf) == -1 )
perror("/etc/passwd");
else
printf(" The size of /etc/passwd is %d\n", infobuf.st_size );
}
輸入:./filesize etc/passwd
輸出:可以計算出passwd檔案的位元組數為2298
spwd
作用:這個代碼的功能是列出目前所在目錄
#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;
}
輸入:./spwd
輸出:顯示目前所在的目錄
testioctl.c
作用:計算目前指令行視窗的行列數大小
#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;
}
輸入:./testioctl.c
輸出:x行,y列。
本周代碼托管截圖
代碼連結
學習進度條
代碼行數(新增/累積) | 部落格量(新增/累積) | 學習時間(新增/累積) | 重要成長 |
---|---|---|---|
目标 | 5000行 | 30篇 | 400小時 |
第一周 | 150/150 | 1/2 | 20/20 |
第二周 | 200/350 | 1/2 | 24/44 |
第三周 | 150/500 | 1/3 | 20/64 |
第五周 | 300/800 | 1/4 | 15/79 |
第六周 | 500/1300 | 1/5 | 20/99 |
第七周 | 200/1500 | 1/6 | 21/120 |
第九周 | 210/1710 | 1/9 | 10/130 |
第十周 | 530/2240 | 2/11 | 20/150 |
參考資料
- 《深入了解計算機系統V2》學習指導
- ...
轉載于:https://www.cnblogs.com/GZSdeboke/p/6083957.html