男女直接做的視頻視頻網(wǎng)站蘇州seo怎么做
系列篇從內(nèi)核視角用一句話概括shell
的底層實現(xiàn)為:兩個任務(wù),三個階段。其本質(zhì)是獨立進程,因而劃到進程管理模塊。每次創(chuàng)建shell
進程都會再創(chuàng)建兩個任務(wù)。
- 客戶端任務(wù)(ShellEntry):?負責(zé)接受來自終端(控制臺)敲入的一個個字符,字符按
VT
規(guī)范組裝成一句句的命令。 - 服務(wù)端任務(wù)(ShellTask):?對命令進行解析并執(zhí)行,將結(jié)果輸出到控制臺。
而按命令生命周期可分三個階段.
- 編輯:?鴻蒙在這個部分實現(xiàn)了一個簡單的編輯器功能,處理控制臺輸入的每個字符,主要包括了對控制字符 例如?
<ESC>
,\t
,\b
,\n
,\r
,四個方向鍵0x41
?~?0x44
?的處理。 - 解析:?對編輯后的字符串進行解析,解析出命令項和參數(shù)項,找到對應(yīng)的命令項執(zhí)行函數(shù)。
- 執(zhí)行:?命令可通過靜態(tài)和動態(tài)兩種方式注冊到內(nèi)核,解析出具體命令后在注冊表中找到對應(yīng)函數(shù)回調(diào)。將結(jié)果輸出到控制臺。
編輯部分由客戶端任務(wù)完成,后兩個部分由服務(wù)端任務(wù)完成,命令全局注冊由內(nèi)核完成。
- 本篇主要說?客戶端任務(wù)?和?編輯過程
- 服務(wù)端任務(wù)?和?解析/執(zhí)行過程?已在 (Shell解析篇) 中說明,請自行翻看.
什么是 Shell
從用戶視角看,shell
是用戶窺視和操作內(nèi)核的一個窗口,內(nèi)核并非鐵板一塊,對應(yīng)用層開了兩個窗口,一個是系統(tǒng)調(diào)用,一個就是shell
,由內(nèi)核提供實現(xiàn)函數(shù),由用戶提供參數(shù)執(zhí)行。區(qū)別是?shell
是由獨立的任務(wù)去完成,可通過將shell
命令序列化編寫成獨立的,簡單的shell
程序,所以shell
也是一門腳本語言,系統(tǒng)調(diào)用是依附于應(yīng)用程序的任務(wù)去完成,能做的有限。通過shell
窗口能看到?cpu
的運行情況,內(nèi)存的消耗情況,網(wǎng)絡(luò)的鏈接狀態(tài)等等。
鴻蒙 Shell 代碼在哪
與shell
對應(yīng)的概念是kernel
,在鴻蒙內(nèi)核,這兩部分代碼是分開放的,shell
代碼在?查看 shell 代碼 ,目錄結(jié)構(gòu)如下.
├─include
│ dmesg.h
│ dmesg_pri.h
│ shcmd.h
│ shcmdparse.h
│ shell.h
│ shell_lk.h
│ shell_pri.h
│ shmsg.h
│ show.h
│
└─src├─base│ shcmd.c│ shcmdparse.c│ shell_lk.c│ shmsg.c│ show.c│└─cmdsdate_shellcmd.cdmesg.chwi_shellcmd.cshell_shellcmd.cwatch_shellcmd.c
Shell 控制塊
跟進程,任務(wù)一樣,每個概念的背后需要一個主結(jié)構(gòu)體來的支撐,shell
的主結(jié)構(gòu)體就是ShellCB
,掌握它就可以將shell
拿捏的死死的,搞不懂這個結(jié)構(gòu)體就讀不懂shell
的內(nèi)核實現(xiàn).所以在上面花再多功夫也不為過.
typedef struct {UINT32 consoleID; //控制臺IDUINT32 shellTaskHandle; //shell服務(wù)端任務(wù)IDUINT32 shellEntryHandle; //shell客戶端任務(wù)IDVOID *cmdKeyLink; //待處理的shell命令鏈表VOID *cmdHistoryKeyLink;//已處理的歷史記錄鏈表,去重,10個VOID *cmdMaskKeyLink; //主要用于方向鍵上下遍歷歷史命令UINT32 shellBufOffset; //buf偏移量UINT32 shellKeyType; //按鍵類型EVENT_CB_S shellEvent; //事件類型觸發(fā)pthread_mutex_t keyMutex; //按鍵互斥量pthread_mutex_t historyMutex; //歷史記錄互斥量CHAR shellBuf[SHOW_MAX_LEN]; //shell命令buf,接受鍵盤的輸入,需要對輸入字符解析.CHAR shellWorkingDirectory[PATH_MAX];//shell的工作目錄
} ShellCB;
//一個shell命令的結(jié)構(gòu)體,命令有長有短,鴻蒙采用了可變數(shù)組的方式實現(xiàn)
typedef struct {UINT32 count; //字符數(shù)量LOS_DL_LIST list; //雙向鏈表CHAR cmdString[0]; //字符串,可變數(shù)組的一種實現(xiàn)方式.
} CmdKeyLink;enum {STAT_NOMAL_KEY, //普通的按鍵STAT_ESC_KEY, //<ESC>鍵在VT控制規(guī)范中時控制的起始鍵STAT_MULTI_KEY //組合鍵
};
解讀
- 鴻蒙支持兩種方式在控制臺輸入
Shell
命令,關(guān)于控制臺請自行翻看控制臺篇.- 在串口工具中直接輸入
Shell
命令?CONSOLE_SERIAL
。 - 在
telnet
工具中輸入Shell
命令?CONSOLE_TELNET
。
- 在串口工具中直接輸入
shellTaskHandle
和shellEntryHandle
編輯/處理shell
命令的兩個任務(wù)ID,本篇重點說后一個.cmdKeyLink
,cmdHistoryKeyLink
,cmdMaskKeyLink
是三個類型為CmdKeyLink
的結(jié)構(gòu)體,本質(zhì)是雙向鏈表,對應(yīng)編輯shell
命令過程中的三個功能.cmdKeyLink
?待執(zhí)行的命令鏈表cmdHistoryKeyLink
?存儲命令歷史記錄的,即:?history
命令顯示的內(nèi)容cmdMaskKeyLink
?記錄按上下方向鍵輸出的內(nèi)容,這個有點難理解,自行在shell
中按上下方向鍵自行體驗
shellBufOffset
和shellBuf
是成對出現(xiàn)的,其中存放的就是用戶敲入處理后的字符.keyMutex
和historyMutex
為操作鏈表所需的互斥鎖,內(nèi)核用的最多的就是這類鎖.shellEvent
用于任務(wù)之間的通訊,比如.SHELL_CMD_PARSE_EVENT
:編輯完成了通知解析任務(wù)開始執(zhí)行CONSOLE_SHELL_KEY_EVENT
:收到來自控制臺的CTRL + C
信號產(chǎn)生的事件.
shellKeyType
?按鍵的類型,分三種 普通,鍵,組合鍵shellWorkingDirectory
?工作區(qū)就不用說了,從哪個目錄進入shell
的
創(chuàng)建 Shell
//shell進程的入口函數(shù)
int main(int argc, char **argv)
{//...g_shellCB = shellCB;//全局變量,說明鴻蒙同時只支持一個shell進程return OsShellCreateTask(shellCB);//初始化兩個任務(wù)
}
//創(chuàng)建shell任務(wù)
STATIC UINT32 OsShellCreateTask(ShellCB *shellCB)
{UINT32 ret = ShellTaskInit(shellCB);//執(zhí)行shell命令的任務(wù)初始化if (ret != LOS_OK) {return ret;}return ShellEntryInit(shellCB);//通過控制臺接收shell命令的任務(wù)初始化
}
//進入shell客戶端任務(wù)初始化,這個任務(wù)負責(zé)編輯命令,處理命令產(chǎn)生的過程,例如如何處理方向鍵,退格鍵,回車鍵等
LITE_OS_SEC_TEXT_MINOR UINT32 ShellEntryInit(ShellCB *shellCB)
{UINT32 ret;CHAR *name = NULL;TSK_INIT_PARAM_S initParam = {0};if (shellCB->consoleID == CONSOLE_SERIAL) {name = SERIAL_ENTRY_TASK_NAME;} else if (shellCB->consoleID == CONSOLE_TELNET) {name = TELNET_ENTRY_TASK_NAME;} else {return LOS_NOK;}initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ShellEntry;//任務(wù)入口函數(shù)initParam.usTaskPrio = 9; /* 9:shell task priority */initParam.auwArgs[0] = (UINTPTR)shellCB;initParam.uwStackSize = 0x1000;initParam.pcName = name;initParam.uwResved = LOS_TASK_STATUS_DETACHED;ret = LOS_TaskCreate(&shellCB->shellEntryHandle, &initParam);//創(chuàng)建任務(wù)
#ifdef LOSCFG_PLATFORM_CONSOLE(VOID)ConsoleTaskReg((INT32)shellCB->consoleID, shellCB->shellEntryHandle);//將任務(wù)注冊到控制臺
#endifreturn ret;
}
解讀
main
為shell
進程的主任務(wù),每個進程都會創(chuàng)建一個默認的線程(任務(wù)),這個任務(wù)的入口函數(shù)就是大家熟知的main
函數(shù),不清楚的自行翻看任務(wù)管理各篇有詳細的說明.- 由
main
任務(wù)再創(chuàng)建兩個任務(wù),即本篇開頭說的兩個任務(wù),本篇重點說其中的一個?ShellEntry
,任務(wù)優(yōu)先級為9
,算是較高優(yōu)先級. - 指定內(nèi)核棧大小為
0x1000 = 4K
?,因任務(wù)只負責(zé)編輯處理控制臺輸入的字符,命令的執(zhí)行在其他任務(wù),所以4K的內(nèi)核空間足夠使用. ShellEntry
為入口函數(shù),這個函數(shù)的實現(xiàn)為本篇的重點
ShellEntry | 編輯過程
LITE_OS_SEC_TEXT_MINOR UINT32 ShellEntry(UINTPTR param)
{CHAR ch;INT32 n = 0;ShellCB *shellCB = (ShellCB *)param;CONSOLE_CB *consoleCB = OsGetConsoleByID((INT32)shellCB->consoleID);//獲取控制臺if (consoleCB == NULL) {PRINT_ERR("Shell task init error!\n");return 1;}(VOID)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);//重置shell命令bufwhile (1) {
#ifdef LOSCFG_PLATFORM_CONSOLEif (!IsConsoleOccupied(consoleCB)) {//控制臺是否被占用
#endif/* is console ready for shell ? */n = read(consoleCB->fd, &ch, 1);//從控制臺讀取一個字符內(nèi)容,字符一個個處理if (n == 1) {//如果能讀到一個字符ShellCmdLineParse(ch, (pf_OUTPUT)dprintf, shellCB);}if (is_nonblock(consoleCB)) {//在非阻塞模式下暫停 50msLOS_Msleep(50); /* 50: 50MS for sleep */}
#ifdef LOSCFG_PLATFORM_CONSOLE}
#endif}
}
//對命令行內(nèi)容解析
LITE_OS_SEC_TEXT_MINOR VOID ShellCmdLineParse(CHAR c, pf_OUTPUT outputFunc, ShellCB *shellCB)
{const CHAR ch = c;INT32 ret;//不是回車鍵和字符串結(jié)束,且偏移量為0if ((shellCB->shellBufOffset == 0) && (ch != '\n') && (ch != '\0')) {(VOID)memset_s(shellCB->shellBuf, SHOW_MAX_LEN, 0, SHOW_MAX_LEN);//重置buf}//遇到回車或換行if ((ch == '\r') || (ch == '\n')) {if (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1)) {shellCB->shellBuf[shellCB->shellBufOffset] = '\0';//字符串結(jié)束}shellCB->shellBufOffset = 0;(VOID)pthread_mutex_lock(&shellCB->keyMutex);OsShellCmdPush(shellCB->shellBuf, shellCB->cmdKeyLink);//解析回車或換行(VOID)pthread_mutex_unlock(&shellCB->keyMutex);ShellNotify(shellCB);//通知任務(wù)解析shell命令return;} else if ((ch == '\b') || (ch == 0x7F)) { /* backspace or delete(0x7F) */ //遇到刪除鍵if ((shellCB->shellBufOffset > 0) && (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1))) {shellCB->shellBuf[shellCB->shellBufOffset - 1] = '\0';//填充`\0`shellCB->shellBufOffset--;//buf減少outputFunc("\b \b");//回調(diào)入?yún)⒑瘮?shù)}return;} else if (ch == 0x09) { /* 0x09: tab *///遇到tab鍵if ((shellCB->shellBufOffset > 0) && (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1))) {ret = OsTabCompletion(shellCB->shellBuf, &shellCB->shellBufOffset);//解析tab鍵if (ret > 1) {outputFunc("OHOS # %s", shellCB->shellBuf);//回調(diào)入?yún)⒑瘮?shù)}}return;}/* parse the up/down/right/left key */ret = ShellCmdLineCheckUDRL(ch, shellCB);//解析上下左右鍵if (ret == LOS_OK) {return;}if ((ch != '\n') && (ch != '\0')) {//普通的字符的處理if (shellCB->shellBufOffset < (SHOW_MAX_LEN - 1)) {//buf范圍shellCB->shellBuf[shellCB->shellBufOffset] = ch;//直接加入} else {shellCB->shellBuf[SHOW_MAX_LEN - 1] = '\0';//加入字符串結(jié)束符}shellCB->shellBufOffset++;//偏移量增加outputFunc("%c", ch);//向終端輸出字符}shellCB->shellKeyType = STAT_NOMAL_KEY;//普通字符
}
解讀
ShellEntry
內(nèi)部是個死循環(huán),不斷的讀取控制臺輸入的每個字符,注意是按字符處理.- 處理四個方向,換行回車,
tab
,backspace
,delete
,esc
?等控制鍵,相當(dāng)于重新認識了下Ascii
表.可以把shell
終端理解為一個簡單的編輯器.- 按回車鍵 表示完成前面的輸入,進入解析執(zhí)行階段.
- 按方向鍵 要顯示上/下一個命令的內(nèi)容,一直按就一直顯示上上/下下命令.
- 按
tab
鍵 是要補齊命令的內(nèi)容,目前鴻蒙支持如下命令:
arp cat cd chgrp chmod chown cp cpup date dhclient dmesg dns format free help hwi ifconfig ipdebug kill log ls lsfd memcheck mkdir mount netstat oom partinfo partition ping ping6 pwd reset rm rmdir sem statfs su swtmr sync systeminfo task telnet test tftp touch umount uname watch writeproc
例如:當(dāng)在控制臺按下?ch
和?tab
鍵后會輸出以下三個
chgrp chmod chown
內(nèi)容,這些功能對使用者而已看似再平常不過,但都需要內(nèi)核一一實現(xiàn).
shellBuf
存儲編輯結(jié)果,當(dāng)按下回車鍵時,將結(jié)果保存并交付給下一個階段使用.
鴻蒙全棧開發(fā)全新學(xué)習(xí)指南
也為了積極培養(yǎng)鴻蒙生態(tài)人才,讓大家都能學(xué)習(xí)到鴻蒙開發(fā)最新的技術(shù),針對一些在職人員、0基礎(chǔ)小白、應(yīng)屆生/計算機專業(yè)、鴻蒙愛好者等人群,整理了一套純血版鴻蒙(HarmonyOS Next)全棧開發(fā)技術(shù)的學(xué)習(xí)路線【包含了大廠APP實戰(zhàn)項目開發(fā)】。
本路線共分為四個階段:
第一階段:鴻蒙初中級開發(fā)必備技能
第二階段:鴻蒙南北雙向高工技能基礎(chǔ):gitee.com/MNxiaona/733GH
第三階段:應(yīng)用開發(fā)中高級就業(yè)技術(shù)
第四階段:全網(wǎng)首發(fā)-工業(yè)級南向設(shè)備開發(fā)就業(yè)技術(shù):gitee.com/MNxiaona/733GH
《鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊》(共計892頁)
如何快速入門?
1.基本概念
2.構(gòu)建第一個ArkTS應(yīng)用
3.……
開發(fā)基礎(chǔ)知識:gitee.com/MNxiaona/733GH
1.應(yīng)用基礎(chǔ)知識
2.配置文件
3.應(yīng)用數(shù)據(jù)管理
4.應(yīng)用安全管理
5.應(yīng)用隱私保護
6.三方應(yīng)用調(diào)用管控機制
7.資源分類與訪問
8.學(xué)習(xí)ArkTS語言
9.……
基于ArkTS 開發(fā)
1.Ability開發(fā)
2.UI開發(fā)
3.公共事件與通知
4.窗口管理
5.媒體
6.安全
7.網(wǎng)絡(luò)與鏈接
8.電話服務(wù)
9.數(shù)據(jù)管理
10.后臺任務(wù)(Background Task)管理
11.設(shè)備管理
12.設(shè)備使用信息統(tǒng)計
13.DFX
14.國際化開發(fā)
15.折疊屏系列
16.……
鴻蒙開發(fā)面試真題(含參考答案):gitee.com/MNxiaona/733GH
鴻蒙入門教學(xué)視頻:
美團APP實戰(zhàn)開發(fā)教學(xué):gitee.com/MNxiaona/733GH
寫在最后
- 如果你覺得這篇內(nèi)容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉(zhuǎn)發(fā),有你們的 『點贊和評論』,才是我創(chuàng)造的動力。
- 關(guān)注小編,同時可以期待后續(xù)文章ing🚀,不定期分享原創(chuàng)知識。
- 想要獲取更多完整鴻蒙最新學(xué)習(xí)資源,請移步前往小編:
gitee.com/MNxiaona/733GH