您好,登錄后才能下訂單哦!
這篇“node.js怎么實現偽終端”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“node.js怎么實現偽終端”文章吧。
偽終端
偽終端不是真正的終端,而是內核提供的一個“服務”。終端服務通常包括三層:
最頂層提供給字符設備的輸入輸出接口中間層的線路規程(line discipline)底層的硬件驅動
其中,最頂層的接口往往通過系統調用函數實現,如(read,write);而底層的硬件驅動程序則負責偽終端的主從設備通信,它由內核提供;線路規程看起來則比較抽象,但是實際上從功能上說它負責輸入輸出信息的“加工”,如處理輸入過程中的中斷字符(ctrl + c)以及一些回退字符(backspace 和 delete)等,同時轉換輸出的換行符n為rn等。
一個偽終端分為兩部分:主設備和從設備,他們底層通過實現默認線路規程的雙向管道連接(硬件驅動)。偽終端主設備的任何輸入都會反映到從設備上,反之亦然。從設備的輸出信息也通過管道發送給主設備,這樣可以在偽終端的從設備中執行shell,完成終端的功能。
偽終端的從設備中,可以真實的模擬終端的tab補全和其他的shell特殊命令,因此在node原生模塊不能滿足需求的前提下,我們需要把目光放到底層,看看OS提供了什么功能。目前,glibc庫提供了posix_openpt接口,不過流程有些繁瑣:
使用posix_openpt打開一個偽終端主設備 grantpt設置從設備的權限 unlockpt解鎖對應的從設備獲取從設備名稱(類似 /dev/pts/123)主(從)設備讀寫,執行操作
因此出現了封裝更好的pty庫,僅僅通過一個forkpty函數便可以實現上述所有功能。通過編寫一個node的c++擴展模塊,搭配pty庫實現一個在偽終端從設備執行命令行的terminal。
關于偽終端安全性的問題,我們在文章的最后在進行討論。
偽終端實現思路
根據偽終端的主從設備的特性,我們在主設備所在的父進程中管理偽終端的生命周期及其資源,在從設備所在的子進程中執行shell,執行過程中的信息及結果通過雙向管道傳輸給主設備,由主設備所在的進程向外提供stdout。
在此處借鑒pty.js的實現思路:
pid_t pid = pty_forkpty(&master, name, NULL, &winp); switch (pid) { case -1: return Nan::ThrowError("forkpty(3) failed."); case 0: if (strlen(cwd)) chdir(cwd); if (uid != -1 && gid != -1) { if (setgid(gid) == -1) { perror("setgid(2) failed."); _exit(1); } if (setuid(uid) == -1) { perror("setuid(2) failed."); _exit(1); } } pty_execvpe(argv[0], argv, env); perror("execvp(3) failed."); _exit(1); default: if (pty_nonblock(master) == -1) { return Nan::ThrowError("Could not set master fd to nonblocking."); } Local<Object> obj = Nan::New<Object>(); Nan::Set(obj, Nan::New<String>("fd").ToLocalChecked(), Nan::New<Number>(master)); Nan::Set(obj, Nan::New<String>("pid").ToLocalChecked(), Nan::New<Number>(pid)); Nan::Set(obj, Nan::New<String>("pty").ToLocalChecked(), Nan::New<String>(name).ToLocalChecked()); pty_baton *baton = new pty_baton(); baton->exit_code = 0; baton->signal_code = 0; baton->cb.Reset(Local<Function>::Cast(info[8])); baton->pid = pid; baton->async.data = baton; uv_async_init(uv_default_loop(), &baton->async, pty_after_waitpid); uv_thread_create(&baton->tid, pty_waitpid, static_cast<void*>(baton)); return info.GetReturnValue().Set(obj); }
以上就是關于“node.js怎么實現偽終端”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。