目录

套接字Netlink地址 sockaddr_nl

协议簇

常使用的宏

内核常用的函数

创建流程

Netlink套接字

uevent内核事件

套接字监视接口

demo


Netlink套接字接口最初是Linux内核2.2引入的,作用用户空间进程与内核间通信方法。

相对于ioctl,sysfs,proc的优势

优势:

  • IOCTL处理程序不能从内核向用户空间发送异步消息,而Netlink套接字则可以。
  • 用户与内核间的通信方式,不需要轮询,用户空间应用程序打开套接字,调用recvmsg(),如果没有来自内核的消息,就进入阻塞状态。
  • 内核可以主动向用户空间发送异步消息,而不需要用户空间来触发。
  • 支持组播传输。

命令iproute2包含命令(ip tc ss lnstat bridge)主要使用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 */
};

消息头

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

协议簇

#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   /* Unused number, formerly ip_queue     */
#define NETLINK_SOCK_DIAG   4   /* 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 NETLINK_RDMA        20
#define NETLINK_CRYPTO      21  /* Crypto layer */
#define NETLINK_SMC     22  /* SMC monitoring */

常使用的宏

#define NLMSG_ALIGNTO    4U
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN     ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len)  ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \(nlh)->nlmsg_len <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))

内核常用的函数

//内核创建socket
static inline struct sock * netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)//nlmsg_new - Allocate a new netlink message
static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags)//Add a new netlink message to an skb
static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,int type, int payload, int flags)//单播
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);//多播
extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid,__u32 group, gfp_t allocation);

创建流程

Netlink套接字

在内核网络栈中,可以创建多种Netlink套接字,每种套接字处理不同类型消息。如NETLINK_ROUTE消息的套接字创建过程

static int __net_init rtnetlink_net_init(struct net *net)
{struct sock *sk;struct netlink_kernel_cfg cfg = {.groups      = RTNLGRP_MAX,.input       = rtnetlink_rcv,.cb_mutex  = &rtnl_mutex,.flags       = NL_CFG_F_NONROOT_RECV,.bind      = rtnetlink_bind,};sk = netlink_kernel_create(net, NETLINK_ROUTE, &cfg);if (!sk)return -ENOMEM;net->rtnl = sk;return 0;
}
  • 在netlink_kernel_create种第二个参数 NETLINK_ROUTE表示rtnetlink消息,此外还有NETLINK_XFRM表示IPsec子系统,NETLINK_AUDIT表示审计子系统。
  • 成员input函数用于指定回调函数,rtnetlink_rcv用于接收用户空间的信息。

uevent内核事件

只需要从内核向用户发送数据即可,初始化为

static int uevent_net_init(struct net *net)
{struct uevent_sock *ue_sk;struct netlink_kernel_cfg cfg = {.groups    = 1,.input = uevent_net_rcv,.flags    = NL_CFG_F_NONROOT_RECV};ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);if (!ue_sk)return -ENOMEM;ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);if (!ue_sk->sk) {pr_err("kobject_uevent: unable to create netlink socket!\n");kfree(ue_sk);return -ENODEV;}
...
}

套接字监视接口

//支持SS 监视接口 NETLINK_SOCK_DIAG
static int __net_init diag_net_init(struct net *net)
{struct netlink_kernel_cfg cfg = {.groups  = SKNLGRP_MAX,.input   = sock_diag_rcv,.bind  = sock_diag_bind,.flags    = NL_CFG_F_NONROOT_RECV,};net->diag_nlsk = netlink_kernel_create(net, NETLINK_SOCK_DIAG, &cfg);return net->diag_nlsk == NULL ? -ENOMEM : 0;
}

demo

内核程序实例

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <linux/netlink.h>#define NETLINK_USER  22
#define USER_MSG    (NETLINK_USER + 1)
#define USER_PORT   50static struct sock *netlinkfd = NULL;int send_msg(int8_t *pbuf, uint16_t len)
{struct sk_buff *nl_skb;struct nlmsghdr *nlh;int ret;//创建sk_buffernl_skb = nlmsg_new(len, GFP_ATOMIC);if(!nl_skb){printk("nlmsg_new error\n");return -1;}//设置netlink头nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);if(nlh == NULL){printk("netlink header error\n");nlmsg_free(nl_skb);return -1;}//拷贝数据memcpy(nlmsg_data(nlh), pbuf, len);//单播发送数据ret = netlink_unicast(netlinkfd, nl_skb, USER_PORT, MSG_DONTWAIT);return ret;
}//接收数据
static void recv_cb(struct sk_buff *skb)
{struct nlmsghdr *nlh = NULL;void *data = NULL;//打印接收数据的长度printk("recv_datalen:%u\n", skb->len);if(skb->len >= nlmsg_total_size(0)){nlh = nlmsg_hdr(skb);//宏 获取数据data = NLMSG_DATA(nlh);if(data){printk("kernel receive data: %s\n", (int8_t *)data);//将数据发送给用户send_msg(data, nlmsg_len(nlh));}}
} //cfg参数 注册了input
struct netlink_kernel_cfg cfg =
{.input = recv_cb,
};//初始化
static int __init netlink_init(void)
{//创建socketnetlinkfd = netlink_kernel_create(&init_net, USER_MSG, &cfg);if(!netlinkfd){printk(KERN_ERR "create a netlink socket error!\n");return -1;}printk("init netlink  ok!\n");return 0;
}
//退出
static void __exit netlink_exit(void)
{sock_release(netlinkfd->sk_socket);printk(KERN_DEBUG "netlink exit\n!");
}module_init(netlink_init);
module_exit(netlink_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("wy");
MODULE_DESCRIPTION("netlink");

linux 内核中Netlink相关推荐

  1. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  2. 简单谈一点linux内核中套接字的bind机制--数据结构以及端口确定

    众所周知,创建一个套接字可以bind到一个特定的ip地址和端口,实际上套接字这一概念代表了TCP/IP协议栈的应用层标识,协议栈中的应用层就是通过一个ip地址和一个端口号标识的,当然这仅仅是对于TCP ...

  3. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  4. 如何放出Linux内核中的链表大招

    前言 上回,我们说到Linux内核中max()宏的终极奥义,Linux内核链表也不甘示弱,那么接下来,让我们看看Linux内核中的链表大招. 如何放出Linux内核中的链表大招 前言 一.链表简介 ( ...

  5. Linux内核中max()宏的奥妙何在?(一)

    Linux内核中max()宏的奥妙何在?(一) 1.max()宏那点事 在Linux内核中,有这样四个比较大小的函数,如下: max(x,y) //两个数求最大值 min(x,y) //两个数求最小值 ...

  6. Linux内核中max()宏的奥妙何在?(二)——大神Linus对这个宏怎么看?

    最新max()宏 上回,我们在<Linux内核中max()宏的奥妙何在?(一)>一文中说到,在3.18.34版Linux内核源码中的max()宏,采用了GCC的扩展特性,可以避免一些错误. ...

  7. Linux中文件描述符1,linux内核中的文件描述符(一)--基础知识简介

    原标题:linux内核中的文件描述符(一)--基础知识简介 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blo ...

  8. Linux 内核中的 GCC 特性(zz)

    from:http://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux ...

  9. 【Linux 内核】进程管理 ( Linux 内核中的进程状态 | TASK_RUNNING | TASK_INTERRUPTIBLE | __TASK_STOPPED | EXIT_ZOMBIE )

    文章目录 一.Linux 内核中的进程状态 二.TASK_RUNNING 状态 三.TASK_RUNNING 状态 四.TASK_UNINTERRUPTIBLE 状态 五.__TASK_STOPPED ...

最新文章

  1. Matlab与线性代数 -- 矩阵的重组2
  2. 使用awk获得java进程号,获取进程号并赋值判断进程状态
  3. 触摸屏mtp文件转c语言,F28335与上位机(触摸屏)之间的通讯遵循modbus协议使用C语言编程...
  4. 服务提供者与服务消费者
  5. MyBatis基础知识概述
  6. 大咖齐聚!好好聊聊啥是AI大模型
  7. 使用CocoaPods被卡住:Updating local specs repositories
  8. 中国大学MOOC伦理学题库及答案
  9. 微商软文发布方法有哪些?文案怎么编辑?
  10. 跑分软件测试原理,只会比高低?教你三分钟看懂安兔兔跑分
  11. 那些年Android开发遇到的坑(JNI 之 Illegal start byte 0xfe)
  12. 攻防比赛中蓝队常用的攻击方法
  13. iphone android 传照片,教你如何在两台iPhone之间传照片
  14. html 列表页 后台添加分类 后台添加商品 商品详情页 注册页面 首页
  15. 程序员月薪3万?2020年12月程序员平均薪资14222元,招聘近40万人!
  16. 利用 Eclipse Visual Editor 项目构建 GUI 应用程序
  17. 海康威视监控云存储服务器,监控设备,云存储服务器,安防监控—年轻人安防官网...
  18. python N叉树
  19. 数据从哪儿来?一些实用的网址
  20. 宿迁学院计算机二级必须要过吗,宿迁学院四级没过能拿到学位证书吗

热门文章

  1. CTF论剑场web题目(持续更新)--WEB2
  2. Oracle instant clinet 连接数据库注意
  3. 机器学习流程错误分析
  4. 打开APP,判断是否是原生页面的方法(含flutter判断)
  5. 测试总结该怎么写才高级?
  6. AD域是什么意思?有什么用?
  7. 加拿大访问学者家属如何办理探亲签证?
  8. 2022考研肖秀荣《讲真题》pdf
  9. Navicat链接linux上的mysql出现 1577 Cannot proceed because system tables used by Event Scheduler where foun
  10. 类似损失函数符号L的字母怎么在mathtype打出来?