Linux 24 内核和用户通信之netlink

本文详细介绍了Linux中用户空间和内核空间通过Netlink进行双向通信的方法,包括Netlink的通信地址和协议、用户态接口的创建、销毁socket、发送和接收Netlink消息的步骤,以及内核空间使用的Netlink API。Netlink通信涉及nl_pid、nl_groups、nlmsg_type和nlmsg_flags等关键概念,同时提供了创建Netlink Socket、发送和接收消息的示例。
摘要由CSDN通过智能技术生成
Netlink的通信地址和协议

一般来说用户空间和内核空间的通信方式有三种:/proc、ioctl、Netlink。而前两种都是单向的,而Netlink可以实现双工通信。
所有socket之间的通信,必须有个地址结构,Netlink也不例外。我们最熟悉的就是IPV4的地址了,netlink的地址结构如下:

struct sockaddr_nl  
{  
    sa_family_t nl_family;          //必须为AF_NETLINK或者PF_NETLINK  
    unsigned short  nl_pad;             //必须为0  
    __u32       nl_pid;             //通信端口  
__u32       nl_groups;              //组播掩码  
};  

本质上,nl_pid就是netlink的通信地址(双方约定好)。除了通信地址,netlink还提供“协议”来标示通信实体,在创建socket的时候,需要指定netlink的通信协议号。每个协议号代表一种“应用”,上层可以用内核已经定义的协议和内核进行通信,获得内核已经提供的信息。具体支持的协议列表如下:

#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  
struct msghdr {
    void         *msg_name;       /* optional address */
    socklen_t     msg_namelen;    /* size of address */
    struct iovec *msg_iov;        /* scatter/gather array */
    size_t        msg_iovlen;     /* # elements in msg_iov */
    void         *msg_control;    /* ancillary data, see below */
    size_t        msg_controllen; /* ancillary data buffer len */
    int           msg_flags;      /* flags (unused) */
};

struct sockaddr_nl
{
    sa_family_t nl_family; /*该字段总是为AF_NETLINK */
    unsigned short nl_pad; /* 目前未用到,填充为0*/
    __u32 nl_pid; /* process pid */
    __u32 nl_groups; /* multicast groups mask */
};

struct nlmsghdr
{
    __u32 nlmsg_len; /* Length of message including header */
    __u16 nlmsg_type; /* Message content */
    __u16 nlmsg_flags; /* Additional flags */
    __u32 nlmsg_seq; /* Sequence number */
    __u32 nlmsg_pid; /* Sending process PID */
};

协议号一般作为测试可以直接使用NETLINK_GENERIC
通信端口一般原则如下:
生成式1:选择应用程序的pid作为nl_pid的值。nl_pid = getpid();
生成式2:这种方式下,同一进程内的不同线程都可以为同一Netlink 协议类型申请自己特有的socket。实际上,即使在一个线程内,创建多个基于相同协议类型的Netlink Socket也是可能的。然而,开发者需要在如何生成唯一nl_pid上更具创造性。nl_pid = pthread_self() << 16 | getpid();

netlink采用协议号+通信端口的方式构建自己的地址体系。

nlmsg_type:消息状态,内核在include/uapi/linux/netlink.h中定义了以下4种通用的消息类型,它们分别是

#define NLMSG_NOOP      0x1 /* Nothing.     */
#define NLMSG_ERROR     0x2 /* Error        */
#define NLMSG_DONE      0x3 /* End of a dump    */
#define NLMSG_OVERRUN       0x4 /* Data lost        */
#define NLMSG_MIN_TYPE      0x10    /* < 0x10: reserved control messages */

nlmsg_flags:消息标记,它们用以表示消息的类型,如下

/* Flags values */
#define NLM_F_REQUEST       1   /* It is request message.   */
#define NLM_F_MULTI     2   /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK       4   /* Reply with ack, with zero or error code */
#define NLM_F_ECHO      8   /* Echo this request        */
#define NLM_F_DUMP_INTR     16  /* Dump was inconsistent due to sequence change */

/* Modifiers to GET request */
#define NLM_F_ROOT  0x100   /* specify tree root    */
#define NLM_F_MATCH 0x200   /* return all matching  */
#define 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值