當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式大雜燴
[導(dǎo)讀]關(guān)注「Linux大陸」,一起進(jìn)步!繼?300來行代碼帶你實(shí)現(xiàn)一個(gè)能跑的最小Linux文件系統(tǒng)?之后,我們來看看如何60行C代碼實(shí)現(xiàn)一個(gè)shell!在實(shí)現(xiàn)它之前,先看看這樣做的意義。美是有目共睹的。Unix之美,稍微體會(huì),便能得到。1969年,Unix初始,沒有fork,沒有exe...

關(guān)注Linux大陸」,一起進(jìn)步!


繼?300來行代碼帶你實(shí)現(xiàn)一個(gè)能跑的最小Linux文件系統(tǒng)?之后,我們來看看如何60行C代碼實(shí)現(xiàn)一個(gè)shell!

在實(shí)現(xiàn)它之前,先看看這樣做的意義。

美是有目共睹的。Unix之美,稍微體會(huì),便能得到。

1969年,Unix初始,沒有fork,沒有exec,沒有pipe,沒有?“一切皆文件”?,但是那時(shí)它已經(jīng)是Unix了。它簡(jiǎn)單,可塑。

Melvin Conway在1963年的論文中敘述fork思想時(shí)就解釋說并行路徑要用結(jié)果來交互,也就是在匯合的join點(diǎn)來同步結(jié)果。這個(gè)同步點(diǎn)所得到的,就是一個(gè)并行進(jìn)程的?輸出?。

在此之外,Unix還有另一個(gè)原則,就是?組合小程序!

Unix把一系列功能單一的小程序組合成一個(gè)復(fù)雜的邏輯,這個(gè)原則有以下優(yōu)勢(shì):

  • 每一個(gè)小程序都很容易編寫。

  • 每一個(gè)小程序可以分別完成。

  • 每一個(gè)小程序可以分別迭代修復(fù)。

  • 多個(gè)小程序可以自由組合。

這是典型的模塊化思想,小到統(tǒng)籌佐餐燒飯,大到組成生命的嘌呤嘧啶,都不自覺地和這種模塊化思想相契機(jī),原來這就是真理。?程序盡量小,只做一件事并且做好它。

Unix程序在自身的邏輯之外對(duì)外暴露的只有輸入和輸出。那么?用輸出連接另一個(gè)程序輸入?就是一種好的方法。所謂Conway的join點(diǎn)對(duì)于Unix進(jìn)程指的就是輸出。

對(duì)外暴露的越少,程序越內(nèi)聚。這是一種范式,類似RISC處理器也是抽象出僅有的load和store來和內(nèi)存交互。

簡(jiǎn)單來講,Unix程序通過輸入和輸出來彼此連接。下面是一幅來自Wiki的圖示:

詳見Pipeline (Unix):
https://en.wikipedia.org/wiki/Pipeline_(Unix)

Unix的另一個(gè)原則,即著名的?“一切皆文件!”?連接輸出和輸入的那個(gè)管道在Unix中被實(shí)現(xiàn)為Pipe,顯然,它也是文件,一個(gè)FIFO文件。

說實(shí)話,協(xié)作幾個(gè)小程序形成一個(gè)大邏輯的思想還是來自于Convey,在Convey的論文里,他稱為?協(xié)程,?Pile可以說是直接實(shí)現(xiàn)了?Convey協(xié)程?之間的交互。有關(guān)這段歷史,請(qǐng)看:
http://www.softpanorama.org/Scripting/Piporama/history.shtml

用Pipe連接作為輸出和輸入連接Unix進(jìn)程可以做成什么事情呢?讓我們?nèi)ジ惺芤粋€(gè)再熟悉不過的實(shí)例,即數(shù)學(xué)式子:


我們把運(yùn)算符加號(hào),乘號(hào),除號(hào)(暫不考慮括號(hào),稍后解釋為什么)這些看作是程序(事實(shí)上它們也真的是),那么類似數(shù)字3,5,7,6就是這些程序的輸入了,這個(gè)式子最終需要一個(gè)輸出,獲得這個(gè)輸出的過程如下:

  1. 數(shù)字3,5是加號(hào)程序的輸入,3 5執(zhí)行,它獲得輸出8.

  2. 第1步中的輸出8連同數(shù)字7作為乘號(hào)程序的輸入,8 ×?7執(zhí)行,獲得輸出56.

  3. 第2步中的輸出56連同數(shù)字6作為除號(hào)的輸入,…

這個(gè)數(shù)學(xué)式子的求值過程和pipe連接的Unix程序組合獲得最終結(jié)果的過程完全一致。

如果你相信數(shù)學(xué)可以描述整個(gè)世界,那么Pipe連同Unix程序同樣是描述這個(gè)世界的語言 。

在數(shù)學(xué)領(lǐng)域,程序?就是所有的運(yùn)算符,加號(hào),減號(hào),乘號(hào),除號(hào),乘方,開方,求和,積分,求導(dǎo)…它們無一例外,?只做一件事。

在Unix看來也同樣。它做的事情和下面的應(yīng)該差不多,而且更多:

寫出上面的式子中每一個(gè)數(shù)學(xué)運(yùn)算符的程序并不困難,比如加號(hào)程序:

// plus.c
#include
int main(int argc, char **argv)
{
int a, b;

a = atoi(argv[1]);
b = atoi(argv[2]);

a = a b;
printf("%d\n", a);
}
同樣,我們可以寫出除法,直到偏導(dǎo)的程序。然后我們通過pipe就能將它們組合成任意的數(shù)學(xué)式子。

現(xiàn)在談?wù)刄nix組合程序的具體寫法,如果我們要化簡(jiǎn)薛定諤方程,我們應(yīng)該如何用Unix命令寫出與上述式子等價(jià)的組合程序命令行呢?我們無法像數(shù)學(xué)家手寫那樣隨意使用括號(hào),顯然,計(jì)算機(jī)并不認(rèn)識(shí)它。我們能夠使用的只有兩個(gè)符號(hào):

  1. 代表具體Unix小程序的命令。

  2. Pipe符號(hào)"|"。

換句話說,我們需要寫出一個(gè)?鏈?zhǔn)浇M合表達(dá)式。?這時(shí)就要用到前綴表達(dá)式了。

數(shù)學(xué)式子里的括號(hào),其實(shí)它無關(guān)緊要,括號(hào)只是給人看的,它規(guī)定一些運(yùn)算的優(yōu)先級(jí)順序,這叫?中綴表達(dá)式?,一個(gè)中綴表達(dá)式可以輕松被轉(zhuǎn)換為?前綴表達(dá)式,后綴表達(dá)式?,從而消除括號(hào)。事實(shí)上,Unix的Pipe最初也面臨過這樣的問題,到底是中綴好呢,還是前/后綴好呢?

我們現(xiàn)在使用的Unix/Linux命令,以cp舉例:

cp $in $out
這是一個(gè)典型的前綴表達(dá)式,但是當(dāng)pipe的發(fā)明者M(jìn)cIlroy最初引入pipe試圖組合各個(gè)程序時(shí),最初上面的命令行被建議成:

$in cp $out
就像我們的(3 5) ×?8 一樣。但是這非常不適合計(jì)算機(jī)處理的風(fēng)格,計(jì)算機(jī)不得不首先掃描解析這個(gè)式子,試圖:

  1. 理解?“括號(hào)括起來的要優(yōu)先處理”?這句復(fù)雜的話;

  2. 區(qū)分哪些是輸入,哪些是操作符…

對(duì)于式子(3 5) ×?8?的求值,計(jì)算機(jī)更適合用一種在簡(jiǎn)單規(guī)則下非常直接的方式去?順序執(zhí)行?求解,這就是前綴表達(dá)式的優(yōu)勢(shì)。

× 8 ? 35就是(3 5)?×?8?的前綴表達(dá)式,可以看到,沒有了括號(hào)。對(duì)于pipe組合程序而言,同樣適用于這個(gè)原則。于是前綴命令成了pipe組合命令的首選,現(xiàn)如今,我們可以用:

pro1 $stdin|pro2|pro3|pro4|...|proX $stdout
輕松組合成任意復(fù)雜的邏輯。

Pipe協(xié)同組合程序的Unix原則是一個(gè)創(chuàng)舉,程序就是一個(gè)加工過濾器,它把一系列的輸入經(jīng)過自己的程序邏輯生成了一系列的輸出,該輸出又可以作為其它程序的輸入。

在Unix/Linux中,各種shell本身就實(shí)現(xiàn)了這樣的功能,但是為了徹底理解這種處理方式的本質(zhì),只能自己寫一個(gè)才行。來寫一個(gè)微小的shell吧。

再次看上面提到的Unix Pipe的處理序列:

pro1 $stdin|pro2|pro3|pro4|...|proX $stdout
如果讓一個(gè)shell處理以上組合命令,要想代碼量少,典型方案就是遞歸,然后用Pipe把這些遞歸調(diào)用過程給串起來,基本邏輯如下:

int exec_cmd(CMD *cmd, PIPE pipe)
{
// 持續(xù)解析命令行,以pipe符號(hào)|分割每一個(gè)命令
while (cmd->next) {
PIPE pp = pipe_create();
if (fork() > 0) {
// 父進(jìn)程遞歸解析下一個(gè)
exec_cmd(cmd->next, pp);
return 0;
}
// 子進(jìn)程執(zhí)行
dup_in_out(pp);
exec(cmd->cmdline);
}
if (fork() > 0) {
wait_all_child();
return 0;
} else {
dup_in_out(pp);
exec(cmd->cmdline);
}
}
按照上面的思路實(shí)現(xiàn)出來,大概60行左右代碼就可以:

// tinysh.c
// gcc tinysh.c -o tinysh
#include
#include
#include
#include

#define CMD_BUF_LEN 512
char cmd[CMD_BUF_LEN] = {0};

void fork_and_exec(char *cmd, int pin, int pout)
{
if (fork() == 0) {
if (pin != -1) {
dup2 (pin, 0);
close(pin);
}
if (pout != -1) {
dup2 (pout, 1);
close(pout);
}
system(cmd);
exit(0);
}
if (pin != -1)
close(pin);
if (pout != -1)
close(pout);
}

int execute_cmd(char *cmd, int in)
{
int status;
char *p = cmd;
int pipefd[2];

while (*p) {
switch (*p) {
case '|':
*p = 0;
pipe(pipefd);
fork_and_exec(cmd, in, pipefd[1]);
execute_cmd(p, pipefd[0]);
return 0;
default:
p ;
}
}
fork_and_exec(cmd, in, -1);
while(waitpid(-1,
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉