信息安全系統設計基礎第九周學習總結

第十章 系統級I/O

第九周(11.02-11.08):
估算學習時間:共8小時
讀書:4
代碼:1
做業:1
博客:2
實際學習時間:共12小時
讀書:4
代碼:2
做業:2
博客:4node

1、學習目標

  1. 掌握系統編程和系統調用的概念
  2. 掌握系統編程錯誤處理的方式
  3. 掌握Unix/Linux系統級I/O:open close read write seek stat
  4. 掌握RIO
  5. 掌握I/O重定向的方法
    2、學習資源
  6. 教材:附錄A,第10章《系統級I/O》
  7. 課程資料:https://www.shiyanlou.com/courses/413 實驗11,課程邀請碼:W7FQKW4Y
  8. 教材中代碼運行、思考一下,讀代碼的學習方法見這。

3、學習方法

  1. 進度很重要:必須跟上每週的進度,閱讀,練習,問答,項目。我會認真對待每一位同窗,請你不要由於困難半途而廢。
  2. 問答很重要:遇到知識難點請多多提問,這是你的權利更是您對本身負責的義務。問答到博客園討論小組:http://group.cnblogs.com/103791/
  3. 實踐很重要:解決書中習題,實踐書中實例,完成每週項目,纔算真的消化了這本好書。經過實驗樓環境或本身安裝的虛擬機在實踐中進行學習
  4. 實驗報告很重要:詳細記錄你完成項目任務的思路,得到老師點評和幫助本身複習。學習完成後在博客園中(http://www.cnblogs.com/)把學習過程經過博客發表,博客標題「信息安全系統設計基礎第九周學習總結

4、學習任務

  1. 閱讀教材,注意每一個系統調用的參數、返回值,會查幫助文檔
    完成課後練習(書中有參考答案)重點:10.一、10.二、10.三、10.四、10.5
    2.重要命令:
    man -k key1 | grep key2| grep 2 : 根據關鍵字檢索系統調用
    grep -nr XXX /usr/include :查找宏定義,類型定義
  2. 考覈:教材內容,練習題把數據變換一下
  3. 實驗:須要動手的到實驗樓中練習一下

5、後續學習預告(可選):

教材第八章《異常控制流》程序員

6、學習過程

  • 輸入輸出I/O是在主存和外部設備(如磁盤,網絡和終端)之間拷貝數據的過程。
  • 輸入就是從I/O設備拷貝數據到主存,而輸出就是從主存拷貝數據到I/O設備。
  • 全部語言的運行時系統都提供執行I/O的較高級別的工具。例如,ANSI C提供標準I/O庫,包含像printf和scanf這樣執行帶緩衝區的I/O函數。C++語言用它的重載操做符<<(輸出)和>>(輸入)提供了相似的功能。在UNIX系統中,是經過使用由內核提供的系統級UnixI/O函數來實現這些比較高級的I/O函數的。
  • 學習Unix I/O緣由:
    • 瞭解Unix I/O將幫助你理解其餘的系統概念;
    • 有時你除了使用Unix I/O外別無選擇。

10.1 unix i/o

全部的I/O設備,如網絡、磁盤和終端,都被模型化爲文件,而全部的輸入和輸出都被當作對相應的文件的讀和寫來執行。這種將設備優雅地映射爲文件的方式,容許Unix內核引出一個簡單、低級的的應用接口,稱爲Unⅸ I/O,這使得全部的輸入和輸出都能以一種統一且一致的方式來執行:編程

  • 打開文件。一個應用程序經過要求內核打開相應的文件,來宣告它想要訪問一個I/O設備。內核返回一個小的非負整數,叫作描述符,它在後續對此文件的全部操做中標識這個文件。內核記錄有關這個打開文件的全部信息。應用程序只需記住這個描述符。Unⅸ外殼建立的每一個進程開始時都有三個打開的文件:標準輸入(描述符爲0)、標準輸出(描述符爲1)和標準錯誤(描述符爲2)。頭文件可用來代替顯式的描述符值。
  • 改變當前的文件位置。對於每一個打開的文件,內核保持着一個文件位置k,初始爲0。這個文件位置是從文件開頭起始的字節偏移量。應用程序可以經過執行seek操做,顯式地設置文件的當前位置爲k。
  • 讀寫文件。一個讀操做就是從文件拷貝n>0個字節到存儲器,從當前文件位置k開始,而後將k增長到k+n。給定一個大小爲m字節的文件,當k>=m時執行讀操做會觸發―個稱爲end-of-file(EOF)的條件,應用程序能檢測到這個條件。在文件結尾到處並無明確的「EOF」符號。
  • 關閉文件。當應用完成了對文件的訪問以後,它就通知內核關閉這個文件。做爲響應,內核釋放文件打開時建立的數據結構,並將這個描述符恢復到可用的描述符池中。不管一個進程由於何種緣由終止時,內核都會關閉全部打開的文件並釋放它們的存儲器資源。

10.2 打開和關閉文件

進程是經過調用open函數來打開一個已存在的文件或者建立一個新文件緩存

  • flags參數表示進程打算如何訪問這個文件,它的值包括:

O_RDONLY
O_WRONLY
O_RDWR安全

  • flags參數也能夠是一個或者更多位掩碼的或,提供一些額外的指示:

O_CREAT
O_TRUNC:若是文件已經存在,就截斷它。
O_APPEND網絡

  • mode參數指定了新文件的訪問權限位。符號名字以下圖。做爲上下文的一部分,每一個進程都有一個umask它是經過調用umask函數來設置的。當進程經過帶某個mode參數的open函數調用來建立一個新文件時,文件的訪問權限位被設置爲mode&umask。

10.3 讀和寫文件

應用程序是經過分別調用系統函數 read和write函數來執行輸入和輸出的。數據結構

在某些狀況下,read和write傳送的字節比應用程序要求的要少。出現這種狀況的可能的緣由有:less

  • 讀時遇到EOF。假設該文件從當前文件位置開始只含有20個字節,而應用程序要求咱們以50個字節的片進行讀取,這樣一來,這個read的返回的值是20,在此以後的read則返回0。socket

  • 從終端讀文本行。若是打開的文件是與終端相關聯的,那麼每一個read函數將一次傳送一個文本行,返回的不足值等於文本行的大小。
  • 讀和寫socket。若是打開的文件對應於網絡套接字,那麼內部緩衝約束和較長的網絡延遲會致使read和write返回不足值。函數

 10.4 用rio包健壯地讀寫

RIO提供了兩類不一樣的函數:

  • 無緩衝的輸入輸出函數
    這些函數直接 在存儲器和文件之間傳送數據,沒有應用級緩衝。
  • 帶緩衝的輸入函數
    內容緩存在應用級緩衝區內。

10.4.1 rio的無緩衝的輸入輸出函數

rio_readn函數從描述符fd的當前文件位置最多傳送n個字節到存儲器位置usrbuf。相似的rio_writen函數從位置usrbuf傳送n個字節到描述符fd。rio_readn函數在遇到EOF時只能返回一個不足值。rio_writen函數毫不會返回不足值。
注意:若是rio_readn和rio_writen函數被一個從應用信號處理程序的返回中斷,那麼每一個函數都會手動地重啓read或write。

10.4.2 rio的帶緩衝的輸入函數

一個文本行就是一個由 換行符 結尾的ASCII碼字符序列。在Unix系統中,換行符是‘\n’,與ASCII碼換行符LF相同,數值爲0x0a。假設咱們要編寫一個程序來計算文本文件中文本行的數量應該如何來實現呢?

一種方法是用read函數來一次一個字節地從文件傳送到用戶存儲器,檢查每一個字節來查找換行符。這種方法的問題就是效率不高,每次取文件中的一個字節都要求陷入內核。
一種更好的方法是調用一個包裝函數(rio_readlineb),它從一個內部緩衝區拷貝一個文本行,當緩衝區變空時,會自動的調用read系統調用來從新填滿緩衝區。

10.5 讀取文件元數據

應用程序可以經過調用stat和fstat函數,檢索到關於文件的信息。
stat函數結構

st_size成員包含了文件的字節數大小。st_mode成員則編碼了文件訪問許可位和文件類型。Unix識別大量不一樣的文件類型。普通文件包括某種類型的二進制或文本數據。對於內核而言,文本文件和二進制文件毫無區別。
目錄文件包含關於其餘文件的信息。套接字是一種用來經過網絡與其餘進程通訊的文件。Unix提供的宏指令根據st_mode成員來肯定文件的類型。

10.6 共享文件

內核用三個相關數據結構來表示打開的文件

描述符表
文件表
v-node表

10.7 i/o重定向

Unix外殼提供了I/O重定向操做符,容許用戶將磁盤文件和標準輸入輸出聯繫起來。

10.8 標準i/o

ANSI C定義了一組高級輸入輸出函數,成爲標準I/O庫,爲程序員提供了Unix I/O的較高級別的替代。這個庫(libc)提供了打開和關閉文件的函數(fopen和fclose)、讀和寫字節的函數(fread和fwrite)、讀和寫字符串的函數(fgets和fputs)、以及複雜的格式化I/O函數(printf和scanf)。
標準I/O庫將一個打開的文件模型化爲一個流。對於程序員而言,一個流就是一個指向FILE類型的結構的指針。每一個ANSI C程序開始時都有三個打開的流stdin、stdout和stderr,分別對應於標準輸入、標準輸出和標準錯誤:

#include<stdio.h>
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;

10.9 綜合:我該使用哪些i/o函數

這一章討論過的各類I/O包
標準I/O流,從某種意義上來講是全雙工的,由於程序可以在同一個流上執行輸入和輸出。
建議在網絡套接字上不要使用標準I/O函數來進行輸入和輸出。而要使用健壯的RIO函數。

10.10 小結

  • Unix提供了少許的系統級函數,它們容許應用程序打開、關閉、讀和寫文件,提取文件的元數據,以及執行I/O重定向。Unix的讀和寫操做會出現不足值,應用程序必須能正確地預計和處理這種狀況。應用程序不該直接調用unⅸ I/O函數,而應該使用RIO包,RIO包經過反覆執行讀寫操做,直到傳送完全部的請求數據,自動處理不足值。
  • Unix內核使用三個相關的數據結構來表示打開的文件。描述符表中的表項指向打開文件中的表項,而打開文件表中的表項又指向v-node表中的表項,每一個進程都有它本身單獨的描述符表,而全部的進程共享同一個打開文件表和v-node表,理解這些結構的通常組成就能使咱們清楚地理解文件共享和I/O重定向。
  • 標準I/O庫是基於Unix I/O實現的,並提供了一組強大的高級I/O例程,對於大多數應用程序而言,標準I/O更簡單,是優於Unix I/O的選擇。然而,由於對標準I/O和網絡文件的一些相互不兼容的限制,Unix I/O比標準I/O更適用於網絡應用程序。

7、遇到的問題及解決

8、其餘

怎樣學習系統編程(利用Linux學習Linux編程)

1 分析實用程序
/bin, /usr/bin, /usr/local/bin
學習使用工具,分析工具,瞭解功能和原理
2 學習系統調用
函數和系統調用本質上都是函數。不一樣的庫,不一樣的頭文件
分析須要哪些系統調用,學習系統調用的使用方法:參數?返回值?
3 編程實現
利用上面的原理和一組協同工做的系統調用,本身編程實現使用程序的功能
或積極主動抄代碼,學習那些系統調用是協同工做的

C語言的學習能夠參考這個思路,實現標準庫
伴隨咱們學習常常要問的三個問題:
能作什麼?
如何實現?
本身如何編寫?

好比說Linux操做系統
能作什麼?
登陸-運行程序-註銷
如何登陸?如何獲取程序名?如何運行程序?
目錄操做:目錄樹:ls,cd,pwd,mkdir,rmdir
目錄樹如何組織的?目錄存在哪?什麼是當前目錄?
文件操做:cat, more/less/pg, cp, mv, lpr
文件數據如何存儲?如何複製,移動,更名?文件名存在哪?
文件訪問控制:ugo
如何設置?

從OS的角度看: 網絡遊戲
通訊
協做
網絡訪問
bc/dc---->網絡 B/S

標準I/O 學習示例:more

能作什麼?用一下

使用方法
more filename
more < filename
command | more
如何實現?
僞代碼:

若是用戶沒有輸入文件名
輸出鍵盤輸入內容
對整個文件
顯示24行
提示用戶選擇 空格 回車 q
若是用戶選擇空格
顯示下24行
若是用戶選擇回車
顯示下一行
若是用戶選擇 q
退出

函數調用:
fopen/fclose
stdin stdout stderr
fgets/fputs
getchar/putchar
printf("\033[7m more? \033[m")

本身編寫:
如何判斷讀到文件尾部了?
feof
fgets的返回值是0
fseek 與文件讀寫位置

問題:
選擇都要回車
文字和反白more一塊兒上滾
百分比
適應窗口
重定向: who | more, ls |more
/dev/tty(流與文件)

系統調用:文件I/O 如何用Linux學習系統編程
多用戶系統如何知道誰在使用系統?who
who能作什麼?使用一下
man who (info who; who --help)
如何實現who?

閱讀ManPages
man man
搜索ManPages
man -k
man -k XXX | grep -i YYY
閱讀頭文件
參閱see also

man who
man -k utmp
man 5 utmp
utmp.h
grep -i XXX -nr /usr/include

UTMP_FILE
struct utmp

define ut_name ut_user

ut_line

define ut_time ut_tv.tv_sec

僞代碼:

打開utmp文件
針對文件
讀取一條記錄
顯示記錄
關閉文件

哪些系統調用?
man -k file | grep -i read
see also

open/read/close

struct utmp s;
read( fd, &s, sizeof(s));

man
cf fopen fread fclose

本身編寫who:
read: return value
/var/run/utmp
var/run/unp

問題:空白記錄
ut_type
時間轉換
man -k time | grep -i transform (trans)
asctime(3)
ctime(3)
localtime(3)
man -k time | grep -i convert

查找關鍵字:至少漢語有想法
轉換

時間格式
man -k time | grep -i format
strftime(3)

如何複製文件?cp
cp能幹什麼?
cp src dst

如何實現cp?
open/close

open(fff, O_WRONLY|O_CREAT,0644)
creat(fff, 0644);
n = read(fd, buf, BUFSIZE);//#define BUFSIZE 4096
write(fd, buf, n);

僞代碼:
打開源文件
建立目標文件
針對源文件
把源文件讀入緩衝區
把緩衝區內容寫入目標文件
關閉源文件和目標文件

本身編寫cp:

系統調用錯誤處理:
錯誤種類:errno
顯示錯誤消息:perror(3)
錯誤處理封裝函數
fork()

if((pid = fork()) < 0)
unix_error("fork error");
return pid;

學有餘力者:
ac last cat head tail od dd

read/write能夠讀取文件內容,如何讀取文件名和文件屬性?ls

ls能幹什麼?
ls
ls -l
ls -a
ls -lu:最後訪問時間
ls -s:以塊爲單位的文件大小
ls -t:按時間排序
ls -F:顯示文件類型

列出文件目錄
顯示文件信息
如何列出文件目錄?
如何顯示文件屬性?
如何判斷一個名字是文件仍是目錄?

文件樹
文件和目錄被組織成目錄樹(tree),節點是目錄或者文件
目錄是一種特殊文件,文件內容就是目錄和文件的名字,與utmp相似
與文件不一樣,目錄不會爲空

如何實現ls?
man -k direct
man -k direct | grep -i read
man -k direct | grep -i entry

readdir
see also: opendir closedir
總結:代碼模式
fopen fread/fwrite fclose
open read/write close
opendir readdir closedir

僞代碼:
打開目錄文件
針對目錄文件
讀取目錄條目
顯示文件名
關閉文件目錄文件

本身編寫ls:

傳入參數,顯示任意目錄: ls /tmp; ls /; ls /dev
分欄
.開頭隱含文件:-a
排序:man -k sort

代碼庫:DRY
xxx_uitl.h xxx_util.c
出錯處理,參數處理,經常使用結構...
xxx_datastru.h xxx_datastru.c
鏈表,雙向鏈表
樹,圖。。。
xxx_algorith.h xxx_algorthm.c

ls -l能作什麼?
顯示文件信息:模式(文件類型file(1),訪問控制),連接數,文件全部者,組,大小,最後修改時間,文件名

如何實現ls -l?
man -k file | grep -i infomation (status, property, attribute)

stat(1) stat(2)
struct stat
最後修改時間:st_mtime ctime
模式:st_mode
type ugs rwx rwx rwx

八進制掩碼
struct stat info;
if ((info.st_mode & 0170000) == 0040000)
printf("這是一個目錄\n");

文件類型宏

define S_ISDIR(m) (((m)&0170000)) == (0040000))

struct stat info;
if (S_ISDIR(info.st_mode))
printf("這是一個目錄\n");

訪問控制屬性?好比說本人能不能寫?如何定義宏?
S_ISREG(mod) '-'
S_ISDIR(mode) 'd'
S_ISCHR(mode) 'c'
S_ISBLK(mode)) 'b'

UID/GID
/etc/passwd
getpwuid(3)
struct passwd

/etc/group
getgrgid(3)
struct group
本身編寫ls -l: ls2.c
stat(2) struct stat
getpwuid(3) struct passwd
getgrgid(3) struct group

記錄計數
按文件名排序 qsort

文件屬性修改與open/creat

open/creat umask(1) umask(2)

chmod(1) chmod(2)
chown(1) chgrp(1) chown(2)
touch(1) utime(2)
mv(1) rename(2)

學有餘力:tree chmod file chown chgrp finger touch

tree ls-R
文件包含數據,目錄是文件列表,目錄構成目錄樹。
文件在目錄中什麼意思?
用戶的主目錄(home)是什麼意思?
文件系統(解決的問題參考教材)
路徑:絕對路徑,相對路徑。pwd
用戶眼中的文件系統
目錄和文件:構成目錄樹
目錄命令:
. .. /
mkdir
rmdir
-p
mv
cd
pwd
...
練習:構建一棵目錄樹
文件命令:
cp
-r
cat
mv
rm
-r
ln
ls
...
目錄樹命令
tree
ls -R
chmod -R
du
find:注意與grep的區別
...

目錄樹的深度??

思考: 文件系統造成目錄樹,操做系統提供相應的操做命令來協同工做 目錄是什麼? 如何知道文件所處的目錄? 切換目錄(cd)是什麼意思? pwd如何自知道你處的目錄?

相關文章
相關標籤/搜索