内核通信之Netlink源码分析-基础架构

发布时间:2017-7-9 7:15:03编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"内核通信之Netlink源码分析-基础架构 ",主要涉及到内核通信之Netlink源码分析-基础架构 方面的内容,对于内核通信之Netlink源码分析-基础架构 感兴趣的同学可以参考一下。

2017-07-04


netlink是一种基于网络的通信机制,一般用于内核内部或者内核与用户层之间的通信。其有一个明显的特点就是异步性,通信的双方不要求同时在线,也就不用阻塞等待。NetLink按照数据包的格式发送/接收消息,提供双向通信,和其他内核与用户层通信机制相比,NetLink有其特有的优势:

  • 任何一方不需要轮训,如果通过文件传递状态信息,则需要不断的检查是否有新消息到达。
  • 系统调用和ioctl均可以从用户层向内核传递消息,但比简单的Netlink链接难于实现,另外,NetLink是系统提供的机制,不会和任何模块其冲突,兼容性好。
  • 使用NetLink可以让内核主动的向用户层发消息,此时内核扮演的就是一个逻辑用户;而ioctl和系统调用、/proc均只能由用户层发起请求,让内核去被动响应。
  • Netlink不仅支持单播,也支持多播即向多个进程发送消息。

 从逻辑上来讲,NetLink应该处于传输层,因此其同样需要特定的协议。对于NetLink就是Netlink协议,内核中有netlink_family_ops,在用户层创建netlink类型的socket的时候最终会调用到netlink_family_ops注册的create函数

static const struct net_proto_family netlink_family_ops = {    .family = PF_NETLINK,    .create = netlink_create,    .owner    = THIS_MODULE,    /* for consistency 8) */};

 每种协议都需要一组协议处理函数,针对Netlink有netlink_ops

static const struct proto_ops netlink_ops = {    .family =    PF_NETLINK,    .owner =    THIS_MODULE,    .release =    netlink_release,    .bind =        netlink_bind,    .connect =    netlink_connect,    .socketpair =    sock_no_socketpair,    .accept =    sock_no_accept,    .getname =    netlink_getname,    .poll =        netlink_poll,    .ioctl =    sock_no_ioctl,    .listen =    sock_no_listen,    .shutdown =    sock_no_shutdown,    .setsockopt =    netlink_setsockopt,    .getsockopt =    netlink_getsockopt,    .sendmsg =    netlink_sendmsg,    .recvmsg =    netlink_recvmsg,    .mmap =        netlink_mmap,    .sendpage =    sock_no_sendpage,};

 我们重点关注netlink_sendmsg和netlink_recvmsg,这是netlink发送和接收数据的处理函数。

地址表示

NetLink的地址表示由sockaddr_nl负责

struct sockaddr_nl {    __kernel_sa_family_t    nl_family;    /* AF_NETLINK    */    unsigned short    nl_pad;        /* zero        */    __u32        nl_pid;        /* port ID    */    __u32        nl_groups;    /* multicast groups mask */};

nl_family制定了协议族,这里肯定是AF_NETLINK,nl_pid用以该套接字,对于内核套接字来讲,nl_pid为0,而对于用户层程序而言,该值可以为任何值,协商好并保证唯一性即可。一般取为进程id或线程ID。nl_groups用以多播,当不需要多播时,该字段为0。

NetLink消息

NetLink消息是作为套接字缓冲区sk_buff的数据部分传递的,其消息本身又分为头部和数据。头部为

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 port ID */};

nlmsg_len为消息的长度,包含该头部在内。nlmsg_pid为发送进程的端口ID,这个用户可以自定义。其余的字段暂时用不到。在用户层还用到了一个结构

struct msghdr {    void    *    msg_name;    /* Socket name            */    int        msg_namelen;    /* Length of name        */    struct iovec *    msg_iov;    /* Data blocks            */    __kernel_size_t    msg_iovlen;    /* Number of blocks        */    void     *    msg_control;    /* Per protocol magic (eg BSD file descriptor passing) */    __kernel_size_t    msg_controllen;    /* Length of cmsg list */    unsigned int    msg_flags;};

msg_name是目标socket的地址结构sockaddr_nl的地址,msg_namelen是长度。msg_iov指向一个iov向量,msg_iovlen是向量的个数。剩下的暂不考察。当用户层向内核发送消息时,该结构作为参数传递。nlmsghdr 只能描述单个消息,而msghdr描述一组消息。通过iov向量聚合所有的消息,每个消息都有其对应的nlmsghdr.逻辑结构如下:

之前提到,socket也是一种特殊的文件,通过VFS的借口同样可以对其实现管理。scoket本身就需要实现文件系统的香影接口,有自己的文件系统操作。

内核中的表示

netlink socket在内核中涉及到的结构有下:socket,sock,netlink_sock,前者是套接字通用结构,sock是套接字在网络层的体现,而sock其实是内嵌在netlink_sock结构中,后者

以马内利

参考资料:

《linux3.10.1源码》


上一篇:“等一下,我碰!”——常见的2D碰撞检测
下一篇:Java实现二分法排序

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款