www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式大雜燴
[導(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之美,稍微體會,便能得到。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之美,稍微體會,便能得到。

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

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

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

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

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

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

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

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

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

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

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

簡單來講,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)這段歷史,請看:
http://www.softpanorama.org/Scripting/Piporama/history.shtml

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


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

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

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

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

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

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

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

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

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

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

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

  2. Pipe符號"|"。

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

數(shù)學(xué)式子里的括號,其實(shí)它無關(guān)緊要,括號只是給人看的,它規(guī)定一些運(yùn)算的優(yōu)先級順序,這叫?中綴表達(dá)式?,一個(gè)中綴表達(dá)式可以輕松被轉(zhuǎn)換為?前綴表達(dá)式,后綴表達(dá)式?,從而消除括號。事實(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. 理解?“括號括起來的要優(yōu)先處理”?這句復(fù)雜的話;

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

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

× 8 ? 35就是(3 5)?×?8?的前綴表達(dá)式,可以看到,沒有了括號。對于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符號|分割每一個(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)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉