從bash源碼解讀重定向實現(一)
來自專欄我的雜記
本文從Linux系統調用, bash Shell程序源碼的角度分析了重定向的實現.
什麼是重定向
重定向本身不好定義. 但是重定向常用來把輸出到屏幕的字元保存到文件.
示例
Linux下打開終端, 運行命令 echo hello > test.txt
, 你會發現當前目錄下多了一個名為 test.txt
的文件, 其內容就是 hello
. 繼續運行 echo world >> test.txt
, 單詞 world
就被追加到 test.txt
中了.
重定向的原理
這麼好玩的功能究竟是怎麼實現的呢?
文件描述符
這還要從文件描述符說起.
我們都知道, linux系統下, 有一個系統級的打開文件表 (Open File Table).
而每個進程的 PCB (Process Control Block) 中都有一個文件描述符表 (File Descriptor Table), 進程就是通過文件描述符表中的文件描述符對文件進行操作的.每個文件描述符指向打開文件表中的一個文件. 不同的文件描述符卻可以指向同一個文件.
echo hello
時, 實際上是對文件描述符為1的文件的寫操作.
修改文件描述符的指向
讀到這裡, 我們就有了大概的思路, 如果我們趁程序不注意, 把文件描述符1指向用戶文件, 那麼原本輸出到屏幕的內容就寫入到文件里了.
那麼如何修改文件描述符的指向呢? 最簡單直接的系統調用就是 dup2
了, 除此之外還有dup
, dup3
和fcntl
.
int dup (int oldfd)
dup()系統調用創建文件描述符oldfd的拷貝並返回, 使用儘可能小的未使用文件描述符.
成功返回後, 新舊描述符可以交替使用.
int dup2(int oldfd, int newfd)
dup2()系統調用與dup()基本相同, 不同的是可以指定返回的文件描述符為newfd.如果newfd已經被打開, 就悄悄關閉它.
代碼實現重定向
test.c
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#define STDOUT 1 int main(int argc, char *argv[]){ int fd = open("test", O_CREAT|O_TRUNC|O_WRONLY, 0666); dup2(fd, STDOUT); close(fd); system("echo hello"); return 0;}
上面代碼執行後, 會生成一個內容為hello的文件test, 說明我們的試驗成功了.
而將代碼中的 O_TRUNC
改為 O_APPEND
, 就可以實現>>
的效果了.
從bash源碼解讀重定向實現(二)
推薦閱讀:
※獻給命令行重度用戶的一組實用 BASH 腳本
※【練習】bash shell
※初入命令行之必會
※命令行簡單命令用法,以及explainshell網站
※巴夏 Bashar:開朗起來,閃耀起來!