Linux Kernel 网络 之 Netlink

参考书籍

《精通Linux内核网络》  Rami Rosen著(罗伊森)

 Netlink 也是一种套接字,就是socket,跟TCP/UDP的socket是类似的,但是,不同的是,TCP/UDP层的socket是 BSD socket。Netlink是独立的一套协议族。

作用

这是该参考书中的说明,这段说明,真是扯淡,对于没有从事过内核网络开发的人来说,这简直是天书。

说白了,这也是一种通信协议,不同的是,一般所说的通信协议,指的是不同主机,包括网络设备之间的通信,可以是有线,也可以是无线。

但是,通信,不仅仅是发生在不同的网络设备之间,也可能发生在一个机器内部,比如进程与进程之间,这就是所谓的进程间通信,手段有信号,信号量,消息队列,共享内存,管道,unix域套接字等等,Unix环境高级编程卷三,就是专门说的这个进程间通信。除了进程与进程之间,内核与进程之间,也是需要通信的。前面也有过一些例子,copy_to_user,copy_from_user之类的,通过ioctl 或者 write/read 进行从内核到用户空间数据的传输,这个走的是文件系统(我猜的)。而Netlink就是一种用户空间与内核之间的通信机制,可以实现双向的通信,并且,Netlink还可以进行内核不同模块之间的通信。当然,不同的进程与内核通信,就能通过Netlink进行进程间通信,但是,不推荐这么干。

Netlink协议,优势在于,第一,不需要轮询。第二,内核可以主动往应用层发送异步消息,而不需要用户空间触发,也就是不需要用户空间去调用什么ioctl。第三,Netlink套接字支持组播。

其实除了以上的优点,我在想,是否还有其他的优点,以下说的未必准确:

第一,Netlink封装了一层,有效的去抽象出了一个功能模块,协助内核内部其他模块的通信,架构层面,更加清晰了,编码更容易了。

第二,Linux内核的网络编程里面,网络数据的流转,都是通过 skb 去流转的,其实都是 skb 的指针,而netlink 虽然抽象出了这样一层通信工具层,但是,数据流转依旧是以skb指针去流转,在内核内部,依旧遵循了 零拷贝 策略,保证了性能。

第三,没有那些过程中依赖的文件里,比如之前博客中的字符设备,/dev 下会创建一个设备文件,netlink就不会创建了。

创建方式

 对于用户空间,也就是进程代码中,就当成 socket 创建就可以。

family参数: AF_NETLINK , 与TCP/UDP的 AF_INET / AF_INET6 不同。

第二个参数:SOCK_RAW 或者 SOCK_DGRAM,当然这里面加了个 CLOEXEC 标志。这个fd的标志,不写,也是默认加的,所以可以不显式的去写。至于干嘛的,跟 dup,fork, vfork , 以及 exec 系列族有关。我们要关心的就是 fork的时候,fd会被dup的方式被继承到子进程,如果调用exec系列族函数,那么有这个标志,这个fd就不会被继承了,失效了,否则,这个fd依旧可以读写,前面有博客提到了fork 针对 fd的处理,dup或者fork继承了内核的同一张文件表项。

第三个参数:这是netlink众多协议族中的一种NETLINK_ROUTE。netlink是协议族,这是其中一个协议的规定,利用了netlink的框架,我们自己试验,可以自己定义一个协议,不跟其他的去混淆。

我们不按照这个书去走,这个书上说的,废话连篇,而且,看完之后,你也写不出一个实验来,很扯淡。

我们做个试验

场景:内核与进程通信

内核作为一个 server 端,也就说,不主动给进程空间发消息,而是被动的监听用户进程消息,收到了之后呢,回复一个消息给到用户层,然后就结束,类似回射模型,并且,用同步的方式去处理。

内核层内,我们用动态模块的方式去加载进内核。

用户空间,就写个linux的app即可。

内核代码

// server_netlink.c
#include <linux/init.h>
#include <linux/module.h>
#include <net/sock.h>
#include <net/netlink.h>
#include <linux/rwsem.h>
#include <linux/idr.h>
#include <linux/string.h>

#define NETLINK_TEST	30
#define USER_PORT		100

extern struct net init_net;

static struct sock	*s_netlink;
static DECLARE_RWSEM(hello_lock);

static int hello_send_msg_2_user(char *pbuf, uint16_t len)
{
    struct sk_buff *nl_skb;
    struct nlmsghdr *nlh;
 
    int ret = 0;
 
    /* 创建sk_buff 空间 */
    nl_skb = nlmsg_new(len, GFP_ATOMIC);
    if(!nl_skb)
    {
        printk("netlink alloc failure !\n");
        return -1;
    }
 
    /* 设置netlink消息头部 */
    nlh = nlmsg_put(nl_skb, 0, 0, NETLINK_TEST, len, 0);
    if(nlh == NULL)
    {
        printk("nlmsg_put failaure !\n");
        nlmsg_free(nl_skb);
        return -1;
    }
 
    /* 拷贝数据发送 */
    memcpy(nlmsg_data(nlh), pbuf, len);
    ret = netlink_unicast(s_netlink, nl_skb, USER_P
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值