finish shell分析之語法直譯器

2021-09-22 13:59:42 字數 4629 閱讀 1256

如果說linux 的shell是屬於指令碼類的語言風格,那finsih shell的語言風格明顯是c的。畢竟c比較偏底層,資源占用少,這個對於資源貧瘠的嵌入式系統而言是非常適合的。finish shell從usart獲取文字資訊,在根據一定的語法規矩將文字語言重新按執行順序組織一遍,最後再將重新組織的語句翻譯成彙編指令,最後交由cpu執行指令。當然finsih shell的彙編指令都是偽彙編指令,而且執行的環境也是虛擬出來的,而這個是編譯執行過程,我之後再提。

語句的執行是以資料為基礎的。受限於系統的架構,finish shell裡面的資料型別並不多,整體來說分成以下幾個部分

針對上述的**,在int a中,int是指代變數型別,a是變數名,因為這條指令是在串列埠中讀取的,所以a是動態申請的變數,隸屬於var中。像『1』『2』『3』是屬於int型常量,而「+」「*」「-」是符號。而sys_var和sys_call是在編譯的時候生成的,分別通過巨集finsh_var_export和finsh_function_export新增到系統中的。

long hello()

finsh_function_export(hello, say hello world);

對於上述的hello函式,通過呼叫finsh_function_export就可以新增到finish shell中,在終端中輸入hello(),串列埠就可以列印"hello rt-thread!"。

#define finsh_function_export(name, desc)                     \

const char __fsym_##name##_name = #name;                     \

const char __fsym_##name##_desc = #desc;                     \

const struct finsh_syscall __fsym_##name section("fsymtab")= \

;

具體分析finsh_function_export(hello, say hello world),其實這個巨集就是申請了3個變數_fsym_hello_name=』hello』,_fsm_hello_desc=』hello rt-thread!\n』,_fsym_hello=。說穿了就是_fsym_hello裡有3個4位元組的指標,分別指向_fsym_hello_name,_fsm_hello_desc和hello()函式。那_fsym_hello是如何和sys_call扯上關係的呢?這就要從section("fsymtab")說起了。section()是乙個巨集變數,針對不同的編譯平台對於不同的操作,但無論編譯平台如何其作用是相同的。本人編譯平台是mdk,開啟rtthread-stm32.sct檔案我們可以看到

lr_irom1 0x08000000 0x00080000 

rw_iram1 0x20000000 0x00010000 

}

這個檔案作用主要是指出了編譯工程後鏈結檔案的各個段的位址空間。我們知道編譯程式一般會生成text,rodata,data,bss以及一些其他的段,我們可以通過sct將某個函式的**段放到某個位址空間,也可以將它的資料段放到另乙個位址空間。一般來說,我們不會蛋疼的去安排每個.c檔案或是函式的鏈結位址空間,因為系統已經預設優化好了但是我們必須知道是可以通過修改sct來改變鏈結位址空間的。這個相信研究過linux核心編譯的同學一定心領神會。然後再看rtthread-stm32.map檔案,我擷取了與fsymtab相關的一段。

fsymtab$$base       0x08013614   number   0 led.o(fsymtab)

__fsym_led         0x08013614   data    12 led.o(fsymtab)

__fsym_list_mem    0x08013620   data    12 mem.o(fsymtab)

__fsym_hello       0x0801362c   data    12 cmd.o(fsymtab)

__fsym_version     0x08013638   data    12 cmd.o(fsymtab)

__fsym_list_sem    0x08013644   data    12 cmd.o(fsymtab)

__fsym_list_event  0x08013650   data    12 cmd.o(fsymtab)

__fsym_list_mutex  0x0801365c   data    12 cmd.o(fsymtab)

__fsym_list_mailbox  0x08013668 data    12 cmd.o(fsymtab)

__fsym_list_msgqueue 0x08013674 data    12 cmd.o(fsymtab)

__fsym_list_mempool  0x08013680 data    12 cmd.o(fsymtab)

__fsym_list_timer  0x0801368c   data    12 cmd.o(fsymtab)

__fsym_list_device 0x08013698   data    12 cmd.o(fsymtab)

__fsym_list        0x080136a4   data    12 cmd.o(fsymtab)

__fsym_ls          0x080136b0   data    12 dfs_raw.o(fsymtab)

__fsym_mkdir       0x080136bc   data    12 dfs_raw.o(fsymtab)

__fsym_rm          0x080136c8   data    12 dfs_raw.o(fsymtab)

__fsym_cat         0x080136d4   data    12 dfs_raw.o(fsymtab)

__fsym_mkfs        0x080136e0   data    12 dfs_elm.o(fsymtab)

fsymtab$$limit      0x080136ec   number   0 dfs_elm.o(fsymtab)

region$$table$$base 0x080136ec   number   0 anon$$obj.o(region$$table)

region$$table$$limit 0x0801370c  number   0 anon$$obj.o(region$$table)

vsymtab$$base        0x0801370c  number   0 cmd.o(vsymtab)

__vsym_dummy      0x0801370c   data    16 cmd.o(vsymtab)

vsymtab$$limit      0x0801371c   number   0 cmd.o(vsymtab)

相信大家找到了_fsym_hello了吧,所謂的section("fsymtab")也就是把_fsym_hello這個12個位元組的常量,儲存在fsymtab這個段內,鏈結的時候根據sct檔案安排按順序將fsymtab放到flash的位址空間裡去。也就是說,無論我在這個或那個檔案用呼叫了finsh_function_export,說生成的_fsym***一定是連續分布在flash的位址空間了。finsh_var_export的執行原理和finsh_function_export一樣,只不過存的是變數的位址,我就不再重複說明了

至於為什麼要這麼大費周章的將fsymtab和vsymtab的變數放到一起,就是為了方便生成syscall_table和sysvar_table。在finsh_system_init中有兩個函式finsh_system_function_init(&fsymtab$$base, &fsymtab$$limit);

finsh_system_var_init(&vsymtab$$base, &vsymtab$$limit);

void finsh_system_function_init(void* begin, void* end)

void finsh_system_var_init(void* begin, void* end)

再看一下rtthread-stm32.map,是不是找到了fsymtab$$base,fsymtab$$limit和vsymtab$$base, vsymtab$$limit,就這樣我們生成了syscall_table和sysvar_table,而這系統就是用這兩個表來查詢sys_call和sys_var變數的。

除了靜態的生成sys_call函式外,rt_thread也支援動態的載入sys_call函式。

else

}} 注意這裡將函式新增到了global_syscall_list鍊錶中了,而這個鍊錶的功能是相當於syscall_table的,只不過它是負責動態生成的sys_call。與之對應的有global_sysvar_list鍊錶,其對應的是sys_var。

Spring boot原始碼分析 yaml語言(9)

yaml j m l 和camel同發音 是人類可讀的 資料序列化語言。它通常用於配置檔案js yaml yaml表示 json表示 備註資訊 使用內嵌塊的表示方式 物件 name petspeople 水果 蘋果 西瓜 桃子水果 蘋果,西瓜,桃子,果汁 資料 曾經有乙份真摯的愛情 擺在我的面前 門...

隨心所語之「讀書」

電腦科學與技術畢業,幹c 開發4年,但是,發現好多東西 甚至是相關的東西都不會 不懂,於是,就需要學習,需要讀書。也許,這就是所謂的學無止境。我買的書,有30 本,但是看完的,卻是寥寥無幾,為什麼呢?簡單乙個詞 沒有恆心。但是,為什麼會沒有恆心呢?這裡,我有點沒 恆心 的心得,希望糾正這些之後,可以...

隨心所「語」之 STL

自己是個程式設計師,用c 開發也有5年時間了。期間,stl用的挺多了,對其印象也挺好的。網上 周圍,許多人都不用stl,對此我比較疑惑。網上找了下,發現主要有下面幾個問題 1 膨脹。stl是模板實現,在每乙個宣告 使用的地方,都會擴充套件,導致 膨脹。個人看法 的確存在這樣乙個問題,暫時也沒看到好的...