Netlink是套接字家族中的一员,主要用内核与用户空间的进程间、用户进程间的通讯。然而它并不像网络套接字可以用于主机间通讯,Netlink只能用于同一主机上进程通讯,并通过PID来标识它们。
Netlink被设计为在Linux内核与用户空间进程传送各种网络信息。网络工具iproute2利用 Netlink从用户空间与内核进行通讯。Netlink由一个在用户空间的标准的Socket接口和内核模块 提供的内核API组成。Netlink的设计比ioctl更加灵活,Netlink使用了AF_NETLINK Socket 家族。
RFC 3549详细的描述了Netlink协议。
netlink的实际应用很多,包括大家熟知的udev也是用的netlink方式。所以学习下netlink很有必要。
资料名称: netlink socket 编程之 why & how
内容简介: 此文章是翻译国外的一个权威文章,维基百科上首推。优点是介绍详细全面,缺点是
文章比较老,此原创文章在2005年写的,但作为netlink的入门学习非常好。
文章链接:
资料名称: Linux-3.2.0.24中内核的Netlink测试使用
内容简介: 此文章讲的是3.2的内核,由于不同的内核版本netlink的api创建方式是不同的,但原理相同。
如果用这个版本内核的童鞋可以参考下。
文章链接:http://blog.csdn.net/wangpengqi/article/details/9969599
资料名称: netlink 学习笔记 3.8.13内核
内容简介: 此文章讲的是3.8的内核,这个内核还是比较新的,我看了下这个文章的对应的api和我笔记本
上的3.10.10的api基本相同,所以想看新的netlink的api可以参考这个,缺点是这个文章没有
完整的参考代码,如果有空我会补上的。
文章链接:http://www.cnblogs.com/D3Hunter/p/3207670.html
资料名称: 监听网卡的链路通断
内容简介: netlink的一个实际应用,监听网卡的up&down事件。通过这个可以同理写个地址变化监听的程序。
文章链接:http://blog.chinaunix.net/uid-317451-id-92692.html
内核3.10.10示例:
用户态:app.c
-
#include <unistd.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <sys/socket.h>
-
#include <sys/types.h>
-
#include <string.h>
-
#include <asm/types.h>
-
#include <linux/netlink.h>
-
#include <linux/socket.h>
-
#include <errno.h>
-
-
#define NETLINK_TEST 25
-
#define MAX_PAYLOAD 1024 // maximum payload size
-
-
int main(int argc, char* argv[])
-
{
-
int state;
-
struct sockaddr_nl src_addr, dest_addr;
-
struct nlmsghdr *nlh = NULL;
-
struct iovec iov;
-
struct msghdr msg;
-
int sock_fd, retval;
-
int state_smg = 0;
-
// Create a socket
-
-
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
-
if(sock_fd == -1){
-
printf("error getting socket: %s", strerror(errno));
-
return -1;
-
}
-
-
// To prepare binding
-
-
memset(&msg,0,sizeof(msg));
-
memset(&src_addr, 0, sizeof(src_addr));
-
src_addr.nl_family = AF_NETLINK;
-
src_addr.nl_pid = getpid(); // self pid
-
-
src_addr.nl_groups = 0; // multi cast
-
-
-
retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
-
if(retval < 0){
-
printf("bind failed: %s", strerror(errno));
-
close(sock_fd);
-
return -1;
-
}
-
-
// To prepare recvmsg
-
-
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
-
if(!nlh){
-
printf("malloc nlmsghdr error!\n");
-
close(sock_fd);
-
return -1;
-
}
-
-
memset(&dest_addr,0,sizeof(dest_addr));
-
dest_addr.nl_family = AF_NETLINK;
-
dest_addr.nl_pid = 0;
-
dest_addr.nl_groups = 0;
-
-
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
-
nlh->nlmsg_pid = getpid();
-
nlh->nlmsg_flags = 0;
-
strcpy(NLMSG_DATA(nlh),"Hello you!");
-
-
iov.iov_base = (void *)nlh;
-
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
-
// iov.iov_len = nlh->nlmsg_len;
-
-
memset(&msg, 0, sizeof(msg));
-
-
msg.msg_name = (void *)&dest_addr;
-
msg.msg_namelen = sizeof(dest_addr);
-
msg.msg_iov = &iov;
-
msg.msg_iovlen = 1;
-
-
printf("state_smg\n");
-
state_smg = sendmsg(sock_fd,&msg,0);
-
-
if(state_smg == -1){
-
printf("get error sendmsg = %s\n",strerror(errno));
-
}
-
-
memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
-
printf("waiting received!\n");
-
// Read message from kernel
-
state = recvmsg(sock_fd, &msg, 0);
-
if(state<0){
-
printf("state<1");
-
}
-
printf("Received message: %s\n",(char *) NLMSG_DATA(nlh));
-
close(sock_fd);
-
-
return 0;
-
}
内核态: netlink.c
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/timer.h>
-
#include <linux/time.h>
-
#include <linux/types.h>
-
#include <net/sock.h>
-
#include <net/netlink.h>
-
-
#define NETLINK_TEST 25
-
#define MAX_MSGSIZE 1024
-
int pid;
-
int err;
-
struct sock *nl_sk = NULL;
-
int flag = 0;
-
-
int stringlength(const char *s)
-
{
-
int slen = 0;
-
for(; *s; s++){
-
slen++;
-
}
-
return slen;
-
}
-
-
void sendnlmsg(void)
-
{
-
struct sk_buff *skb_1;
-
struct nlmsghdr *nlh;
-
int len = NLMSG_SPACE(MAX_MSGSIZE);
-
int slen = 0;
-
char buffer[128];
-
const char *message="hello i am kernel";
-
if(!message || !nl_sk){
-
return ;
-
}
-
skb_1 = alloc_skb(len,GFP_KERNEL);
-
if(!skb_1){
-
printk(KERN_ERR "my_net_link:alloc_skb_1 error\n");
-
}
-
nlh = nlmsg_put(skb_1,0,0,0,MAX_MSGSIZE,0);
-
-
//NETLINK_CB(skb_1).pid = 0;
-
NETLINK_CB(skb_1).dst_group = 0;
-
-
slen = stringlength(message);
-
memset(buffer,0,sizeof(buffer));
-
memcpy(buffer,message,slen);
-
memcpy(NLMSG_DATA(nlh),buffer,slen+1);
-
printk("my_net_link:send message '%s'.\n",(char *)NLMSG_DATA(nlh));
-
-
netlink_unicast(nl_sk,skb_1,pid,MSG_DONTWAIT);
-
}
-
-
void nl_data_ready(struct sk_buff *__skb)
-
{
-
struct sk_buff *skb;
-
struct nlmsghdr *nlh;
-
char str[100];
-
struct completion cmpl;
-
int i=10;
-
skb = skb_get (__skb);
-
if(skb->len >= NLMSG_SPACE(0)){
-
nlh = nlmsg_hdr(skb);
-
-
memcpy(str, NLMSG_DATA(nlh), sizeof(str));
-
printk("Message received:%s\n",str) ;
-
pid = nlh->nlmsg_pid;
-
while(i--){
-
//init_completion(&cmpl);
-
//wait_for_completion_timeout(&cmpl,3 * HZ);
-
sendnlmsg();
-
break;
-
}
-
flag = 1;
-
kfree_skb(skb);
-
}
-
-
}
-
-
// Initialize netlink
-
-
/*
-
kernel 3.9.6中实例代码
-
-
struct netlink_kernel_cfg {
-
unsigned int groups;
-
unsigned int flags;
-
void (*input)(struct sk_buff *skb);
-
struct mutex *cb_mutex;
-
void (*bind)(int group);
-
};
-
-
netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
-
-
3.2.0-24中
-
struct sock *netlink_kernel_create(struct net *net,
-
int unit,unsigned int groups,
-
void (*input)(struct sk_buff *skb),
-
struct mutex *cb_mutex,
-
struct module *module);
-
*/
-
-
static int netlink_init(void)
-
{
-
struct netlink_kernel_cfg cfg = {
-
.input = nl_data_ready,//该函数原型可参考内核代码,其他参数默认即可,可参考内核中的调用
-
};
-
-
nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);
-
-
if(!nl_sk){
-
printk(KERN_ERR "my_net_link: create netlink socket error.\n");
-
return 1;
-
}
-
-
printk("my_net_link_3: create netlink socket ok.\n");
-
return 0;
-
}
-
-
static void netlink_exit(void)
-
{
-
if(nl_sk != NULL){
-
sock_release(nl_sk->sk_socket);
-
}
-
-
printk("my_net_link: self module exited\n");
-
}
-
-
module_init(netlink_init);
-
module_exit(netlink_exit);
-
-
MODULE_AUTHOR("");
-
MODULE_LICENSE("GPL");
Makefile:
-
obj-m := netlink.o
-
KERNELBUILD := /lib/modules/`uname -r`/build
-
default:
-
make -C $(KERNELBUILD) M=$(shell pwd) modules
-
clean:
-
rm -rf *.o .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers .*.d *.unsigned *.order
关键词解释:
协议族
是一组协议的集合。
协议栈
是协议的实现。
地址族
是地址划分的标准集合。
阅读(1727) | 评论(0) | 转发(0) |