1. 程式人生 > >linux下的stdin,stdout和stderr

linux下的stdin,stdout和stderr

參考自
在linux中經常會看到stdin,stdout和stderr,這3個可以稱為終端(Terminal)的標準輸入(standard input),標準輸出(standard out)和標準錯誤輸出(standard error)。

通過man stdin檢視手冊,可以看到它們都是在stdio.h中定義的。當linux開始執行程式的時候,程式預設會開啟這3個檔案流,這樣就可以對終端進行輸入輸出操作。

下面用c語言模擬下這3個檔案流。

標準輸入(standard input)

在c語言中表現為呼叫scanf函式接受使用者輸入內容,即從終端裝置輸入內容。也可以用fscanf指明stdin接收內容。 標準輸入的檔案識別符號為0

#include <stdio.h>
 
intmain(void)
{
    charstr[10];
    scanf("%s", str);
    fscanf(stdin, "%s", str);
 
    return0;
}

標準輸出(standard out)

在c語言中表現為呼叫printf函式將內容輸出到終端上。使用fprintf也可以把內容輸出到終端上。標準輸出的檔案識別符號為1

#include <stdio.h>
 
intmain(void)
{
    printf("%s\n", "hello");
    fprintf
(stdout, "%s\n", "hello"); return0; }

標準錯誤輸出(standard error)

標準錯誤和標準輸出一樣都是輸出到終端上, 標準錯誤輸出的檔案識別符號為2。

在程式處理的時候,正常的資訊輸出作為標準輸出,產生錯誤的輸出作為標準錯誤輸出。這樣在重定向的時候,就可以將正常的資訊和錯誤的資訊重定向到不同的檔案。

#include <stdio.h>
 
intmain(void)
{
    printf("%s\n", "hello");
    fprintf(stderr, "%s\n", "error");
 
    return0;
}

上面這個程式分別往終端和stderr輸出了資訊,編譯這個程式生成二進位制檔案a.out,使用下列命令執行,重定向輸出。

# 1是stdout的檔案識別符號,而2是stderr的檔案識別符號
# "hello\n"重定向(輸出)至log.txt,而"error\n"重定向至error.txt
./a.out 1>log.txt 2>error.txt

這樣就把輸出的內容hello儲存到了log.txt檔案,錯誤的資訊error儲存到了error.txt檔案。(也就是通過管道重定位)

在c語言裡,也可以使用freopen函式重定向輸出流

#include <stdio.h>
 
intmain(void)
{
    FILE*out = freopen("out.txt", "w", stdout);
    printf("%s\n", "hello");
 
    return0;
}

上例程式碼編譯執行後,終端上並沒輸出內容,而是儲存到了out.txt這個檔案了。

stdout與stderr的區別

1. 在linux中,標準輸出和標準錯誤預設都是將資訊輸出到終端上,那麼他們有什麼區別呢?

讓我們來看個題目:
問題:下面程式的輸出是什麼?

#include <stdio.h>

int main()
{
    fprintf(stdout,"Hello ");
    fprintf(stderr,"World!");

    return 0;
}

答案是:World!Hello

這是為什麼呢?**在預設情況下,stdout是行緩衝的,它的輸出會先放在一個buffer裡面,只有到換行的時候,才會輸出到螢幕;而stderr是無緩衝的,會直接輸出。**舉例來說就是fprintf(stdout, “xxxx”) 和 fprintf(stdout, “xxxx\n”),前者在返回時並不重新整理buffer,直到遇到新行或函式返回時才會重新整理緩衝區並輸出;而fprintf(stderr, “xxxxx”),不管有沒有’\n’,都直接輸出。

首先,程式執行第一條列印語句時,由於stdout是行緩衝,而這裡沒有換行符,所以函式返回,要列印的內容還留在緩衝區裡; 然後,執行第二條列印語句,由於stderr是無緩衝,World!直接列印在終端上; 最後,函式執行返回語句return,緩衝區中的Hello 此時被沖洗,在終端打印出來。

所以,整個程式的執行結果就是:World!Hello

2. 當stdout、stderr遇到重定向,會發生什麼?

問題:下面的程式gcc編譯之後分別執行下面兩個命令,結果分別是什麼?

./a.out 1>stdout.file 
./a.out 2>stderr.file
#include <stdio.h>

int main()
{
    printf("a\n");

    fprintf(stdout,"b\n");

    fprintf(stderr, "c\n");

    return 0;
}

結果:

# a, b輸出至stdout.file,而螢幕顯示c
./a.out 1>stdout.file 
# c輸出至stderr.file,而螢幕顯示a, b
./a.out 2>stderr.file

總結

總的來說,stdin,stdout和stderr還是和終端有密切關係,通常在生產環境時,會將這3個流重定向到其它檔案。