實(shí)際場(chǎng)景
- 在操作Linux命令行的時(shí)候蛮拔,如果需要將日志到處并保存到某個(gè)文件,我們可能會(huì)用到命令
2>&1
晃财,將“正常日志”和“錯(cuò)誤日志”都放在一起叨橱。 - 在寫Java應(yīng)用時(shí),我們經(jīng)常會(huì)用到
System.out.println(.....)
來打印程序運(yùn)行時(shí)的一些信息断盛,實(shí)際上Java還提供了System.err.println(.....)
方法用來打印程序出錯(cuò)時(shí)候的信息罗洗。
介紹
在Unix系統(tǒng)及類Unix系統(tǒng)中,Standard streams(標(biāo)準(zhǔn)流)是計(jì)算機(jī)程序與其環(huán)境之間钢猛,信息輸入和輸出的通道栖博。包括stdin,stdout和stderr.
根據(jù)POSIX協(xié)議厢洞,這3個(gè)標(biāo)準(zhǔn)流都有自己對(duì)應(yīng)的文件描述符(File_descriptor):
文件描述符(整數(shù)值) | 名稱 | <unistd.h>符號(hào)常量 | <stdio.h>文件流 |
---|---|---|---|
0 | Standard input | STDIN_FILENO | stdin |
1 | Standard output | STDOUT_FILENO | stdout |
2 | Standard error | STDERR_FILENO | stderr |
起源
a. 標(biāo)準(zhǔn)流(Standard streams)的起源
在Unix之前的操作系統(tǒng)仇让,程序必須明確指出鏈接到合適的輸入和輸出數(shù)據(jù)。對(duì)這當(dāng)中的許多系統(tǒng)而言躺翻,這牽涉一些錯(cuò)綜復(fù)雜而又與特定操作系統(tǒng)相關(guān)的事丧叽,過程相當(dāng)復(fù)雜(如控制環(huán)境設(shè)置、訪問一個(gè)文件表格公你、決定區(qū)域數(shù)據(jù)集踊淳、和決定讀卡器、磁帶、磁盤迂尝、打印機(jī)脱茉、打卡機(jī)或交互式終端機(jī))。
Unix 的偉大開創(chuàng)貢獻(xiàn)之一垄开,就是是提供 抽象設(shè)備 :它免除了程序須要知道或在意它正與哪個(gè)設(shè)備溝通琴许。 Unix 借由數(shù)據(jù)流的概念來消除這種復(fù)雜。數(shù)據(jù)流是指一種數(shù)據(jù)字節(jié)的有序序列溉躲,在其讀到文件結(jié)尾(End of file, EOF)之前可以一直被讀取榜田。另一個(gè) Unix 突破為默認(rèn)自動(dòng)鏈接輸入和輸出,程序(或者說編寫它的程序員)锻梳,不用為了文件的輸入箭券、輸出操心。在此之前疑枯,程序員需要用復(fù)雜的工作控制語言創(chuàng)建鏈接辩块,協(xié)調(diào)責(zé)任。
b. 文件描述符(File_descriptor)的起源
linux為了實(shí)現(xiàn)一切皆文件的設(shè)計(jì)哲學(xué)荆永,不僅將數(shù)據(jù)抽象成了文件废亭,也將一切操作和資源抽象成了文件,比如說硬件設(shè)備屁魏,socket滔以,磁盤捉腥,進(jìn)程氓拼,線程等。這樣的設(shè)計(jì)將系統(tǒng)的所有動(dòng)作都統(tǒng)一起來抵碟,實(shí)現(xiàn)了對(duì)系統(tǒng)的原子化操作桃漾,大大降低了維護(hù)和操作的難度,想想看拟逮,對(duì)于socket撬统,硬件設(shè)備,我們只要讀讀寫寫文件就能對(duì)其進(jìn)行操作是多么爽的一件事敦迄。
那么在操作這些所謂的文件的時(shí)候恋追,我們不可能沒操作一次就要找一次名字吧,這樣會(huì)耗費(fèi)大量的時(shí)間和效率罚屋。咱們可以每一個(gè)文件操作一個(gè)索引苦囱,這樣,要操作文件的時(shí)候脾猛,我們直接找到索引就可以對(duì)其進(jìn)行操作了撕彤。我們將這個(gè)索引叫做文件描述符(file descriptor),在系統(tǒng)里面是一個(gè)非負(fù)的整數(shù)猛拴。每打開或創(chuàng)建一個(gè)文件羹铅,內(nèi)核就會(huì)向進(jìn)程返回一個(gè)fd蚀狰,第一個(gè)打開文件是0,第二個(gè)是1职员,依次遞增麻蹋。
Linux的根目錄/dev
是 Device(設(shè)備)的縮寫。該目錄下存放的是 Linux 的外部設(shè)備廉邑,在 Linux 中訪問設(shè)備的方式和訪問文件的方式是相同的哥蔚。從該目錄下的內(nèi)容也可以看到標(biāo)準(zhǔn)流的影子
$ ll /dev |grep std
lrwxrwxrwx 1 root root 15 Jul 27 16:54 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jul 27 16:54 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jul 27 16:54 stdout -> /proc/self/fd/1
$ # Linux的文件描述符可以通過 /proc/PID/fd/ 路徑獲取使用。
應(yīng)用
- Linux命令行中蛛蒙,可以通過重定向符號(hào)(例如:>)來控制標(biāo)準(zhǔn)流的輸出糙箍,使用實(shí)例。
- Java應(yīng)用當(dāng)中牵祟,也可以通過java.lang.Process類來讀取/寫入標(biāo)準(zhǔn)流深夯,可參考源碼方法注釋。
Ref: