图3-2显示了在/proc/sys中由网络代码所使用的主要目录,就每个目录而言,都列出了在哪一章描述其文件。
proc/sys/net
bridge ipv4 core
route neigh conf
图3-2/proc/sys/net 中的核心目录
根据前借所述,我们来看net中的树根是如何定义的,以及在引导期间如何注册。
对于如图3-2所示的每个目录以及这些目录的每个文件而言,都有一个ctl_table 实体。图3-3显示了图3-2所示的大多数目录的ctl_table实体在何处定义以及其父子关系是什么,为了
使图具有更高的可读性,并没有包括所有的目录。
图3-3中的三个方块显示了ctl_table初始化的三个实例,注意;
netdev_max_bcklog文件被分派了一个proc_handler例程。因为netdev_max_backlog是一个整数,来自于用户的输入由proc_dointvec读取。
min_delay 文件被分派了proc_handler和strategy两个例程。因为内核变量ip_rt_min_delay 以jiffies表示,但是用户的输入和输出都是以秒来表示的,因此这两个例程可以完成把秒转换为jiffies。
ip_local_port_range 文件是一个有趣的实例,这个文件允许用户配置一个范围,定义两个值。这恶搞范围必须遵循一个最小值和一个最大值的规范,因此,所选的strategy和proc_handler例程必须能够管理一个蒸熟值的数组,这些值表示这个范围,并且用于确保用户输入的值遵循此范围。
ioctl
在图3-4顶端,可以看到ioctl调用时如何发布的,来看一个包括ifconfig的示例。
稍早我们就说过,ifconfig命令使用ioctl与内核通信,例如,当系统管理输入像ifconfig eth0 mtu1250这样的命令,用以改变接口eth0的MTU时,ifconfig会打开一个套接字,用从管理员那里接受的信息,初始化一个本地数据结构,然后以ioctl 调用传给内核,SIOCSIFMTU是命令标识符。
struct ifreq data;
fd = socket(PF_INET, SOCK_DGRAM, 0);
err = ioctl(fd, SIOCSIFMTU, &data);
内核会在几个不同的地方处理ioctl命令,图3-4显示了网络代码最常用的ioctl命令如何由sock_ioctl分派,并且路由到正确的函数处理例程。我们将不说明sock_ioctl是如何调用的,或者像UDP和TCP这些传输协议是如何注册其处理例程的。如果你想深入挖掘这部分代码,可以使用此图作为起点,有关本书所谈及的例程,图3-4提供了正确的章节的指引。
kernel/sysctl.c --root_table
.proname="net"
.child = net_table
net/sysctl_net.c
net_table
.proname = "core"
.child = core_table
proname = ipv4
.child = ipv4_table
net/core/sysctl_net_core.c
core_table
net/ipv4/sysctl_net.c
.proname = netdev_max_backlog
.data = &netdev_max_backlog
.maxlen = sizeof(int)
.mode = 0644
.pro_handler = &proc_dointvec
net/ipv4/route.c
ipv4_route_table
.proname = min_delay
.data = &ip_rt_min_delay
.maxlen = sizeof(int)
.mode = 0644
.provc_handler = &proc_dointvec_jiffies
.strategy = &sysctl_jiffies
图3-3 在/proc/sys/net中创建的核心目录
为了方便起见,图中ioctl命令的名称已经做了分解,例如,用于把一条路径新增至路由表的命令SIOCADDRT被显示成SIOC ADDR RT以强调两个感兴趣的组建,ADD 表示要添加什么RT表示添加一条路由,多数命令都遵循此语法,通常,当一个对象类型可以读写时,命令名称中会多一个组件,G是指取得,而S是指设置,SIOCGIFADDR和SIOCSIFADDR这两个命令可以为接口新增或者删除IP地址。就是实际的例子,先前ifconfig范例中所见的SIOCSIFMTU是设定S接口IF的最大传输单位MTU,这件事由dev_ioctl所做,但是并没有出现在图3-4中。
网络ioctl命令列在include/linux.sockio.h中,设备驱动程序可以用代码定义新的命令,其范围介于SIOCDEVPRIVATE和SIOCDEVPRIVATE 之间,例如,可以看一看隧道设备使用的四个私有命令在include/linux/if_tunnel.h中是如何定义的,然而,使用私有的ioctl命令是被反对和不鼓励的。