linux下的netlink编程

linux学习 2.4 版以后版本的内核中,几乎全部的中断过程与用户态进程的通信都是使用 netlink 套接字实现的,同时还使用 netlink 实现了 ip queue 工具,但 ip queue 的使用有其局限性,不能自由地用于各种中断过程。内核的帮助文档和其他一些 linux学习 相关文章都没有对 netlink 套接字在中断过程和用户空间通信的应用上作详细的说明,使得很多用户对此只有一个模糊的概念。

Unicast Communication between Kernel and Application
在下面的例子中,一个用户空间进程发送一个netlink消息给内核模块,内核模块应答一个消息给发送进程,这里是用户空间的代码:

 

#include  < sys / socket.h >
#include 
< linux学习 / netlink.h >
#define  MAX_PAYLOAD 1024  /* maximum payload size*/
struct  sockaddr_nl src_addr, dest_addr;
struct  msghdr msg;
struct  nlmsghdr  * nlh  =  NULL;
struct  iovec iov;
int  sock_fd;
void  main()  {
 sock_fd 
= socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);
 memset(
&src_addr, 0sizeof(src_addr));
 src__addr.nl_family 
= AF_NETLINK;      
 src_addr.nl_pid 
= getpid();  /* self pid */
 src_addr.nl_groups 
= 0;  /* not in mcast groups */
 bind(sock_fd, (
struct sockaddr*)&src_addr, 
      
sizeof(src_addr));
 memset(
&dest_addr, 0sizeof(dest_addr));
 dest_addr.nl_family 
= AF_NETLINK;
 dest_addr.nl_pid 
= 0;   /* For Linux Kernel */
 dest_addr.nl_groups 
= 0/* unicast */
 nlh
=(struct nlmsghdr *)malloc(
                         NLMSG_SPACE(MAX_PAYLOAD));
 
/* Fill the netlink message header */
 nlh
->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
 nlh
->nlmsg_pid = getpid();  /* self pid */
 nlh
->nlmsg_flags = 0;
 
/* Fill in the netlink message payload */
 strcpy(NLMSG_DATA(nlh), 
"Hello you!");
 iov.iov_base 
= (void *)nlh;
 iov.iov_len 
= nlh->nlmsg_len;
 msg.msg_name 
= (void *)&dest_addr;
 msg.msg_namelen 
= sizeof(dest_addr);
 msg.msg_iov 
= &iov;
 msg.msg_iovlen 
= 1;
 sendmsg(fd, 
&msg, 0);
 
/* Read message from kernel */
 memset(nlh, 
0, NLMSG_SPACE(MAX_PAYLOAD));
 recvmsg(fd, 
&msg, 0);
 printf(
" Received message payload: %s "
        NLMSG_DATA(nlh));
    
 
/* Close Netlink Socket */
 close(sock_fd);
}
    

这里是内核代码:

 

struct  sock  * nl_sk  =  NULL;
void  nl_data_ready ( struct  sock  * sk,  int  len)
{
  wake_up_interruptible(sk
->sleep);
}

void  netlink_test()  {
 
struct sk_buff *skb = NULL;
 
struct nlmsghdr *nlh = NULL;
 
int err;
 u32 pid;     
 nl_sk 
= netlink_kernel_create(NETLINK_TEST, 
                                   nl_data_ready);
 
/* wait for message coming down from user-space */
 skb 
= skb_recv_datagram(nl_sk, 00&err);
 nlh 
= (struct nlmsghdr *)skb->data;
 printk(
"%s: received netlink message payload:%s "
        __FUNCTION__, NLMSG_DATA(nlh));
 pid 
= nlh->nlmsg_pid; /*pid of sending process */
 NETLINK_CB(skb).groups 
= 0/* not in mcast group */
 NETLINK_CB(skb).pid 
= 0;      /* from kernel */
 NETLINK_CB(skb).dst_pid 
= pid;
 NETLINK_CB(skb).dst_groups 
= 0;  /* unicast */
 netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
 sock_release(nl_sk
->socket);
}
 

在内核模块被加载到内核,当我们运行用户程序,我们将看到下面的信息:

Received message payload: Hello you!
 
 

然后用dmesg我们可以看到内核输出:

netlink_test: received netlink message payload:
Hello you!

Multicast Communication between Kernel and Applications
这个例子中,两个应用程序在监听同一个netlink广播组.内核模块发送一个netlink消息给这个广播组,所用的应用程序都收到它,如下是用户程序代码:

#include  < sys / socket.h >
#include 
< linux学习 / netlink.h >
#define  MAX_PAYLOAD 1024  /* maximum payload size*/
struct  sockaddr_nl src_addr, dest_addr;
struct  nlmsghdr  * nlh 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值