内核通过各种不同的接口把内部信息输出到用户空间,除了程序员用于请求特定信息的经典系统调用外,还有三个特殊接口,而其中两个是虚拟文件系统:
procfs 文件系统
这是一个虚拟文件系统,通过是挂在proc ,允许内核以文件的形式向用户空间输出内部信息,这些文件并没有实际存在于磁盘中,但是可以通过cat或more以及 shell重定向符予以写入。这些文件甚至可以像真实文件一样指定其访问权限。因此,创建这些文件的内核组建可以说明任何一个文件可由谁读取或者写入。目录则不能被写入。多数linux发行套件的默认内核都支持procfs.procfs不能编译成为一个模块。配置菜单中相关的内核选项为Filesysrtem=>pseudo filesystem=?proc file system support
sysctl
此接口允许用户空间读取或修改变量的值。不能用此接口对每个内核变量进行操作;内核应明确指出那些变量从此接口是可见的。从用户空间,你可以用两种方式访问sysctl输出的变量。一种是sysctl系统调用,而另一种是procfs。当内核支持procfs时,会在/proc中添加一个特殊目录/proc/sys为每个由sysctl所输出的内核变量引入一个文件。
procps 包随附的sysctl命令可用于配置由sysctl接口所输出的变量。此命令通过写入/proc/sys与内核对话。多数linux发行套件默认内核都支持sysctl。sysctl不能编译成为一个模块。配置菜单中相关的内核选项为General setup-> Sysctl support。
sysfs
procfs和sysctl已经被滥用了多年,这就导致引入了一种的文件系统:sysfs。sysfs 以非常干净而有组织的方式输出很多信息,如你所期望的,当前由sysctl所输出的部分信息可以移植到sysfs。 内核对sysfs的支持只是在2.6版本才开始。多数linux发行套件默认内核都支持sysfs。sysfs不能编译成为一个模块。配置菜单中相关的内核选项为Gernal setup _. configure standard kernel features 选项,才能看得到上述选项。
在O Reilly最新的《linux设备驱动程序》书中可以找到对应sysfs 的详尽分析。在第十七章中,我们将看到桥接代码如何使用sysfs。
你也可以使用下列接口吧命令传给内核,配置某事或者倾卸某事的配置内容。
ioctl 系统调用操作的对象是一个文件,通常是用于实现特殊设备所需但是标准文件系统没有提供的操作,你可以把socket系统调用返回的套接字描述符传给ioctl。而这也是忘了代码使用ioctl的方式,此接口也是由老一代命令所用,如ifconfig和route等。
netlink套接字
这是网络应用程序与内核通信时最新的首选机制,IPROUTE2包中大多数命令都使用此接口,对linux而言, netlink 代表的就是BSD世界中的路由套接字,多数网络内核功能都可以用Netlink或者ioctl接口进行配置,因为内核支持比较新的配置工具,以及老式工具。
profs与sysctl
procfs和sysfs 都输出内核内部信息,但是prcfs 主要是输出只读数据,而大多数sysctl 信息都是可写入的,但是只有超级用户能写入。
就输出只读数据而言,procfs和sysctl之间的选择依赖于有多少信息应该输出,与一个简单的内核变量或者数据结构相关的一些文件,可以用sysctl输出,其他涉及更为复杂的数据结构而且需要特殊格式时,就可以procfs输出,例如缓存和统计数据。
profs
大多数网络功能在其初始化时都会在/proc中注册一个或者多个文件,不是在引导时就是在模块加载时,当一位用户读取该文件时,会引起内核间接运行一组内核函数,以返回某种输出内容,网络代码所注册的文件位于/proc/net。
/proc 中的目录可以使用Proc_mkdir创建,/proc/net中的文件可以使用定义在Include/linux/proc_fs.h 中的proc_net_fops_create和proc_net_remove 予以注册和除名。
这两个函数都是包裹函数,其中含有通用的API,create_proc_entry和remove_proc_entry, 特别是,proc_net_fops_create负责创建文档 用proc-net_create, 然后初始化其文件操作处理函数。我们来看一个实例。
以下是ARP协议如何在/proc/net中注册其arp文件。
static struct file_operations arq_seq_fops =
{
.owner = THIS_MODULE,
.open = arq_seq_open,
.read = seq_read,
.llseek = seq_lseek
.release = seq_release_private
}
static int __init arq_proc_init(void)
{
if (!proc_net_fops_create("arp", S_IRUGO, &arq_seq_fops))
return 0;
}
由proc_net_fops_craete 的三个输入参数可知,文件名为arq,权限必须指定为只读,
而且该组文件操作处理例程是arq_seq_ops, 当一个用户读取文件时,使用file_operations 数据结构,允许procfs返回相当多的数据给用户,当数据由一群相同类型的对象组成时会很有用,例如,ARQ缓存在返回时一次只返回一项,而路由表在返回时一次只返回跳路径。
open所初始化的例程会做另一次重要的初始化;注册一个函数指针数组,包括procfs用于便利要传回给用户数据的所有例程;一个例程启动倾卸,另一个推进到一个项目,而另一个再倾卸以一个项目。这些例程内部负责保存必要的环境信息,这些信息会就是倾泄点以及从正确位置重新继续倾斜所必需的。
static struct seq_operations arq_seq_ops = {
start = clip_seq_start
next = neigh_seq_next
stop = neight_seq_stop
show = clip_seq_show
};
static int arq_seq_open(struct inode *inode, struct file *file)
{
rc = seq_open(file, &arq_seq_ops);
}