Shell

shell/init 如何創建 stdio 流?

  • January 14, 2020

我正在閱讀 MIT’s xv6 OS的原始碼。這個片段出現在開頭sh.c

// Ensure that three file descriptors are open.
while((fd = open("console", O_RDWR)) >= 0){
   if(fd >= 3){
     close(fd);
     break;
   }
}

我知道這通過檢查新分配的文件描述符是否高於(或等於)3來檢查是否打開了至少3個文件描述符(可能是stdin、stdout和stderr)。

1)如何open從同一個程序多次訪問同一個設備並期望不同的文件描述符?

2)為了理解這一點,我在我的主機(x86_64 Linux 4.6.0.1)上執行了一個類似的片段。測試程序open在循環中重複編輯一個文本文件,看看我們是否可以期待不同的 fd,但它總是產生相同的文件描述符。由此,我得出結論,open-ing 一個真實的文件和一個設備(如/dev/console)在某種程度上有所不同,因為來自 xv6 的片段顯然有效(在 Qemu 中測試)。究竟有什麼區別?

#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>

int main(void)
{
   int fd;
   int cnt = 0;

   while ((fd = open("sample.txt", O_RDWR) > 0)) {
       if (cnt != 10) {
           cnt++;
           printf("File descriptor opened: %d\n", fd);
       } else {
           break;
       }
   }

   return 0;
}

這是執行它的輸出:

$ ./a.out
File descriptor opened: 1
File descriptor opened: 1
[snip]
File descriptor opened: 1
File descriptor opened: 1

編輯基於其中一個答案,我strace在執行檔上執行,發現open 確實返回了多個文件描述符,但由於某種原因,所有這些文件描述符都沒有列印出來。為什麼會這樣?

  1. 有點不相關,但在 fds 0-2 中使用 stdio 流的慣例不就是這樣 - 慣例嗎?例如,如果初始化序列將輸入/輸出文件描述符分配給其他東西 - 它會以某種方式影響其子代如何進行 I/O 操作嗎?

這實際上是3個問題。立即處理#2,因為程序不正確:

   while ((fd = open("sample.txt", O_RDWR) > 0)) {

你可能是說

   while ((fd = open("sample.txt", O_RDWR)) > 0) {

使用不正確放置的括號,您只測試是否fd大於零(因為文件描述符 0、1 和 2 是打開的,這可能是一個很好的假設)。

對於#1:open呼叫(成功時)被定義為返回不同的文件描述符。如果設備無法重新打開,open將返回-1.

對於#3:當然,這是一個約定,但也在POSIX標準中。其他系統使用了其他約定,包括為每個程序設置第四個開放流。

進一步閱讀:使用您的 Aegis 環境(1988 年 7 月)

參見第 6-9 頁,其中說 Apollo Domain/OS 有錯誤輸入和**輸出*

引用自:https://unix.stackexchange.com/questions/313344