`
tcspecial
  • 浏览: 910383 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

netlink套接字

阅读更多

Linux下如何实现用户态与内核态的交互呢?一种是上文讲的/proc文件,还有一种是netlink套接字机制,netlink实现了用户空间与内核空间双向通信方法。

netlink用户态API与常见的socket编程一致,只是内核态要实现自定义protocol。

 

一.内核态模块

    该模块用于接收用户态信息,并发送一字符串响应。

#ifndef __KERNEL__
#define __KERNEL__
#endif  /* __KERNEL__ */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/uaccess.h>
#include <net/sock.h>
#include <net/netlink.h>  // netlink 
#include <linux/string.h>
#include <linux/ip.h>

#define NETLINK_TEST 31    // 自定义用户协议 

static struct sock *nlfd = NULL;  // 内核socket文件描述符
static char *payload = "Hello user,i'm from kernel!";

// 向用户层发送消息
static int sendNLMsg(int pid,void *msg,int len)
{
	struct sk_buff *skb;
	int size,count;
	struct nlmsghdr *nlmsgh = NULL;
	char *pos = NULL;
	int retval = 0;

	size = NLMSG_SPACE(len);               // 加消息头部长度
	skb = alloc_skb(size,GFP_KERNEL);	// 申请空间
	if(!skb)
	{
		retval = -1;
		return retval;
	}

	nlmsgh = nlmsg_put(skb,0,0,0,len,0);

	// 填充数据
	pos = NLMSG_DATA(nlmsgh);
	memset(pos,0,len);
	memcpy(pos,msg,len);

	NETLINK_CB(skb).dst_group = 0;  // 单播

	count = netlink_unicast(nlfd,skb,pid,MSG_DONTWAIT); 
	printk(KERN_ALERT "pid:%d send:%d\n",pid,count);

	return retval;
}


// 处理用户层传递的消息
static void handle_msg(struct sk_buff *_sk)
{
	struct sk_buff *skb;
	struct nlmsghdr *nlh = NULL;
	char str[100] = {};
	int pid;

 	printk("==>handle_msg\n");
 	
 	skb = skb_get(_sk);   // 引用当前_sk

 	if(skb->len >= NLMSG_SPACE(0))
 	{
 		nlh = nlmsg_hdr(skb);  	      // 获得信息头部
 		pid = nlh->nlmsg_pid;         // 获取用户进程pid

 		memcpy(str,NLMSG_DATA(nlh),100);
 		printk(KERN_ERR "recv:%s\n",str);

 		sendNLMsg(pid,payload,strlen(payload));  // 向用户层发送数据

 		kfree_skb(skb);
 	}

 	printk("<==handle_msg\n");
}

// 建立netlink套接字
int NLCreate(void)
{
        // 消息回调函数为handle_msg,注:参数1区别以往内核版本API,设为init_net
 	nlfd = netlink_kernel_create(&init_net,NETLINK_TEST,1,handle_msg,NULL,THIS_MODULE);
	if(!nlfd)
	{
		return -1;
	}

	return 0;
}

// 清除netlink套接字
int NLDestroy(void)
{
	if(nlfd)
	{
		sock_release(nlfd->sk_socket);
	}

	return 0;
}


static int __init netlink_init(void)
{
	NLCreate();

	return 0;
}


static void __exit netlink_exit(void)
{
	NLDestroy();
}

module_init(netlink_init);
module_exit(netlink_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("kettas");
MODULE_DESCRIPTION("Netlink Test Demo");
MODULE_VERSION("1.0.1");
MODULE_ALIAS("Netlink 01");

 

 

二.用户态

该应用向内核模块发送信息,并接收来自内核响应字符串。

        

#include <unistd.h>
#include <stdio.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/netlink.h>
#include <assert.h>
#include <stdlib.h>


#define NETLINK_TEST 31
#define MAX_NL_MSG_LEN 1024

typedef struct _packet_u
{
	struct nlmsghdr hdr;
	char payload[1024];
}packet_u;


static int nls;  // socket文件描述符

// 向内核发送消息
int sendtokernel(char *buf,int len,int type)
{
	struct nlmsghdr nlmsg;
	struct sockaddr_nl nldest = {};
	int size;

	nldest.nl_family	= AF_NETLINK;
	nldest.nl_pid		= 0;
	nldest.nl_groups	= 0;

	// 填充netlink消息头
	nlmsg.nlmsg_len = NLMSG_LENGTH(len);
	nlmsg.nlmsg_pid = getpid();
	nlmsg.nlmsg_flags = 0;
	nlmsg.nlmsg_type  = type;

	// 填充负载
	memcpy(NLMSG_DATA(&nlmsg),buf,len);

	// 发送
	size = sendto(nls,&nlmsg,nlmsg.nlmsg_len,0,(struct sockaddr*)&nldest,sizeof(nldest));
	return size;
}


// 接收内核消息
int recvfromkernel(void)
{
	int size = 0;

        // 方法一:调用recvfrom方法接收内核数据,注此时message结构体包含有消息体
        /*
	packet_u message;
	struct sockaddr_nl nldest = {};
	int len = sizeof(nldest);
	
	memset(&message,0,sizeof(message));

	nldest.nl_family	= AF_NETLINK;
	nldest.nl_pid		= 0;
	nldest.nl_groups	= 0;
	
	// 接收消息
	size = recvfrom(nls, 
			&message, 
			sizeof(message), 
			0, 
			(struct sockaddr*)&nldest, 
			&len);	
	printf("size:%d recv:%s\n",size,message.payload);   // NLMSG_DATA()与message.payload结果一致				
        */
	// 方法二:调用recvmsg方法
	struct sockaddr_nl nladdr;
	struct msghdr msg;
	struct iovec iov;
	struct nlmsghdr *nlhdr;

	nlhdr = (struct nlmsghdr *)malloc(MAX_NL_MSG_LEN);
	iov.iov_base = (void *)nlhdr;
	iov.iov_len = MAX_NL_MSG_LEN;
	msg.msg_name = (void *)&(nladdr);
	msg.msg_namelen = sizeof(nladdr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	size = recvmsg(nls, &msg, 0);
	printf("size:%d recv:%s\n",size,(char*)NLMSG_DATA(nlhdr));

	return size;
}

int main(int argc,char **argv)
{
	struct sockaddr_nl nlsource;
	int ret;

	// socket
	nls = socket(PF_NETLINK,SOCK_RAW,NETLINK_TEST);
	assert(nls!=-1);

	memset(&nlsource,0,sizeof(struct sockaddr_nl));
	nlsource.nl_family = AF_NETLINK;
	nlsource.nl_pid	   = getpid();
	nlsource.nl_groups = 0;

	// bind
	ret = bind(nls,(struct sockaddr*)&nlsource,sizeof(nlsource));
	assert(ret!=-1);

	// send
	char *str = "Hello kernel,i'm from user";
	sendtokernel(str,strlen(str),0);

	// recv
	recvfromkernel();

	close(nls);
	return 0;
}

 

三.测试运行

 

[scada@linux netlink]$ sudo insmod netlink_test.ko
[scada@linux netlink]$ ./netlink_u 
size:44 recv:Hello user,i'm from kernel!
[scada@linux netlink]$ dmesg
==>handle_msg
recv:Hello kernel,i'm from user
pid:40122 send:44
<==handle_msg
  

 

分享到:
评论

相关推荐

    Netlink套接字在Linux系统通信中的应用研究.pdf

    Netlink套接字在Linux系统通信中的应用研究 Netlink套接字是一种基于Socket编程接口的通信机制,在Linux系统中发挥着至关重要的作用。作为一种相对新的进程间通信机制,Netlink套接字具有其自身的优势。本文将详细...

    netlink:软件包netlink提供对Linux netlink套接字的低级访问。 麻省理工学院许可

    网络链接 软件包netlink提供了对Linux netlink套接字的低级访问。 麻省理工学院许可。 有关netlink的工作方式的更多信息,请查看我关于博客系列。 如有任何疑问或需要指导,请在#networking频道中加入 !稳定性有关...

    netlink实现usb热插拔

    2. **创建netlink套接字**:使用`socket()`和`bind()`系统调用来创建和绑定一个netlink套接字,指定netlink家族(如NETLINK_KOBJECT_UEVENT)和相关的组ID。 3. **接收内核事件**:使用`recvmsg()`或`poll()`等方法...

    Linux 用户态与内核态的交互――netlink 篇

    在Linux 2.4及后续版本中,Netlink套接字成为了用户态和内核态交互的重要机制,尤其在处理中断过程与用户进程间的通信时表现突出。例如,iproute2这样的网络管理工具以及Netfilter包过滤框架都广泛使用了Netlink进行...

    Linux内核中netlink协议族的实现

    Netlink套接字结构定义了用于通信的基本单元,其结构如下: ```c struct netlink_sock { struct sock sk; // 必须放在第一位 u32 pid; // 自己的PID u32 dst_pid; // 对方的PID u32 dst_group; // 对方的组 u...

    netlink socket programming

    这个配置接口和协议被称为Netlink套接字,它旨在为设置网络控制平面的所有方面创建一个通信框架。 尽管Netlink系统的构建尚未完成,但很明显它是新的网络配置方法,并且其基础设施已经相当稳定并可运行。本文档旨在...

    linux内核态与用户态通信-netlink实例解析

    用户态程序创建Netlink套接字,连接到NETLINK_NETFILTER(网络过滤器)协议,然后发送包含网络配置信息的Netlink消息,内核接收到消息后处理配置,并可能通过Netlink回应确认或错误信息。 六、源码分析 阅读...

    基于netlink机制内核空间与用户空间通信的分析_董昱1

    Netlink套接字在Linux 2.4及以上版本的内核中被广泛使用,尤其是在中断处理和用户进程之间的通信场景。 在netlink通信中,内核首先创建netlink套接字,然后通过广播消息函数向用户空间发送信息。用户空间则通过创建...

    Linux防御系统数据收集方法的研究.pdf

    综上所述,这篇研究探讨了Linux防御系统中数据收集的策略和技术,包括日志处理、网络数据流的捕获以及利用Netlink套接字和libipq库实现用户空间与内核空间的有效通信,以增强系统的监控和防御能力。这些技术对于构建...

    Linux中与内核通信Netlink机制.docx

    一旦定义了新的协议类型,内核中就可以通过`netlink_kernel_create()`创建对应的Netlink套接字,并指定特定的输入处理函数来处理相应的消息。 在内核中,`struct sock`对象代表了Netlink套接字的内核表示,它包含了...

    qdevicewatcher-master.zip

    本文将深入探讨一个名为“qdevicewatcher”的开源项目,它基于Qt框架,利用netlink套接字在多种操作系统环境下实现实时监控USB块设备的热插拔功能。 首先,让我们了解Qt框架。Qt是一个跨平台的C++图形用户界面应用...

    利用netlink内核态与用户态交互信息的范例

    1. **套接字创建**:首先,使用socket函数创建一个Netlink套接字,指定NETLINK_GENERIC协议家族,这是Netlink通用协议,可以用于多种目的。 2. **消息构建**:然后,定义一个Netlink消息结构体,包括必要的头部信息...

    linux下netflink通信实例(内核2.6.25)

    2. 打开套接字:使用`socket()`函数创建一个Netlink套接字,指定`AF_NETLINK`作为地址族,以及如`NETLINK_ROUTE`或`NETLINK_KOBJECT_UEVENT`等特定的Netlink协议。 3. 绑定套接字:使用`bind()`函数将套接字绑定到...

    netlink实现分析.docx

    用户进程通过socket系统调用创建一个Netlink套接字,然后使用bind和connect等函数指定接收端口和连接目标,从而实现消息的接收。 3.3 内核Netlink接收端接收消息 内核接收到Netlink消息后,会调用预先注册的处理...

    netlink内核态和用户态编程

    在内核态中,我们通常会使用`netlink_kernel_create()`函数创建一个Netlink套接字,并指定一个接收消息的回调函数,如这里的`kernel_receive()`。这个回调函数会在有新消息到达时被调用,处理接收到的数据。 在给出...

    netlinkTest.tar.gz

    1. **创建Netlink套接字**:使用`socket()`函数创建一个Netlink套接字,指定AF_NETLINK域,以及相应的Netlink家族,如NETLINK_KOBJECT_UEVENT,这是用于传递内核对象事件的Netlink家族。 2. **绑定和连接**:通过`...

    netlink查询数据时的避坑总结

    在Netlink查询IP路由时,首先需要创建一个Netlink套接字(socket)。这个套接字通常是`PF_NETLINK`协议家族的原始类型(SOCK_RAW),并且关联到`NETLINK_ROUTE`,这样就可以与内核的路由子系统进行交互。然后,发送...

    Linux中与内核通信Netlink机制.pdf

    Netlink的核心函数`netlink_kernel_create()`用于在内核中创建一个Netlink套接字。这个函数接受几个关键参数,包括`struct net *net`,通常为`init_net`全局变量,表示网络命名空间,每个命名空间可以拥有自己的网络...

    基于S3C4510B的嵌入式路由器的研究.pdf

    综合来看,文章提出的基于S3C4510B的嵌入式路由器设计方案,充分利用了ARM处理器的性能优势和uClinux操作系统的灵活性,通过Netlink套接字实现了高效的路由功能和协议转换,为构建高性能、低成本的嵌入式网络设备...

Global site tag (gtag.js) - Google Analytics