本文並非闡述文件描述符與文件句柄的異同,而是標準
這是怎樣的標準呢?
fork
創建一個進程,規定默認存在3個文件描述符,分別是
描述符編號 | 簡介 | 作用 |
---|---|---|
0 | 標準輸入 | 通用於獲取輸入的文件描述符 |
1 | 標準輸出 | 通用輸出普通信息的文件描述符 |
2 | 標準錯誤 | 通用輸出錯誤信息的文件描述符 |
標準輸入比較好理解,在函數scanf
中,就是從標準輸入獲取的數據。我們執行一個命令,只要此命令在前臺執行,標準輸入就是我們在終端的輸入。
標準輸出與標準錯誤用途是有差別的。從命名上我們就發現,標準錯誤用於輸出錯誤信息,而標準輸出更多隻是輸出提示信息。通過不同的文件描述符,把普通的提示信息和錯誤提示信息區分開,非常方便於過濾日誌。
在默認情況下,標準輸出和標準錯誤都指向同一個文件,如果在終端前臺執行,那麼不管是標準輸出還是標準錯誤,都是輸出到終端。
C語言對標準的運用
C中與這標準相關的宏有六個,
標準 | stdio.h | unistd.h |
---|---|---|
標準輸入 | stdin | STDIN_FILENO |
標準輸出 | stdout | STDOUT_FILENO |
標準錯誤 | stderr | STDERR_FILENO |
stdin
和 STDIN_FILENO
都指向的是標準輸入,前者是 FILE
類型,就是我們所說文件句柄,而後者是int
類型,就是我們所說的文件描述符。標準輸出和標準錯誤也是一樣的情況。
所以,在不同的C接口,我們需要用不同的宏。
fprintf(stdout, "stdout\n");
write(STDOUT_FILENO, "STDOUT_FILENO\n", 14);
前面有提到,標準輸入、標準輸出、標準錯誤是默認存在的,也就是說我們不需要open
或者fopen
,可以直接使用。例如
#include <stdio>
int main(int argc, char **argv)
{
fprintf(stderr, "something error\n");
}
Shell對標準的運用
Shell命令經常用到的 重定向 實際上就是對標準的運用
標準 | 運用 | 示例 |
---|---|---|
標準輸入 | < | cat < helloworld.c |
標準輸出 | > 或者 1> | echo "helloworld" > stdout.log |
標準錯誤 | 2> | grep "error" 2>/dev/null |
C&Shell配合
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv)
{
char input[100];
FILE *file;
fprintf(stdout, "stdout\n");
fprintf(stderr, "stderr\n");
write(STDOUT_FILENO, "STDOUT_FILENO\n", strlen("STDOUT_FILENO\n"));
write(STDERR_FILENO, "STDERR_FILENO\n", strlen("STDERR_FILENO\n"));
}
在Bash shell中直接執行,默認情況下,標準輸出和標準錯誤都輸出到終端
[GMPY@14:43 tmp]$./stdio
stdout
stderr
STDOUT_FILENO
STDERR_FILENO
通過Shell重定向的方法,區分開標準輸出和標準錯誤的日誌
[GMPY@14:43 tmp]$./stdio 2>stderr.log 1>stdout.log
[GMPY@14:47 tmp]$cat stderr.log
stderr
STDERR_FILENO
[GMPY@14:47 tmp]$cat stdout.log
STDOUT_FILENO
stdout
[GMPY@14:47 tmp]$