Могу ли я иметь более 32 сокетов netlink в пространстве ядра?
У меня есть несколько модулей ядра, которые должны взаимодействовать с пространством пользователя. Следовательно, каждый модуль имеет сокет Netlink.
Моя проблема в том, что эти розетки мешают друг другу. Это связано с тем, что все они регистрируются в одном и том же семействе адресов Netlink (поскольку не так много доступных для начала - максимум 32, а более половины уже зарезервировано), а также потому, что все они привязаны к одному и тому же pid (ядро pid - ноль).
Хотелось бы, чтобы было больше места для адресных семей. Или, еще лучше, я хотел бы связать свои гнезда с другими пидсами. Почему Netlink является предпочтительным каналом ядра пользователя, если одновременно можно открыть только 32 сокета?
Документация libnl-3 гласит
Адрес netlink (порт) состоит из 32-битного целого числа. Порт 0 (ноль) зарезервирован для ядра и относится к сокету на стороне ядра каждого семейства протоколов netlink. Другие номера портов обычно относятся к сокетам, принадлежащим пользовательскому пространству, хотя это не применяется.
Это последнее утверждение кажется ложью прямо сейчас. Ядро использует константу в качестве pid и не экспортирует более универсальные функции:
if (netlink_insert(sk, 0))
goto out_sock_release;
Я думаю, я могу перекомпилировать ядро и увеличить предел семейства адресов. Но это модули ядра; Я не должен был этого делать.
Я что-то пропустил?
2 ответа
Нет.
Предел количества сокетов Netlink - это то, почему Generic Netlink существует.
Универсальный Netlink - это слой поверх стандартного Netlink. Вместо того, чтобы открывать сокет, вы регистрируете обратный вызов на уже установленном сокете и слушаете там сообщения, направленные к "подсемейному" семейству. Учитывая, что есть больше доступных слотов семейства (1023) и нет портов, я предполагаю, что они чувствовали, что разделение между семействами и портами было ненужным на этом уровне.
Чтобы зарегистрировать слушателя в пространстве ядра, используйте genl_register_family()
или его братья и сестры. В пользовательском пространстве Generic Netlink можно использовать через API libnl-3 (хотя он довольно ограничен, но код говорит о многом и открыт).
Вы смущены MAX_LINKS
имя переменной. Это не "максимальное количество ссылок", это "максимальное количество семейств". Вы перечислили семейства netlink или IOW группы netlink. Там действительно 32 семьи. Каждая семья посвящена служению определенной цели. Например NETLINK_SELINUX
для уведомления SELinux и NETLINK_KOBJECT_UEVENT
предназначен для уведомлений kobject (это то, что обрабатывает udev).
Но нет ограничений по количеству розеток для каждой семьи.
Когда вы звоните netlink_create
он проверяет номер вашего протокола, который в случае сокета netlink относится к семейству netlink NETLINK_SELINUX
, Посмотри код
static int netlink_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
...
if (protocol < 0 || protocol >= MAX_LINKS)
return -EPROTONOSUPPORT;
...
Вот как ваш MAX_LINKS использует.
Позже, когда на самом деле создать сокет, он вызывает __netlink_create
который в свою очередь вызывает sk_alloc
который в свою очередь вызывает sk_prot_alloc
, Сейчас в sk_prot_alloc
он выделяет сокет kmalloc
ing (netlink не имеет своего собственного кэша slab):
slab = prot->slab;
if (slab != NULL) {
sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
if (!sk)
return sk;
if (priority & __GFP_ZERO) {
if (prot->clear_sk)
prot->clear_sk(sk, prot->obj_size);
else
sk_prot_clear_nulls(sk, prot->obj_size);
}
} else
sk = kmalloc(prot->obj_size, priority);