Linux用户与内核空间交互—netlink
目录
简介
一、netlink soket
优点
二、用户空间
1、API
2、编程流程
3、源码
三、内核编程
1、API
2、内核空间编程流程
3、内核源码
简介
用户空间与内核的交互方式,使用copy_from_user(), copy_to_user().
除了这两种交互方式,内核还提供了其他高级的方式,对于写驱动来说很重要。有proc、sysfs、debugfs、netlink、ioctl。
本文学习netlink
一、netlink soket
优点
- 双向同步传输数据;
- 高速数据传输,特别是在本地主机上;
- 异步通信;消息可以排队,因此发送方不必等待接收方;
- 在其他用户到内核通信方法(如procfs、sysfs、debugfs和ioctl)中,用户空间程序必须开始传输到内核空间的;而使用netlink套接字,内核可以起始传输到用户空间;
- procfs、sysfs、debugfs中可能引起域名污染;对于netlink套接字,情况并非如此,因为没有文件。
二、用户空间
1、API
socket(PF_NETLINK, SOCK_RAW, NETLINK_MY_UNIT_PROTO)
2、编程流程
- 创建netlink;socket(PF_NETLINK, SOCK_RAW, NETLINK_MY_UNIT_PROTO);域名 PF_NETLINK,类型SOCK_RAW,协议 NETLINK_MY_UNIT_PROTO
- 初始化netlink源的sockerddr; bind socket
- 初始化netlink目的地址结构。目的地址设置成0表示是内核;
- 初始化netlink的头数据结构,指定源PID,数据负载;
- 初始化iovec结构,指向引用netlink头,初始化msghdr 数据结构,指向目的地址和iov
- 数据的发送sendmsg,数据的接收recvmsg
3、源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>#define NETLINK_MY_UNIT_PROTO 31#define NLSPACE 1024//数据
static const char *thedata = "hello world";int main(int argc, char **argv)
{int sd;struct sockaddr_nl src_nl, dest_nl;struct nlmsghdr *nlhdr; // 'carries' the payloadstruct iovec iov;struct msghdr msg;ssize_t nsent, nrecv;//、创建节点,域名PF_NETLINK,类型SOCK_RAW,协议NETLINK_MY_UNIT_PROTOsd = socket(PF_NETLINK, SOCK_RAW, NETLINK_MY_UNIT_PROTO);if (sd < 0) {exit(EXIT_FAILURE);}//2、设置netlink源地址结构体已经绑定memset(&src_nl, 0, sizeof(src_nl));src_nl.nl_family = AF_NETLINK;src_nl.nl_pid = getpid();src_nl.nl_groups = 0x0; // no multicastif (bind(sd, (struct sockaddr *)&src_nl, sizeof(src_nl)) < 0) {exit(EXIT_FAILURE);}/* 3. 设置目的地址结构体*/memset(&dest_nl, 0, sizeof(dest_nl));dest_nl.nl_family = AF_NETLINK;dest_nl.nl_groups = 0x0; // no multicastdest_nl.nl_pid = 0; // destined for the kernel/* 4. 分配netlink头内存*/nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(NLSPACE));if (!nlhdr) {exit(EXIT_FAILURE);}memset(nlhdr, 0, NLMSG_SPACE(NLSPACE));nlhdr->nlmsg_len = NLMSG_SPACE(NLSPACE);nlhdr->nlmsg_pid = getpid();/* 设置payload thedata是待发送的数据*/strncpy(NLMSG_DATA(nlhdr), thedata, strnlen(thedata, NLSPACE)+1);/* 5.设置iovec*/memset(&iov, 0, sizeof(struct iovec));iov.iov_base = (void *)nlhdr;//上面申请的空间iov.iov_len = nlhdr->nlmsg_len;/* 设置消息头结构体 */memset(&msg, 0, sizeof(struct msghdr));msg.msg_name = (void *)&dest_nl; // 目的地址msg.msg_namelen = sizeof(dest_nl); // 目的地址大学msg.msg_iov = &iov;//msg.msg_iovlen = 1; // # elements in msg_iov/* 6. sendmsg */nsent = sendmsg(sd, &msg, 0);if (nsent < 0) {free(nlhdr);exit(EXIT_FAILURE);} else if (nsent == 0) {free(nlhdr);exit(EXIT_FAILURE);}printf("%s:sendmsg(): *** success, sent %ld bytes all-inclusive\n"" (see kernel log for dtl)\n", argv[0], nsent);fflush(stdout);/* 7. 阻塞接收数据*/printf("%s: now blocking on kernel netlink msg via recvmsg() ...\n", argv[0]);nrecv = recvmsg(sd, &msg, 0);if (nrecv < 0) {free(nlhdr);exit(EXIT_FAILURE);}printf("%s:recvmsg(): *** success, received %ld bytes:""\nmsg from kernel netlink: \"%s\"\n",argv[0], nrecv, (char *)NLMSG_DATA(nlhdr));free(nlhdr);close(sd);exit(EXIT_SUCCESS);
}
三、内核编程
1、API
struct sock * netlink_kernel_create(struct net *, int , struct netlink_kernel_cfg *);
2、内核空间编程流程
- netlink_kernel_create 创建netlink
- nlmsg_new()分配netlink内存,nlmsg_put()添加netlink信息到分配的内存;借助nlmsg_data()
拷贝数据; - nlmsg_unicast()发送内核数据到用户空间;
- netlink_kernel_release() 释放netlink
3、内核源码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>MODULE_AUTHOR("wy");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION("0.1");//文件名
#define OURMODNAME "netlink_simple_intf"
#define NETLINK_MY_UNIT_PROTO 31
#define NLSPACE 1024static struct sock *nlsock;//收到数据,触发回调函数。
static void netlink_recv_and_reply(struct sk_buff *skb)
{struct nlmsghdr *nlh;struct sk_buff *skb_tx;//返回的数据char *reply = "Reply from kernel netlink";int pid, msgsz, stat;//发生在进程上下文,而不是中断上下文PRINT_CTX();nlh = (struct nlmsghdr *)skb->data;pid = nlh->nlmsg_pid; //发送进程的PIDpr_info("received from PID %d:\n" "\"%s\"\n", pid, (char *)NLMSG_DATA(nlh));//返回数据长度msgsz = strnlen(reply, NLSPACE);//新netlink申请skb_tx = nlmsg_new(msgsz, 0);if (!skb_tx) {pr_warn("skb alloc failed!\n");return;}// 设置 payloadnlh = nlmsg_put(skb_tx, 0, 0, NLMSG_DONE, msgsz, 0);NETLINK_CB(skb_tx).dst_group = 0; //将发送的数据reply,使用nlmsg_data拷贝到netlink strncpy(nlmsg_data(nlh), reply, msgsz);// 发送stat = nlmsg_unicast(nlsock, skb_tx, pid);if (stat < 0)pr_warn("nlmsg_unicast() failed (err=%d)\n", stat);pr_info("reply sent\n");
}//当用户空间向kernel发数据,将触发此回调函数
static struct netlink_kernel_cfg nl_kernel_cfg = {.input = netlink_recv_and_reply,
};static int __init netlink_simple_intf_init(void)
{//创建netlinknlsock = netlink_kernel_create(&init_net, NETLINK_MY_UNIT_PROTO,&nl_kernel_cfg);if (!nlsock) {pr_warn("netlink_kernel_create failed\n");return PTR_ERR(nlsock);}pr_info("inserted\n");return 0; /* success */
}//模块退出清理
static void __exit netlink_simple_intf_exit(void)
{netlink_kernel_release(nlsock);pr_info("removed\n");
}module_init(netlink_simple_intf_init);
module_exit(netlink_simple_intf_exit);
四、串口输出
kernel
[ 310.858620] netlink_simple_intf: loading out-of-tree module taints kernel.
[ 310.858650] netlink_simple_intf: module verification failed: signature and/or required key missing - tainting kernel
[ 310.860505] netlink_simple_intf:netlink_simple_intf_init(): creating kernel netlink socket
[ 310.860510] netlink_simple_intf:netlink_simple_intf_init(): inserted
[ 320.874385] netlink_simple_intf:netlink_recv_and_reply(): 005) netlink_userapp :3730 | ...0 /* netlink_recv_and_reply() */
[ 320.874391] netlink_simple_intf:netlink_recv_and_reply(): received from PID 3730:"sample user data to send to kernel via netlink"
[ 320.874394] netlink_simple_intf:netlink_recv_and_reply(): reply sent
app
./netlink_userapp:PID 3730: netlink socket created
./netlink_userapp: bind done
./netlink_userapp: destination struct, netlink hdr, payload setup
./netlink_userapp: initialized iov structure (nl header folded in)
./netlink_userapp: initialized msghdr structure (iov folded in)
./netlink_userapp:sendmsg(): *** success, sent 1040 bytes all-inclusive(see kernel log for dtl)
./netlink_userapp: now blocking on kernel netlink msg via recvmsg() ...
./netlink_userapp:recvmsg(): *** success, received 44 bytes:
msg from kernel netlink: "Reply from kernel netlink"
Linux用户与内核空间交互—netlink相关推荐
- Linux用户与内核空间交互—sysfs
目录 简介 一.sysfs 1./sys 目录 2.API 3.platform API 4.创建platform总线设备文件 二.程序源码 简介 用户空间与内核的交互方式,使用copy_from_ ...
- 用户空间和内核空间通讯Netlink
用户空间和内核空间通讯Netlink http://pan.baidu.com/s/1i386MWX
- 跟踪 linux 内核调用_Linux用户和内核空间中的动态跟踪
跟踪 linux 内核调用 您是否曾经遇到过这样的情况,即您意识到没有在代码中的某些点插入调试打印 ,所以现在您将不知道您的CPU是否命中了特定的代码行来执行,直到您重新编译该代码为止.调试语句? 不 ...
- linux 用户态 内核态 通信,procfs(从0开始,内核态和用户态通信charpter2)
这篇博文将针对linux内核态与用户态通信方式中的procfs进行详细的学习. /proc主要存放内核的一些控制信息,所以这些信息大部分的逻辑位置位于内核控制的内存,在/proc下使用ls -l你会发 ...
- linux内核dma内存分配,Linux 4.x 内核空间 DMA 虚拟内存地址
Architecture: i386 32bit Machine Ubuntu 16.04 Linux version: 4.15.0-39-generic 目录 DMA 虚拟内存区 在 IA32 体 ...
- Linux 用户进程内存空间详解
经常使用top命令了解进程信息,其中包括内存方面的信息.命令top帮助文档是这么解释各个字段的. VIRT , Virtual Image (kb) RES, Resident size (kb) S ...
- linux内存非线性映射到文件,Linux 4.x 内核空间 FIXUP 固定映射和临时映射虚拟内存...
Architecture: i386 32bit Machine Ubuntu 16.04 Linux version: 4.15.0-39-generic 目录 FIXUP 虚拟内存区 在 IA32 ...
- netlink实现与使用方法详解(用户态/内核态)
一.什么是netlink Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口. 在Linux 内核中,使用netlink ...
- 用户空间和内核空间通讯之【proc文件系统】
今天我们介绍另一种用户内核空间通信的方法:proc文件系统. proc文件系统作为linux提供的一种虚拟文件系统并不占用实际外围存储空间,它仅存在于内存中,系统断电即消失.proc文件系统最开始的设 ...
最新文章
- Android短视频中如何实现720P磨皮美颜录制?
- mnist手写数字识别_手写数字识别
- android 4.4 下拉菜单 透明,4.2状态栏,下拉,全局透明教程
- 这篇被引用近4k次的论文教你如何正确的理解和使用相关系数!
- python中的switch语句_python技巧 switch case语句
- 高中辅导班为何改名成培训机构了?
- 加密解密技术基础、PKI及创建私有CA
- Maven实战(六)依赖
- 【Git教程】入门安装客户端与服务器
- linux 解析elf文件格式,Linux下ELF文件解析
- matplotlib色彩(colors)之图表数据系列默认配色(默认色彩循环)
- 2020年毕业生腾讯校园招聘提前批——后台开发——面试经验——分享给大家交流经验。
- python三国演义人物出现次数_Python分析《三国演义》人物出场次数,孔明第二,赵云第五...
- va_list原理及用法
- vue实现图片预加载的几种方式
- 计算机考研用python_2014北邮计算机考研复试上机题解(上午+下午)
- 快手发布《2021磁力引擎营销通案》,以信任基因赋能全域营销
- netty报错:远程主机强迫关闭了一个现有的连接。(已解决)
- python编写函数showmsg(n、name)_python学习-函数
- c代码实现 ifft运算_二维FFT,IFFT,c语言实现 | 学步园
热门文章
- 巧妙使用金山快盘实现qq聊天记录“网络漫游”
- php代码生成器软件_php代码生成器好用吗
- [Recap] ApacheCon North America 2019 完美谢幕
- 应届生看过来 别以为没交社保就稳妥了
- Android Loader LoaderManager 总结(一)
- linux下隐藏windows硬盘,windows下隐藏磁盘分区
- 鸡兔同笼 需求:今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
- 李飞飞北京演讲:AI会改变世界,改变AI的又会是谁?
- SpringCloud集成发送短信--容联云通讯--Redis
- 简单聊下STM32F103的串口