分类: LINUX
2012-11-16 22:42:24
ioctl
在Linux系统中,ifconfig命令就是使用ioctl与内核通信。下图显示了ioctl调用对命令的分派路由过程:
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,都是如此。