目录

套接字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. 电磁学讲义6:高斯定理计算电场
  2. 常用[js,css,jquery,html]
  3. webstorm 修改端口号
  4. 如何进行网站的安全测试
  5. CTFshow php特性 web110
  6. 测试MVC3时关于Model Builder语句的更改
  7. Cocos2d-x 3.x plist+png 做动画
  8. optee中断处理的介绍(概念篇)
  9. ES6_Promise
  10. 计算机网络网际协议实验报告,计算机网络课程网际协议IP地址实验报告.doc
  11. c语言 rgb颜色渐变_这种渐变噪点的质感,咋做的?
  12. user_agent
  13. 非极大值抑制(PyTorch-YOLOv3代码解析一)
  14. win7 虚拟wifi服务器,在win7系统下创建虚拟wifi的方法
  15. pattern.compile java_Java Pattern compile(String)用法及代码示例
  16. rbenv安装Ruby2.3.5报错BUILD FAILED (Ubuntu 18.04 using ruby-build 20191225-1-gbac1f1c) openssl
  17. 三、Python复习教程(重点)- 前端框架实战
  18. 128 黙齎 李貴 曷若親征
  19. Unity Google VR Cardboard 后台挂起时陀螺仪仍然占用问题解决
  20. gabor滤波器 opencv 实现

热门文章

  1. 手掌静脉识别——利用深度学习进行ROI的选取
  2. MySQL查询优化:GROUP BY
  3. 图片合成gif怎么做?图片转gif,图片生成gif在线制作
  4. 游戏鼠标 测试软件,测试键盘鼠标辐射的专业工具_策略游戏(游戏软件)_键鼠导购-中关村在线...
  5. 图片处理中的Dithering技术
  6. 【波形库】对比和分析波形的在线平台
  7. Redis(2)短信验证码登录
  8. Unity2021+VS2022调试
  9. 官网Instagram集成
  10. ios 第三方键盘开发 无限刷屏浅析