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命令打印的輸出。
:-: 
圖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了,是不是很神奇呢?
- 前言
- 第1章 準備工作
- 1.1 Android系統架構
- 1.2 工具使用
- 1.2.1 Source Insight的使用
- 1.2.2 Eclipse的使用
- 1.2.3 BusyBox的使用
- 1.3 本書資源下載說明
- 第2章 深入理解Netd
- 2.1 概述
- 2.2 Netd工作流程
- 2.2.1 main函數分析
- 2.2.2 NetlinkManager分析
- 2.2.3 CommandListener分析
- 2.2.4 DnsProxyListener分析
- 2.2.5 MDnsSdListener分析
- 2.3 CommandListener中的命令
- 2.3.1 iptables、tc和ip命令
- 2.3.2 CommandListener構造函數和測試工具ndc
- 2.3.3 InterfaceCmd命令
- 2.3.4 IpFwd和FirewallCmd命令
- 2.3.5 ListTtysCmd和PppdCmd命令
- 2.3.6 BandwidthControlCmd和IdletimerControlCmd命令
- 2.3.7 NatCmd命令
- 2.3.8 TetherCmd和SoftapCmd命令
- 2.3.9 ResolverCmd命令
- 2.4 NetworkManagementService介紹
- 2.4.1 create函數詳解
- 2.4.2 systemReady函數詳解
- 2.5 本章總結和參考資料說明
- 2.5.1 本章總結
- 2.5.2 參考資料說明
- 第3章 Wi-Fi基礎知識
- 3.1 概述
- 3.2 無線電頻譜和802.11協議的發展歷程
- 3.2.1 無線電頻譜知識
- 3.2.2 IEEE 802.11發展歷程
- 3.3 802.11無線網絡技術
- 3.3.1 OSI基本參考模型及相關基本概念
- 3.3.2 802.11知識點導讀
- 3.3.3 802.11組件
- 3.3.4 802.11 Service介紹
- 3.3.5 802.11 MAC服務和幀
- 3.3.6 802.11 MAC管理實體
- 3.3.7 無線網絡安全技術知識點
- 3.4 Linux Wi-Fi編程API介紹
- 3.4.1 Linux Wireless Extensions介紹
- 3.4.2 nl80211介紹
- 3.5 本章總結和參考資料說明
- 3.5.1 本章總結
- 3.5.2 參考資料說明
- 第4章 深入理解wpa_supplicant
- 4.1 概述
- 4.2 初識wpa_supplicant
- 4.2.1 wpa_supplicant架構
- 4.2.2 wpa_supplicant編譯配置
- 4.2.3 wpa_supplicant命令和控制API
- 4.2.4 git的使用
- 4.3 wpa_supplicant初始化流程
- 4.3.1 main函數分析
- 4.3.2 wpa_supplicant_init函數分析
- 4.3.3 wpa_supplicant_add_iface函數分析
- 4.3.4 wpa_supplicant_init_iface函數分析
- 4.4 EAP和EAPOL模塊
- 4.4.1 EAP模塊分析
- 4.4.2 EAPOL模塊分析
- 4.5 wpa_supplicant連接無線網絡分析
- 4.5.1 ADD_NETWORK命令處理
- 4.5.2 SET_NETWORK命令處理
- 4.5.3 ENABLE_NETWORK命令處理
- 4.6 本章總結和參考資料說明
- 4.6.1 本章總結
- 4.6.2 參考資料說明
- 第5章 深入理解WifiService
- 5.1 概述
- 5.2 WifiService的創建及初始化
- 5.2.1 HSM和AsyncChannel介紹
- 5.2.2 WifiService構造函數分析
- 5.2.3 WifiStateMachine介紹
- 5.3 加入無線網絡分析
- 5.3.1 Settings操作Wi-Fi分析
- 5.3.2 WifiService操作Wi-Fi分析
- 5.4 WifiWatchdogStateMachine介紹
- 5.5 Captive Portal Check介紹
- 5.6 本章總結和參考資料說明
- 5.6.1 本章總結
- 5.6.2 參考資料說明
- 第6章 深入理解Wi-Fi Simple Configuration
- 6.1 概述
- 6.2 WSC基礎知識
- 6.2.1 WSC應用場景
- 6.2.2 WSC核心組件及接口
- 6.3 Registration Protocol詳解
- 6.3.1 WSC IE和Attribute介紹
- 6.3.2 802.11管理幀WSC IE設置
- 6.3.3 EAP-WSC介紹
- 6.4 WSC代碼分析
- 6.4.1 Settings中的WSC處理
- 6.4.2 WifiStateMachine的處理
- 6.4.3 wpa_supplicant中的WSC處理
- 6.4.4 EAP-WSC處理流程分析
- 6.5 本章總結和參考資料說明
- 6.5.1 本章總結
- 6.5.2 參考資料說明
- 第7章 深入理解Wi-Fi P2P
- 7.1 概述
- 7.2 P2P基礎知識
- 7.2.1 P2P架構
- 7.2.2 P2P Discovery技術
- 7.2.3 P2P工作流程
- 7.3 WifiP2pSettings和WifiP2pService介紹
- 7.3.1 WifiP2pSettings工作流程
- 7.3.2 WifiP2pService工作流程
- 7.4 wpa_supplicant中的P2P
- 7.4.1 P2P模塊初始化
- 7.4.2 P2P Device Discovery流程分析
- 7.4.3 Provision Discovery流程分析
- 7.4.4 GO Negotiation流程分析
- 7.5 本章總結和參考資料說明
- 7.5.1 本章總結
- 7.5.2 參考資料說明
- 第8章 深入理解NFC
- 8.1 概述
- 8.2 NFC基礎知識
- 8.2.1 NFC概述
- 8.2.2 NFC R/W運行模式
- 8.2.3 NFC P2P運行模式
- 8.2.4 NFC CE運行模式
- 8.2.5 NCI原理
- 8.2.6 NFC相關規范
- 8.3 Android中的NFC
- 8.3.1 NFC應用示例
- 8.3.2 NFC系統模塊
- 8.4 NFC HAL層討論
- 8.5 本章總結和參考資料說明
- 8.5.1 本章總結
- 8.5.2 參考資料說明
- 第9章 深入理解GPS
- 9.1 概述
- 9.2 GPS基礎知識
- 9.2.1 衛星導航基本原理
- 9.2.2 GPS系統組成及原理
- 9.2.3 OMA-SUPL協議
- 9.3 Android中的位置管理
- 9.3.1 LocationManager架構
- 9.3.2 LocationManager應用示例
- 9.3.3 LocationManager系統模塊
- 9.4 本章總結和參考資料說明
- 9.4.1 本章總結
- 9.4.2 參考資料說明
- 附錄