现在的位置: 首页 > 综合 > 正文

Understanding.Linux.Network.Internals Chapter 3.User-Space-to-Kernel Interface

2013年08月16日 ⁄ 综合 ⁄ 共 2314字 ⁄ 字号 评论关闭
本章主要介绍用户空间程序与内核通信或读取内核信息的几种机制。
1)procfs(/proc )
procfs和sysctl都可以导出内核内部信息,但procfs用于导出只读数据,而sysctl导出的数据是可读写的。
大多数网络功能初始化时都会在/proc中注册一个或多个文件。当用户读取这个文件时,内核会调用一组内核函数来输出相应的数据。这组内核函数是在创建文件
时初始化的文件操作函数句柄定义的;
static struct file_operation xx_fops={    //函数句柄xx_fops
        .open = xx_open;      //也是初始化工作,注册一组函数指针,用与遍邻和定位返回给用户的数据
        .read = xx_read,       
        ....
};
static int__init xx_proc_init(void){
        if(!proc_net_fops_create("xx",s_irugo,&xx_fops)){..}    //创建文件,初始化的文件函数句柄
        ..
};
static struct seq_operations xx_op={   //xx_open
        .start = clip_seq_start,           
        .next = neigh_seq_next,
        ....
};
static in xx_open(struct inode *inode,struct file *file){       //定义xx_open()
         rc=seq_open(file,&xx_op)  
         ...
};
static ... xx_read (..){
    ....
};

2)sysctl(/proc/sys )
/proc/sys中看到的每个文件实际上都是一个内核变量,读取和设置内核变量都是通过ctl_table结构(/proc/sys中的每个目录和文件都是一个ctl_table结构,对于文件

的ctl_table存在proc_handler指定操作,而对于目录存在child指定子目录或该目录中的文件)中的proc_handler域指定的内核函数作具体操作的;
static ctl_table scsi_table[]={
        .ctl_name=dev_scsi_logging_level,
        .procname="logging_level",                  // /proc/sys/下的文件名
        .data=&scsi_logging_level,                      //相关联的内核变量
        .maxlen=sizeof(scsi_logging_level),        //内核变量大小
        .mode=0644,                                         //文件目录权限
        .proc_handler=&proc_dointvec  },         //内核调用的函数  proc_dointvec--读写一个整数数组,类似的函数很多在kernel/sysctl.c中
       {}
};
static ctl_table scsi_dir_table[]={
        .ctl_name=dev_scsi,
        .procname="scsi",
        .mode=0555,
        .child=scsi_table  ],     //目录关系
       {}
};
static ctl_table scsi_root_table[]= {
        .ctl_name=ctl_dev,
        .procname="dev",
        .mode=0555,
        .child=scsi_dir_table },
       {}
};
int __init scsi_init_sysctl(void){
        scsi_table_header=register_sysctl_table(scsi_root_table,1);   //注册/proc/sys/dev/scsi/logging_level文件
}

比如我们cat /proc/sys/dev/scsi/logging_level  实际上是对scsi_logging_level变量执行proc_dointvec函数,具体操作要看proc_dointvec的实现

3)sysfs(/sys )
比procfs和sysctl更新的文件系统
4)ioctl
ioctl接口实际上是通过打开一个socket,并根据这个socket初始化一个数据结构,然后把这个数据结构传递给ioctl,再经由sock_ioctl分派到正确的处理函数
以ifconfig eth0 mtu xxx为例
struct ifreq data;
fd=socket(PF_INET,SOCK_DGRAM,0);     //创建套接字描述符, pf_inet--tcp/ip, sock_dgram--数据报套接字类型
err=ioctl(fd,siocsifmtu,&data);
....
(未涉及sock_ioctl代码)

5)netlink socket
netlink socket直接使用标准的socket api打开、关闭、发送和接收信息
socket(pf_netlink,sock_dgram,...)
netlink socket支持多播信息

抱歉!评论已关闭.