File-Descriptors
將標準輸出 fd 傳遞給“讀取”系統呼叫,但它仍然可以正常工作
我將
1
(stdout)/2
(stderr) 傳遞給read
系統呼叫,但它仍然可以正常工作。然後我將0
(stdin) 傳遞給write
系統呼叫並發現它也有效!int main(int argc, char** argv){ char buf[1024] = "abcdefghi\n"; write(0, buf, 10); char readbuf[1024] = {0}; // read(1, readbuf, 10); works too read(2, readbuf, 10); write(2, readbuf, 10); return 0; }
輸出:
abcdefghi hey stdin <-- I input this hey stdin
很迷茫,我以為應該是錯誤。
實驗:
然後我嘗試重定向 fd 2。
$ ./a.out 2>/dev/null
這次讀取和第二次寫入都不是“可見的”。輸出是
abcdefgi
那麼stderr可以用於讀取嗎?
然後我關閉標準輸出和標準錯誤並製作兩個標準輸入副本:
int main(int argc, char** argv){ char buf[1024] = "abcdefghi\n"; close(1); close(2); dup2(0, 1); dup2(0, 2); write(0, buf, 10); char redbuf[1024] = {0}; read(2, redbuf, 10); write(2, redbuf, 10); return 0; }
它再次起作用。
輸出:
abcdefghi hey stdin <-- I input this hey stdin
那麼stdin可以用來寫嗎?
我在這裡需要一些解釋。
問題
我想知道:
為什麼 stdout/stderr 可以用於讀取?
為什麼stdin可以用於寫?
三個流(stdin,stdout,stderr)在內部是一個流嗎?
如果不是,為什麼我會得到這個結果?
僅將 fd 0/1/2 用於輸入/輸出/錯誤是慣例。如果您在沒有重定向的情況下呼叫程序,則所有三個都指向您的 tty,並且您的 tty 是打開的,具有讀寫訪問權限。這意味著您可以根據需要讀取或寫入它們。您可以將它們稱為相同的流,儘管表達式流通常用於更高級別的 I/O,例如
FILE
在 C 或stream
C++ 中。這就是為什麼兩個或不重定向的範例都只是回顯您輸入的文本的原因。
另一方面,如果您進行重定向,shell 將以只讀或只寫訪問權限打開文件。在您的範例
./a.out 2>/dev/null
中,寫入0
仍然連接到終端,因為它沒有被重定向,因此顯示在螢幕上。讀取2
連接到只寫/dev/null
,因此應該失敗,但您不會注意到與您的程序的區別。寫入2
成功,但寫入/dev/null
. 無效讀取和有效寫入/dev/null
在您的終端上不可見。