2009-05-14 5 views
2

Я пишу драйвер Linux, используя netlink для связи между пользовательским пространством и пространством ядра. Но я не могу найти полезные материалы, потому что netlink изменился с ядра Linux> = 2.6.24. Кто может дать мне несколько советов о том, как создать сокет netlink. Заранее спасибо!Кто может дать мне последние образцы программирования netlink?

ответ

0

Я уже давно не занимаюсь программированием ядра. Поэтому я не могу привести вам прямой пример того, какие изменения были внесены. Я могу рассказать вам, как мне понять функции netlink и как их использовать, считывая код. Особенно код от NetworkManager или беспроводных расширений (iwlib), так как это была моя область фокуса 2 года назад. Эти проекты OSS всегда находятся на вершине изменений в ядре, и их код не сложно понять.

6

В приведенном ниже коде представлены основы отправки данных из приложения пользовательского пространства в модуль ядра с использованием netlink. Этот код работает на Linux 2.6.28.9 с версией git (ef8ba32) от libnl. Для получения дополнительной информации ознакомьтесь с libnl documentation и кодом для iw, который широко использует netlink.

Kernel

#include <linux/kernel.h> 
#include <linux/module.h> 

#include <net/sock.h> 
#include <net/netlink.h> 

#define MY_MSG_TYPE (0x10 + 2) // + 2 is arbitrary. same value for kern/usr 

static struct sock *my_nl_sock; 

DEFINE_MUTEX(my_mutex); 

static int 
my_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 
{ 
    int type; 
    char *data; 

    type = nlh->nlmsg_type; 
    if (type != MY_MSG_TYPE) { 
     printk("%s: expect %#x got %#x\n", __func__, MY_MSG_TYPE, type); 
     return -EINVAL; 
    } 

    data = NLMSG_DATA(nlh); 
    printk("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", __func__, 
      data[0], data[1], data[2], data[3], 
      data[4], data[5], data[6], data[7]); 
    return 0; 
} 

static void 
my_nl_rcv_msg(struct sk_buff *skb) 
{ 
    mutex_lock(&my_mutex); 
    netlink_rcv_skb(skb, &my_rcv_msg); 
    mutex_unlock(&my_mutex); 
} 

static int 
my_init(void) 
{ 
    my_nl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, 
      my_nl_rcv_msg, NULL, THIS_MODULE); 
    if (!my_nl_sock) { 
     printk(KERN_ERR "%s: receive handler registration failed\n", __func__); 
     return -ENOMEM; 
    } 

    return 0; 
} 

static void 
my_exit(void) 
{ 
    if (my_nl_sock) { 
     netlink_kernel_release(my_nl_sock); 
    } 
} 

module_init(my_init); 
module_exit(my_exit); 

Space Пользователь

#include <stdio.h> 
#include <stdlib.h> 

#include <netlink/netlink.h> 

#define MY_MSG_TYPE (0x10 + 2) // + 2 is arbitrary but is the same for kern/usr 
int 
main(int argc, char *argv[]) 
{ 
    struct nl_sock *nls; 
    char msg[] = { 0xde, 0xad, 0xbe, 0xef, 0x90, 0x0d, 0xbe, 0xef }; 
    int ret; 

    nls = nl_socket_alloc(); 
    if (!nls) { 
     printf("bad nl_socket_alloc\n"); 
     return EXIT_FAILURE; 
    } 

    ret = nl_connect(nls, NETLINK_USERSOCK); 
    if (ret < 0) { 
     nl_perror(ret, "nl_connect"); 
     nl_socket_free(nls); 
     return EXIT_FAILURE; 
    } 

    ret = nl_send_simple(nls, MY_MSG_TYPE, 0, msg, sizeof(msg)); 
    if (ret < 0) { 
     nl_perror(ret, "nl_send_simple"); 
     nl_close(nls); 
     nl_socket_free(nls); 
     return EXIT_FAILURE; 
    } else { 
     printf("sent %d bytes\n", ret); 
    } 

    nl_close(nls); 
    nl_socket_free(nls); 

    return EXIT_SUCCESS; 
}