Как мне создать «сетевую связь» между ядром и пользовательским пространством?
-
03-07-2019 - |
Вопрос
Я хочу использовать netlink для связи между приложением и пространством ядра.Моя версия ядра Linux — 2.6.28, и мой неправильный код:
nf_sock=netlink_kernel_create(NL_PROTO,0,nl_user_skb,THIS_MODULE);
Сокращенное сообщение об ошибке:
error: too few arguments to function 'netlink_kernel_create'
В файле <linux/netlink.h>
, функция netlink_kernel_create()
определяется как
extern 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)
Я не понимаю, что использовать в качестве первого аргумента, net
.Может ли кто-нибудь объяснить, что я должен здесь использовать?
Решение
А struct net
содержит информацию о сетевом пространстве имен — наборе сетевых ресурсов, доступных процессам.Обратите внимание, что может существовать несколько сетевых пространств имен (т.несколько экземпляров сетевого стека), но большинство драйверов используют пространство имен init_net.
Ваш звонок, вероятно, должен выглядеть примерно так:
nf_sock = netlink_kernel_create(&init_net,
NETLINK_USERSOCK,
0,
nl_rcv_func,
NULL,
THIS_MODULE);
где nl_rcv_func
это функция, принимающая struct sk_buff *skb
в качестве единственного аргумента и обрабатывает полученное сообщение netlink.
Другие советы
Кажется, вы следовали такому руководству, как Вот этот, который (начиная с 2005 года) вполне мог быть опередлен развитием ядра.Кажется, изменился внутренний API для создания сетевой ссылки со стороны ядра.
Либо проверьте папку Documentation/ в локальном дереве ядра на наличие какой-нибудь (надеюсь, более свежей) документации, либо прочитайте сам код.Вы также можете тралить архивы списка рассылки Linux Kernel для любого упоминания об изменениях, которые, по-видимому, произошли.
Здесь - это фактическая реализация по состоянию на 2.6.29, если вы предпочитаете разгадывать ее задом наперед (и, конечно, еще не проверили это в своем собственном дереве).
Да, struct net действительно предназначена для сетевого пространства имен, но не всегда следует использовать init_net, вам следует зарегистрировать свои собственные pernet_operations, например:
static struct pernet_operations fib_net_ops = {
.init = fib_net_init,
.exit = fib_net_exit,
};
static int __net_init fib_net_init(struct net *net)
{
int error;
#ifdef CONFIG_IP_ROUTE_CLASSID
net->ipv4.fib_num_tclassid_users = 0;
#endif
error = ip_fib_net_init(net);
if (error < 0)
goto out;
error = nl_fib_lookup_init(net);
if (error < 0)
goto out_nlfl;
error = fib_proc_init(net);
if (error < 0)
goto out_proc;
out:
return error;
out_proc:
nl_fib_lookup_exit(net);
out_nlfl:
ip_fib_net_exit(net);
goto out;
}
static int __net_init nl_fib_lookup_init(struct net *net)
{
struct sock *sk;
struct netlink_kernel_cfg cfg = {
.input = nl_fib_input,
};
sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg);
if (sk == NULL)
return -EAFNOSUPPORT;
net->ipv4.fibnl = sk;
return 0;
}
и наконец:
register_pernet_subsys(&fib_net_ops);
Я бы предложил ioctl для связи ядра/пользователя.Интерфейс ioctl является стандартным, и вероятность его обновления между ядрами невелика.