目录
一、什么是 PPP 点对点设备
PPP,即 Point - to - Point Protocol,点对点协议,是一种数据链路层协议,用于在两个直接相连的网络节点之间建立、配置和测试数据链路连接,并传输数据。它就像是一条直接连接两个地方的高速公路,让数据能够在这两个点之间高效、稳定地传输 。
在网络通信的庞大体系中,PPP 点对点设备扮演着举足轻重的角色。以早期家庭拨号上网为例,用户的计算机通过调制解调器与互联网服务提供商(ISP)的接入服务器建立连接,这个连接的建立和数据传输就依赖于 PPP 协议。它使得普通家庭用户能够通过电话线这种物理介质,实现与互联网的对接,开启网络冲浪的大门。再看企业网络,在构建虚拟专用网络(VPN)时,PPP 协议与隧道协议(如 L2TP、PPTP)结合,在不安全的公共网络上建立起安全的加密连接,实现企业不同分支机构之间的数据安全传输 。
从更宏观的网络架构角度来讲,PPP 点对点设备为异构网络的连接提供了可能。不同类型的网络系统,它们所使用的网络层协议、物理介质等可能各不相同,但 PPP 协议能够支持多种网络层协议,如 IP、IPv6 和 OSI 网络层协议,同时允许在多种物理介质,像电话线、光纤、以太网、无线电频道等上进行通信,打破了网络之间的技术壁垒,让各种网络能够相互通信、协同工作,极大地推动了网络通信的发展,是现代网络通信中不可或缺的基础组成部分 。
二、PPP 在 Linux 内核中的实现原理
(一)PPP 驱动架构剖析
在 Linux 内核中,PPP 驱动程序的结构设计精巧且复杂,宛如一座精心构建的大厦,各个组件各司其职,又紧密协作 。
PPP 设备作为一种内核网络接口设备,主要负责在点对点的物理链路之间使用 PPP 帧进行分组交换。由于 Linux 内核将串行设备当作终端设备来驱动,于是引入了 PPP 终端规程,以此实现终端设备与 PPP 设备的接口。依据终端设备物理传输特性的不同,PPP 规程细分为异步规程(N_PPP)和同步规程(N_SYNC_PPP),像普通串口设备通常采用异步 PPP 规程 。
在 PPP 驱动程序里,每一个 tty 终端设备都对应着一条 PPP 传输通道(channel),而每一个 ppp 网络设备则对应着一个 PPP 接口单元(unit)。这就好比一条条高速公路的入口(tty 终端设备)连接着不同的车道(PPP 传输通道),最终汇聚到一个大型的交通枢纽(PPP 接口单元) 。从终端设备接收到的数据流,会先通过 PPP 传输通道解码,转换成 PPP 帧后传递到 PPP 网络接口单元,PPP 接口单元再将其转换为 PPP 设备的接收帧。反之,当 PPP 设备发射数据帧时,发射帧会先通过 PPP 接口单元转换成 PPP 帧,再传递给 PPP 通道,PPP 通道负责将 PPP 帧编码后写入终端设备 。在配置了多链路 PPP 时(CONFIG_PPP_MULTILINK),多个 PPP 传输通道可连接到同一 PPP 接口单元,此时,PPP 接口单元会将 PPP 帧分割成若干个片段传递给不同的 PPP 传输通道,反之,PPP 传输通道接收到的 PPP 帧片段会被 PPP 接口单元重组成完整的 PPP 帧,就像将一个大型货物拆分成多个小包裹运输,到达目的地后再重新组装 。
此外,在 Linux - 2.4 中,应用程序能够通过字符设备 /dev/ppp 监控内核 PPP 驱动程序。用户可以运用 ioctl (PPPIOCATTACH) 将文件绑定到 PPP 接口单元上,进而读写 PPP 接口单元的输出帧;也可以用 ioctl (PPPIOCATTCHAN) 将文件绑定到 PPP 传输通道上,来读写 PPP 传输通道的输入帧 。PPP 传输通道用 channel 结构描述,系统中所有打开的传输通道都在 all_channels 链表中;PPP 接口单元用 ppp 结构描述,系统中所有建立的接口单元都在 all_ppp_units 链表中 。当终端设备的物理链路连接成功后,用户使用 ioctl (TIOCSETD) 将终端切换到 PPP 规程,PPP 规程初始化时,会建立终端设备的传输通道和通道驱动结构。对于异步 PPP 规程来说,通道驱动结构为 asyncppp,它包含通道操作表 async_ops,传输通道和接口单元各自包含自已的设备文件 (/dev/ppp) 参数结构 (ppp_file) 。这些组件和结构相互配合,构成了 PPP 驱动架构的坚实基础,确保了 PPP 协议在 Linux 内核中的稳定运行 。
(二)数据传输流程详解
在 Linux 内核中,数据从应用层到 PPP 设备的传输过程是一个有序且复杂的旅程 。
当应用程序通过 socket 接口发送 TCP/IP 数据包时,这就好比一封邮件从发件人手中寄出 。首先,pppd 在 make_ppp_unit 函数中调用 ioctl (PPPIOCNEWUNIT) 创建一个网络接口(如 ppp0),内核中的 PPP 协议模块在处理 PPPIOCNEWUNIT 时,调用 re