用户空间和内核的接口

内核和用户空间的信息交互主要有如下接口:

1. procfs(/proc文件系统)

    这是一个虚拟文件系统,挂载在/proc目录下。允许内核以文件的形式向用户空间输出内部信息,这些文件并不实际存在于磁盘上,但可以通过cat或more以及‘>’shell重定向字符予以写入。

2. sysctl(/proc/sys目录)

    此接口允许用户读取或修改内核变量的值。从用户空间可以用两种方式访问sysctl输出的变量,一是sysctl系统调用,另一种是procfs。

3. sysfs

    以非常干净而有组织的方式输出很多信息,主要解决了procfs与sysctl滥用的问题而出现的。

4.ioctl系统调用
    ioctl系统调用操作的对象是一个文件,通常用于实现特殊设备需要而标准文件系统没有提供的操作(ifconfig、route)。
5.Netlink套接字
    这是网络应用程序和内核通信时最新的首选机制。多数的网络内核功能都可以用Netlink或ioctl接口进行配置。

Procfs与sysctl

procfs和sysctl都输出内核内部信息,但procfs主要是输出只读数据,而大多数sysctl信息是可写入的。与一个简单的内核变量或数据结构相关联的一些文件,可以用sysctl输出。其他涉及更为复杂的数据结构而需要特殊格式时,就以procfs输出,如缓存和统计数据。

Procfs

大多数网络功能会在引导时或在模块加载时其初始化期间在/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创建文档,然后初始化器文件操作处理函数。

sysctl

用户在/proc/sys下看到的一个文件,实际都是一个内核变量。对于每个变量,内核可以定义:

  • 将其放在/proc/sys的何处。与相同内核组件或功能相关联的变量通常都位于同一个目录中,如/proc/sys/net/ipv4目录中都是与ipv4相关的文件)。
  • 命名。多数时候文件名只是简单的命名为与相关联的内核变量相同的名字。
  • 访问权限。如一个文件可以由任何人读,但只能由超级用户修改。

有些目录和文件在引导期间静态定义,而其他则是在允许期间添加的。导致运行期间创建目录或文件的情况如下:

  • 当一个内核模块实现一项新功能或一个协议被加载或卸载时;
  • 当一个新的网络设备被注册或注销时。都有可能创建目录或文件。
/proc/sys中的文件和目录都是以ctl_table结构定义的。ctl_table结构的注册和注销是通过调用kernel/sysctl.c中定义的register_sysctl_table和unregister_sysctl_table函数完成。下图所示的每个目录以及这些目录的每个文件都有一个ctl_table实体:

ioctl
   在Linux系统中,ifconfig命令就是使用ioctl与内核通信。下图显示了ioctl调用对命令的分派路由过程:
用户空间和内核的接口_第1张图片

socket操作的ioctl命令命令有一定的规范,如新增一条路由的命令SIOCADDRT中SIOC表示Socket Ioctl,ADD表示添加,RT表示添加路由。当一个对象类型还可以被读写时,命令中还会增加G表示获取,S表示设置。如SIOCGIFADDR和SIOCSIFADDR分别表示为指定的网络接口新增或删除一条IP地址。

网络使用的ioctl命令都定义在include/linux/sockios.h文件中。设备驱动程序可以定义自己的私有命令,其范围介于SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间,但使用自己的私有命令是不被推荐的。因为各种协议都可以在这个范围定义自己的私有命令。

Netlink

Netlink套接字代表用户空间与内核的IP网络配置之间的首选接口,Netlink也可作为内核内部以及多个用户空间进程之间的消息传输系统。利用Netlink套接字,可以使用标准套接字API打开或关闭套接字、使用套接字传输数据或者接收套接字数据:

    int socket(int domain, int type, int protocol)

同其他套接字一样,在打开一个Netlink套接字时,必须提供domain、type、以及protocol参数。Netlink使用新的PF_NETLINK协议簇,只支持SOCK_DGRAM类型、并且定义了几种协议,每一种都用于网络协议栈的不同组件。如NETLINK_ROUTE协议用于大多数网络功能,如路由和邻居协议。NETLINK_FIREWALL用于防火墙。Netlink的协议定义在include/linux/netlink.h文件中:

#define NETLINK_ROUTE        0    /* Routing/device hook                */ 
#define NETLINK_UNUSED        1    /* Unused number                */ 
#define NETLINK_USERSOCK    2    /* Reserved for user mode socket protocols     */ 
#define NETLINK_FIREWALL    3    /* Firewalling hook                */ 
#define NETLINK_INET_DIAG    4    /* INET socket monitoring            */ 
#define NETLINK_NFLOG        5    /* netfilter/iptables ULOG */ 
#define NETLINK_XFRM        6    /* ipsec */ 
#define NETLINK_SELINUX        7    /* SELinux event notifications */ 
#define NETLINK_ISCSI        8    /* Open-iSCSI */ 
#define NETLINK_AUDIT        9    /* auditing */ 
#define NETLINK_FIB_LOOKUP    10    
#define NETLINK_CONNECTOR    11 
#define NETLINK_NETFILTER    12    /* netfilter subsystem */ 
#define NETLINK_IP6_FW        13 
#define NETLINK_DNRTMSG        14    /* DECnet routing messages */ 
#define NETLINK_KOBJECT_UEVENT    15    /* Kernel messages to userspace */ 
#define NETLINK_GENERIC        16 
/* leave room for NETLINK_DM (DM Events) */ 
#define NETLINK_SCSITRANSPORT    18    /* SCSI Transports */ 
#define NETLINK_ECRYPTFS    19

#define MAX_LINKS 32       

使用Netlink套接字时,端点是打开此套接字的进程的ID标识,而特殊值0表示是内核。Netlink的功能之一是传送单播和多播消息。目的端的端点地址可以是一个PID、一个多播群组ID或两者的组合。内核定义Netlink多播群组的目的是传出特定种类事件爱你的通知信息,而若用户程序对这类信息感兴趣,可以向这些群组注册。这些群组列在include/linux/rtnetlink.h文件中的RTMGRP_XXX

/* RTnetlink multicast groups - backwards compatibility for userspace */ 
#define RTMGRP_LINK        1 
#define RTMGRP_NOTIFY        2 
#define RTMGRP_NEIGH        4 //用于通知L3到L2的地址映射的改变 
#define RTMGRP_TC        8

#define RTMGRP_IPV4_IFADDR    0x10 
#define RTMGRP_IPV4_MROUTE    0x20 
#define RTMGRP_IPV4_ROUTE    0x40 //用于通知有关路由表的改变 
#define RTMGRP_IPV4_RULE    0x80

#define RTMGRP_IPV6_IFADDR    0x100 
#define RTMGRP_IPV6_MROUTE    0x200 
#define RTMGRP_IPV6_ROUTE    0x400 
#define RTMGRP_IPV6_IFINFO    0x800

#define RTMGRP_DECnet_IFADDR    0x1000 
#define RTMGRP_DECnet_ROUTE     0x4000

#define RTMGRP_IPV6_PREFIX    0x20000

Netlink相对于ioctl接口的优点之一是内核可以启动传输,而不仅限于响应用户空间请求而返回信息。

在Linux网络子系统中,每次应用配置改变时,内核中负责处理此事的例程都会取得一个信号量rtnl_sem,以确保对存储网络配置内容的数据结构的访问具有互斥性,无论该配置的改变是通过ioctl还是netlink,都是如此。












你可能感兴趣的:(linux系统相关)