20145320 《資訊保安系統設計基礎》第9周學習總結

20145320周岐浩發表於2016-11-13

20145320 《資訊保安系統設計基礎》第9周學習總結

教材學習內容總結

輸入/輸出(I/O)是主存和外部裝置(I/O裝置)(如磁碟驅動器、終端、網路)之間拷貝資料的過程。輸入是從I/O裝置拷貝到主存。反之則反。

10.1Unix I/O

  • Unix檔案就是一個m位元組的序列:b0,b1,b2….bm-1。所有的I/O裝置都被虛擬化為檔案。所有的輸入輸出都是在當成相對應的檔案的讀寫。將裝置對映為檔案,Unix核心引出一個應用介面,Unix I/O。

  • 輸入輸出的執行方式:

    • 開啟檔案:開啟檔案,核心會返回描述符。標準輸入(STDIN_FILENO)描述符為0、標準輸出(STDOUT_FILENO)描述符為1、標準錯誤(STDERR_FILENO)描述符為2。也就是說在Unix生命週期一開始,0、1、2就被佔用,以後的open只能從3開始——習題10.1

    • 改變當前檔案位置:檔案位置k,是檔案開頭起始的位元組偏移量。

    • 讀寫檔案:讀是從檔案拷貝到儲存器。寫相反。當k超過檔案位元組數m時,會觸發end-of-file(EOF)條件。

    • 關閉檔案:釋放檔案開啟時建立的資料結構(釋放檔案的儲存器資源),將描述符恢復到可用的描述符池中。

10.2開啟和關閉檔案

  • 1.open函式

(1)函式定義:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(char *filename, int flags, mode_t mode);

(2)引數解析:

返回值:型別為int型,返回的是描述符數字,總是在程式中當前沒有開啟的最小描述符。如果出錯,返回值為-1.
  • filename:檔名

  • flags:指明程式打算如何訪問這個檔案,可以取的值見下:

    O_RDONLY:只讀
    O_WRONLY:只寫
    O_RDWR:可讀可寫
    O_CREAT:檔案不存在,就建立新檔案
    O_TRUNC:如果檔案存在,就截斷它
    O_APPEND:寫操作前設定檔案位置到結尾處
    這些值可以用“或”連線起來。

  • mode:指定了新檔案的訪問許可權位,符號名稱如下:

20145320 《資訊保安系統設計基礎》第9周學習總結
      

  • 2.close函式

(1)函式定義:

#include <unistd.h>

int close(int fd);

(2)引數解析:

返回值:成功返回0,出錯返回-1

關閉一個已經關閉的描述符會出錯

fd:即檔案的描述符。

10.3讀和寫檔案

  • 1.讀 read

(1)函式原型:

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t n);//返回有符號值

(2)引數解析:

返回值:成功則返回讀的位元組數,EOF返回0,出錯返回-1。返回值為有符號數。
fd:檔案描述符
buf:儲存器位置
n:最多從當前檔案位置拷貝n個位元組到儲存器位置buf
  • 2.寫 write

(1)函式原型:

#include <unistd.h>

ssize_t write(int fd, void *buf, size_t n);

(2)引數解析:

返回值:成功則返回寫的位元組數,出錯返回-1。返回值為有符號數。
fd:檔案描述符
buf:儲存器位置
n:最多從儲存器位置buf拷貝n個位元組到當前檔案位置
  • 需要注意的是,read和write在正常情況下返回值是實際傳送的位元組數量。

  • 3.不足值

      不足值指在某些情況下,read和write傳送的位元組比應用程式要求的要少,原因如下:
      讀的時候遇到EOF
      從終端讀文字行
      讀和寫socket

10.4用RIO包健壯地讀寫

  • RIO包能自動地處理不足值。提供了兩個函式:無緩衝的輸入輸出函式,帶緩衝的輸入函式。

  • RIO的無緩衝的輸入輸出函式

這些函式的作用是直接在儲存器和檔案之間傳送資料,常適用於網路和二進位制資料之間。

rio_readn函式和rio_writen定義:

#include "csapp.h"

ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);

引數:

fd:檔案描述符
usrbuf:儲存器位置
n:傳送的位元組數

返回值:

rio_readn成功則返回傳送的位元組數,EOF為0(一個不足值),出錯為-1
rio_writen成功則返回傳送的位元組數,出錯為-1,沒有不足值。
  • RIO的帶緩衝的輸入函式

    • 可以高效的從檔案中讀取文字行和二進位制資料。

    • 文字行就是一個由換行符結尾的ASCII碼字元序列。換行符數字值為0x0a.rio_readlineb函式從內部讀緩衝區拷貝一個文字行,當緩衝區為空時,會自動地呼叫read重新填滿緩衝區。rio_readn帶緩衝區的版本:rio_readnb。

    • rio_readlineb從rp讀出一個文字行(包括換行符)並把它存到usrbuf,並用空字元結束這個文字行。最多讀maxlen-1個位元組,剩下一個給結尾處的空字元。

    • rio_readnb最多讀n個位元組。

10.5讀取檔案後設資料

  • 檢索檔案後設資料的方式:呼叫stat和fstat函式。兩者功能相似。
    • stat資料結構中的成員。重點掌握st_mode,st_size.

       st_size:檔案位元組數大小
      
       st_mode:檔案訪問許可位和檔案型別。(普通檔案:二進位制檔案和文字檔案。目錄檔案:其他檔案資訊。套接字:通過網路與其他程式通訊的檔案。)

10.6共享檔案

  • 用三個相關的資料結構表示開啟的檔案:

    • 描述符表:每個開啟的描述符表項指向檔案表中的一個表項。

    • 檔案表:開啟的檔案的集合是由一張檔案表表示的,所有的程式共享這張表。包括檔案位置、引用計數(當前指向該表項的描述符表項數),指向v-node表的指標。

    • v-node表:包含stat結構中大多數資訊。

      開啟檔案的核心資料結構:
      20145320 《資訊保安系統設計基礎》第9周學習總結

      檔案共享。共享了同一個磁碟檔案:
      20145320 《資訊保安系統設計基礎》第9周學習總結

    子父程式共享檔案。子程式有一個父程式描述表符副本,所以他們共享開啟檔案的集合。注意,在核心刪除相應檔案表表項之前,子父程式必須都關閉他們的描述符。
    20145320 《資訊保安系統設計基礎》第9周學習總結

10.7 I/O重定向

  • I/O重定向操作符: >

      ls > foo.txt

這句程式碼的含義就是使外殼載入和執行ls程式,並且將標準輸出重定向到磁碟檔案foo.txt。

  • I/O重定向函式: dup2

    函式定義為:

      #include <unistd.h>
    
      int dup2(int oldfd, int newfd);

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

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

10.8 標準I/O

標準I/O庫:一組高階輸入輸出函式。將一個開啟的檔案模型化為一個流,一個流即一個指向FILE型別的結構的指標。

每個ANSI C程式開始時都有三個開啟的流:stdin(標準輸入),stdout(標準輸出),stderr(標準錯誤)。

型別為FILE的流是對檔案描述符和流緩衝區的抽象。為了減小系統開銷。

10.9 綜合:該使用哪些I/O函式

在網路套接字的時候使用RIO函式。需要格式化輸出,使用sprintf函式格式化一個字串,然後用rio_writen把它傳送到套介面。

格式化輸入,使用rio_readlineb讀一個完整的文字行,再使用scanf從文字行提取不同欄位。

教材練習

10.1

  • Unix程式生命週期開始時,開啟的描述符賦給了stdin(描述符0)、stdout(描述符1)和stderr(描述符2)。open函式總是返回最低的未開啟的描述符,所以第一次呼叫open會返回描述符3。呼叫close函式會釋放描述符3.最後對open的呼叫會返回描述符3,因此程式的輸出是“fd2=3”。

10.2

  • 描述符fd1和fd2都要各自的開啟檔案表表項,所以每個描述符對於foobar.txt都有它自己的位置。因此,從fd2的讀操作會讀取foobar.txt的第一個自己,並輸出
    • c=f ,而不是 c=o

10.3

  • 這裡是子程式繼承父程式的描述符表,以及所有程式共享的同一個開啟檔案表。因此,描述符fd在父子程式中都指向同一個開啟檔案表表項。當子程式讀取檔案的一個位元組時,檔案位置加1.因此,父程式會讀取第二個位元組,而輸出就是
    • c=o,而不是10.2中的 c=f

10.4

  • 這裡考察的是重定向的內容,重定向標準輸入(描述符0)到描述符5,直接呼叫dup2(5,0)

10.5

  • 這題考察重定向的應用,這裡把fd1重定向到了fd2,輸出應該為
    • c=o

相關文章