Unix/Linux 編程實踐教程第五章習題

tips: 這一章的習題是真的多,花費了我許多時間,說實話,這本書的習題難度對我而言還是挺大的。這裏有一些小建議,看的時候可以同時參考其他書,我參考的是《UNIX環境高級編程》和《Linux C編程一站式學習》,第二本我在最底下留下了鏈接,是在線版本的。然後這一章的很多題還是不太懂,如果你知道答案歡迎評論告訴我,謝謝。

5.2

現在的biff命令是用來控制命令行環境下有新郵件時是否提示,和作者的意思似乎不太一樣……

5.3

試了一下, ln 只能創建設備文件的軟鏈接,

5.4

使用mknod重新創建,比如

sudo mknod /dev/ttytest c 5 0

其中c表示字符設備,後面的兩個數字分別是主設備號和從設備號。

5.5

這是一個排列組合問題,但是有個條件是lseek 操作要在write之前完成,所以並不是 4x3x2 種情況,而是 6 種可能的組合,分別是:用戶A、B 順序定位寫入操作的兩種情況、用戶A和B定位後完成寫入的四種情況,前一種結果是正確寫入,後一種是A覆蓋B或者B覆蓋A。

5.6

do_sys_open 函數中調用 build_open_flags函數,其中

if (flags & O_APPEND)
    acc_mode |= MAY_APPEND;

校驗了並設置了 O_APPEND。我查閱的是Linux 2.6的代碼,在 mm\filemap.c文件中有一個函數_generic_file_aio_write,Linux 大多數文件系統的 write 函數都調用這個函數,其中調用了 generic_write_checks函數,其中

if (file->f_flags & O_APPEND)
    *pos = i_size_read(inode);

表明如果發現文件是以追加方式打開的,則將從 inode 中讀取到的最新文件大小作爲偏移量,從而實現了自動定位。

5.7

這個問題有點複雜,我沒有搞懂,推薦一篇文章

5.8

這裏我寫了一段簡答的代碼測試了一下,代碼寫的比較爛,多多包涵

#include <stdio.h>;
#include <string.h>;
#include <stdlib.h>;
int main(int argc, char const *argv[])
{
    int result;
    char str1[] = "first string\n";
    char str2[] = "second string\n";
    FILE *file1 = fopen("test", "a");
    if (file1 < 0)
    {
        perror("fopen error");
        exit(1);
    }
    FILE *file2 = fopen("test", "a");
    if (file2 < 0)
    {
        perror("fopen error");
        exit(1);
    }
    result = fwrite(str1, strlen(str1), 1, file1);
    result = fwrite(str2, strlen(str2), 1, file2);
    result = fwrite(str1, strlen(str1), 1, file1);
    result = fwrite(str2, strlen(str2), 1, file2);
    fclose(file1);
    fclose(file2);
    return 0;
}

運行後結果如下:

first string
first string
second string
second string

從結果上來看 fopen僅僅是在打開文件後定位文件的末尾,每次都是在此基礎上寫入的。

5.9

在我的deepin15.11上分別輸出:

  1. echo is on , since its bit is 1
  2. bash: /dev/lp: 沒有那個文件或目錄
  3. tcgetattr: Inappropriate ioctl for device
  4. bash: tty: 沒有那個文件或目錄

5.10

我這裏兩個 tty 分別連接到 /dev/pts/1/dev/pts/2,按照書上的步驟第四步顯示回顯開啓,第五步顯示回顯關閉。
使用 stty 也是一樣,至於原因我還不知道…

5.13

查看了APUE相關章節,發現有三種 O_SYNC,O_SYNC要求等待數據和屬性都寫入才返回,O_DSYNC只要求等待數據寫入,O_RSYNC要求讀取時緩存中的所有內容全部讀取完才返回,至於習題中只要求 i-節點也就是屬性的沒有找到。

5.14

向終端文件寫入數據就是把數據發送到設備,權限寫意味着允許向終端發送數據(書上原話)。那麼讀權限就意味着允許接受終端數據。
可是我設置了權限以後向 ls 這樣的命令可以使用,who > /dev/pts/1 就提示權限不足了。

5.15

不支持 read 和 write 的沒找到,不支持 lseek 的有 gpmctl.

5.16

沒看懂題目

5.17

還是沒看懂題目

5.18

當我們在 shell 下運行 ls 這樣的命令的時候,實際上系統會先調用fork創建一個子進程,然後在調用exec運行ls程序。這個子進程的進程控制塊(PCB)是根據父進程複製而來的,所以其中控制終端的信息是一樣的,因此終端處於無回顯狀態。而每次打開同一個文件返回的文件描述符是不一樣的,是相互獨立的,所以不能自動獲得自動添加模式。

519

這道題想通過把終端的標準輸出設置爲O_APPEND,結果沒有成功…

5.20

通過fcntl設置的都是當前進程如何訪問設備或文件的訪問控制屬性,例如讀、寫、追加、非阻塞、加鎖 等,但並不設置文件或設備本身的屬性,例如文件的讀寫權限、串口波特率等。ioctl函數用於設置某些設備本身的屬性,例如串口波特率、終端窗口大小。

5.21

/dev/null設備文件只有一個作用,往它裏面寫任何數據都被直接丟棄。因此保證了該命令執行時屏幕上沒有任何輸出,既不打印正常信息也不打印錯誤信息,讓命令安靜地執行,這種寫法在 Shell 腳本中很常見。
/dev/zero是“零”設備,可以無限的提供空字符(0x00ASCII代碼NUL),常用來生成一個特定大小的文件。
除此之外還有/dev/random,隨機數設備,提供不間斷的隨機字節流,生隨機數據依賴系統中斷,當系統中斷不足時,/dev/random設備會“掛起”,因而產生數據速度較慢,但隨機性好;還有一個類似的叫/dev/urandom,不依賴系統中斷,數據產生速度快,但隨機性較低。

參考資料:
深入解析Linux內核I/O剖析(open,write實現)
rename代碼閱讀(linux 3.10.104)
Linux C編程一站式學習
Linux C 編程 —— fcntl、ioctl和stat區別
Linux中的虛擬設備/dev/null、/dev/zero、/dev/random和/dev/urandom

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章