<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ListTTysCmd和PppdCmd比較簡單,但也涉及兩個重要的背景知識。 **1.背景知識介紹** 本節介紹的兩個背景知識點是TTY和ptmx編程,以及PPP和pppd。 (1)TTY和ptmx編程[19][20] TTY是Linux系統(更確切地說是UNIX)中終端設備的統稱,該詞源于TeleTYpewriter(電傳打字機),是一個通過串行線用打印機鍵盤通過閱讀和發送信息的設備。不過隨著計算機技術的發展,這類設備早就被鍵盤和顯示器替代了。 從現在的情況來看,Linux系統中的TTY設備包含許多類型的設備,它們大體可分為以下 三種。 - 串行端口終端:這類設備一般命名為/dev/ttySn,n為索引號,例如ttyS0、ttyS1等。它們類似于Windows系統的COM0、COM1等,代表串行端口。當某個應用往ttyS0寫入數據時,另一個應用就能從ttyS0讀到對應的數據。 - 偽終端(psuedo terminal):這類設備成對出現,其中一個是master設備,另一個是slave設備。二者的關系類似管道(Pipe),當一個程序往slave設備寫數據時,另外一個打開master設備的程序就能讀到數據。以前(UNIX 98 scheme之前)主從設備命名方式為/dev/ptyp0和/dev/ttyp0。現在master設備命名為/dev/ptmx,而slave設備則對應/dev/pts/目錄下的文件名。 - 控制臺終端:這類設備命名從/dev/ttyN(N從1~64)和/dev/console。/dev/tty0代表當前使用的終端,而/dev/console一般指向這個終端。例如初始化時登錄系統用的是/dev/tty2,那么/dev/tty0指向/dev/tty2,如果切換到/dev/tty1,則/dev/tty0就指向/dev/tty1了。 通過adb shell登錄手機時,其實使用的都是偽終端。圖2-20所示為筆者用adb shell登錄Galaxy Note 2后用tty命令打印的輸出。 :-: ![](https://box.kancloud.cn/162054ac93f093bb0a37a815361503e8_549x161.jpg) 圖2-20 tty命令 對程序員來說,Linux提供了針對偽終端的編程接口。偽終端在概念上和管道沒有太大區別,但是在實際操作時有一些特殊API需要調用。 ~~~ 主從兩端要包含頭文件:一般是在兩個有親緣關系的父子進程中使用 #include<stdlib.h> 主端需要打開/dev/ptmx設備,得到一個文件描述符 從端在使用這個文件描述符前,需要調用grantpt以獲取權限,然后調用unlockpt解鎖 從端通過ptsname獲得從端設備文件名 從端打開由ptsname得到的從端設備 ~~~ Netd中的logwrap將使用偽終端在父子進程中傳遞log信息。代碼如下所示。 **logwrap.c** ~~~ int logwrap(int argc, const char* argv[]) { pid_t pid; int parent_ptty; int child_ptty; char child_devname[64]; // 父進程打開/dev/ptmx parent_ptty = open("/dev/ptmx", O_RDWR); ...... // 父進程解鎖/dev/ptmx。ptsname_r將得到從端設備的名字,例如/dev/pts/1 if (grantpt(parent_ptty) || unlockpt(parent_ptty) || ptsname_r(parent_ptty, child_devname, sizeof(child_devname))) { // ptsname_r是ptsname的可重入(Reentrant,可用于多線程環境)版本 ......// 錯誤處理 } pid = fork(); if (pid < 0) { ......// 錯誤處理 } else if (pid == 0) { // 子進程打開從端設備 child_ptty = open(child_devname, O_RDWR); // 關閉從父進程那繼承到的主設備文件 close(parent_ptty); dup2(child_ptty, 1);// 重定向標準輸入、輸出、錯誤輸出到偽終端的從設備 dup2(child_ptty, 2); close(child_ptty); child(argc, argv); // 執行child函數 } else { int rc = parent(argv[0], parent_ptty); // 父進程執行parent函數 close(parent_ptty); return rc; } return 0; } ~~~ 為什么Netd要使用這種一般很少用的ptmx偽終端呢?結合代碼中的注釋,筆者認為原因有以下兩個。 - 后文會介紹,Netd將fork很多子進程以執行各種任務,而這些進程的代碼一般都直接來自于已有的開源代碼。它們沒有采用Android的ALOG宏來記錄日志。所以,采用這種I/O重定向方法,這些進程的輸出將全部傳遞到Netd進程中來。而Netd進程是可以使用ALOG宏來打印輸出的。上述代碼中的parent函數將一直讀取/dev/ptmx的內容,然后通過ALOG宏輸出。 - 使用偽終端來承擔父子進程通信重任(還可以使用別的進程間通信手段例如socketpair、pipe等)的另一個原因是偽終端不會緩存數據。例如一旦子進程往從設備中寫入數據(借助I/O重定向,當子進程往標準輸出中寫數據時,其實是往從設備中寫數據),父進程就能讀到它們。 (2)PPP和pppd[21][22][23][24] PPP(Point-to-Point Protocol,點對點協議)是為在同等單元之間傳輸數據包這樣的簡單鏈路設計的鏈路層協議。這種鏈路提供全雙工操作,并按照順序傳遞數據包。設計目的主要是通過撥號或專線方式建立點對點連接發送數據,使其成為各種主機、網橋和路由器之間簡單連接的一種共通的解決方案。 PPP提供了一整套方案來解決鏈路建立、維護、拆除、上層協議協商、認證等問題,它主要包含以下幾個部分。 - 鏈路控制協議(Link Control Protocol,LCP):負責創建、維護或終止一次物理連接。 - 網絡控制協議(Network Control Protocol,NCP):包含一簇協議,負責解決物理連接上運行什么網絡協議,以及解決上層網絡協議發生的問題。 - 認證協議:最常用的包括口令驗證協議(Password Authentication Protocol,PAP)和挑戰握手驗證協議(Challenge-Handshake Authentication Protocol,CHAP)。使用時,客戶端會將自己的身份發送給遠端的接入服務器。期間將使用認證協議避免第三方竊取數據或冒充遠程客戶接管與客戶端的連接。 pppd(PPP Daemon的縮寫)是運行PPP協議的后臺進程。它和Kernel中的PPP驅動聯動,以完成在直連線路(DSL、撥號網絡)上建立IP通信鏈路的工作。讀者可簡單認為有了pppd,就可以在直連線路上傳輸IP數據包(類似以前我國大部分家庭用Modem和電話線上網)。 **2.ListTTysCmd和PppdCmd命令分析** 這兩個命令非常簡單,ListTtysCmd用于枚舉系統中所有的tty設備,這是通過列舉/sys/class/tty目錄中以tty開頭的文件名來完成的。 PppdCmd僅有attach和detach兩個選項。其中,attach用于啟動pppd進程,而detach用于殺死pppd進程。代碼在PppController的attachPppd和detachPppd函數中,請讀者自行閱讀。 PppController啟動pppd時傳遞的啟動參數如下所示。 ~~~ pppd-detach \#啟動后轉成后臺進程 devname\ #使用devname這個設備上鏈接到另一端的設備 115200\ #波特率設置為115200 iplocal:ipremote\ #設置本地和遠端IP ms-dns d1 \#為運行在windows的程序配置dns地址,第一個是主dns的地址 ms-dnsd2 \#第二個是從dns的地址 lcp-max-configure 99999 #這里設置LCP config request最大個數為99999 ~~~ 配置并啟動pppd后,手機就相當于一個Modem了,是不是很神奇呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看