Chinaunix首页 | 论坛 | 博客
  • 博客访问: 822493
  • 博文数量: 92
  • 博客积分: 1498
  • 博客等级: 上尉
  • 技术积分: 993
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-18 18:31
文章分类

全部博文(92)

文章存档

2013年(2)

2012年(3)

2011年(3)

2010年(61)

2009年(23)

分类: LINUX

2010-12-07 10:33:09

首先声明,代码是根据网上的代码修改而成,修改主要包括内核态想用户态下的数据传输(之前版本没有),这里贴出的是基于2.6.22内核版本实现的;2.6.32版本的实现见我的博客:传送过去 
nl.h
 

#ifndef __nl_h__
#define __nl_h__
#define My_netlink 26
#define U_PID 1
#define K_MSG 2
#endif
struct
{
  __u32 pid;
}user_proc;

kernel_src.c

/*
 * Copyright (c) 2010-~ zhouyongfei
 *
 * The source code is released for free distribution under the terms of the GNU General Public License
 *
 *
 * Author: alen Chou
 * Created Time: 2010年11月15日 星期一 09时24分23秒
 * File Name: nl_k.c
 * Description:
 *
 */


#include <linux/module.h>
#include <linux/init.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include "nl.h"
static struct sock *nlfd;
int send_to_user(char *info) //发送到用户态

{
    int size;
    struct sk_buff *skb;
    unsigned char *old_tail;
    struct nlmsghdr *nlh;

    int retval;

    size = NLMSG_SPACE(strlen(info));
    //size = NLMSG_SPACE(25);

    skb = alloc_skb(size, GFP_ATOMIC);

    //skb->data = "hello ,this is alen chou.\n";


    //nlh = NLMSG_PUT(skb, 0, 0, K_MSG, size-sizeof(*nlh));

    
    nlh = nlmsg_put(skb,0,0,0,NLMSG_SPACE(strlen(info))-sizeof(struct nlmsghdr),0);
    
    old_tail = skb->tail;
    memcpy(NLMSG_DATA(nlh),info,strlen(info));
    nlh->nlmsg_len = skb->tail - old_tail;
    NETLINK_CB(skb).pid = 0;
    //NETLINK_CB(skb).dst_pid = user_proc.pid;

    NETLINK_CB(skb).dst_group = 0;

    printk("in kernel,skb->data:%s\n",(char *)NLMSG_DATA((struct nlmsghdr *)skb->data));
 
    retval = netlink_unicast(nlfd, skb, user_proc.pid, MSG_DONTWAIT);
    printk("netlink_unicast retuen: %d\n",retval);
    return 0;
//nlmsg_failure:

    //if(skb)

    //    kfree_skb(skb);

//    return -1;

}
void kernel_receive(struct sk_buff* __skb) //内核接受函数

{
    struct sk_buff *skb;
    struct nlmsghdr *nlh = NULL;

    char *data = "hello,this is alenchou's message from kernel\n";
  
    printk("begin kernel_receive\n");
    skb = skb_get(__skb);
    

    if(skb->len >= sizeof(struct nlmsghdr)){
        printk("kernel coming here in if\n");
        nlh = (struct nlmsghdr *)skb->data;
        //nlh = nlmsg_hdr(__skb);

        //memcpy(data,NLMSG_DATA(nlh),sizeof(data));

        if((nlh->nlmsg_len >= sizeof(struct nlmsghdr))
               && (__skb->len >= nlh->nlmsg_len)){
            
            user_proc.pid = nlh->nlmsg_pid;
            printk("data receive from user are:%s\n",(char *)NLMSG_DATA(nlh));
            //printk("data receive from user are:%s\n",data);

            printk("user_pid:%d\n",user_proc.pid);
            send_to_user(data);
        
        }
    }else{
        printk("kernle coming here in else!!\n");
        printk("user data:%s\n",(char *)NLMSG_DATA(nlmsg_hdr(__skb)));
        send_to_user(data);
    }

    
    kfree_skb(skb);
}
int __init nl_init(void)
{
    printk("nl start!!\n");
    nlfd = netlink_kernel_create(&init_net, My_netlink, 0, kernel_receive, NULL, THIS_MODULE);
    if(!nlfd){
        printk("can not create a netlink socket\n");
        return -1;
    }
    return 0;
}
void __exit nl_exit(void)
{
    sock_release(nlfd->sk_socket);
    printk("nl exit!!\n");
}
 
MODULE_DESCRIPTION("NETLINK_TEST");
MODULE_LICENSE("GPL");
module_init(nl_init);
module_exit(nl_exit);


user_src.c

 

/*
 * Copyright (c) 2010-~ zhouyongfei
 *
 * The source code is released for free distribution under the terms of the GNU General Public License
 *
 *
 * Author: alen Chou
 * Created Time: 2010年11月15日 星期一 09时24分35秒
 * File Name: nl_u.c
 * Description:
 *
 */


#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <linux/netlink.h>
#include "nl.h"
struct msg_to_kernel
{
    struct nlmsghdr hdr;
    char data[100];
};
struct u_packet_info
{
    struct nlmsghdr hdr;
    char msg[100];
};
int main(void)
{
    char *data = "hello,this is from alen's space\0";
    //初始化

    struct sockaddr_nl local;
    struct sockaddr_nl kpeer;
    int skfd,ret,kpeerlen = sizeof(struct sockaddr_nl);;
    //struct msg_to_kernel message;

    struct nlmsghdr *message;
    struct u_packet_info info;
    char *retval;

    message = (struct nlmsghdr *)malloc(1);
 
    skfd = socket(PF_NETLINK, SOCK_RAW, My_netlink);
    if(skfd < 0){
            printf("can not create a netlink socket\n");
            return -1;
    }
    memset(&local, 0, sizeof(local));
    local.nl_family = AF_NETLINK;
    local.nl_pid = getpid();
    local.nl_groups = 0;
    if(bind(skfd, (struct sockaddr*)&local, sizeof(local)) != 0){
        printf("bind() error\n");
        return -1;
    }
    memset(&kpeer, 0, sizeof(kpeer));
    kpeer.nl_family = AF_NETLINK;
    kpeer.nl_pid = 0;
    kpeer.nl_groups = 0;
 
    memset(message,'\0', sizeof(struct nlmsghdr));
    message->nlmsg_len = NLMSG_SPACE(strlen(data));
    message->nlmsg_flags = 0;
    message->nlmsg_type = 0;//U_PID;

    message->nlmsg_seq = 0;
    message->nlmsg_pid = local.nl_pid;

    
    retval = memcpy(NLMSG_DATA(message),data,strlen(data));
    //初始化结束

    //发送进程PID

    printf("message sendto kernel are:%s,len:%d\n",(char *)NLMSG_DATA(message),message->nlmsg_len);
    ret = sendto(skfd, message, message->nlmsg_len, 0,(struct sockaddr *)&kpeer, sizeof(kpeer));
    if(!ret){
        perror("send pid:");
        exit(-1);
    }

    //接受内核态确认信息

    ret = recvfrom(skfd, &info, sizeof(struct u_packet_info),0, (struct sockaddr*)&kpeer, &kpeerlen);
    if(!ret){
        perror("recv form kerner:");
        exit(-1);
    }
 
    printf("message from kernel:%s\n",(char *)info.msg);
    //内核和用户进行通信

 
    close(skfd);
    return 0;
}


Makefile

obj-m:=kernel_src.o
KDIR=/lib/modules/$(shell uname -r)/build
all:
    make -C $(KDIR) M=$(PWD) modules
clean:
    make -C $(KDIR) M=$(PWD) clean


阅读(2285) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-12-07 15:53:05

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com