在使用netlink时,我们一般会使用genl_register_family 和 genl_register_ops,或者直接使用genl_register_family_with_ops,但是genl_register_ops的作用仅仅是是用户空间收到消息是实际处理的回调函数,如果我们只是向用户空间发送一个字符串的话,只调用genl_register_family 就可以了。
例如在acpi button的中就调用acpi_bus_generate_netlink_event 来向用户空间发送event
static void acpi_button_notify(struct acpi_device *device, u32 event)
{
keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
input_sync(input);
acpi_bus_generate_netlink_event(
device->pnp.device_class,
dev_name(&device->dev),
event, ++button->pushed);
}
而这里用的netlink其实是在acpi_event_init 中注册的。
static int __init acpi_event_init(void)
{
/* create genetlink for acpi event */
error = acpi_event_genetlink_init();
if (error)
printk(KERN_WARNING PREFIX
"Failed to create genetlink family for ACPI event\n");
return 0;
}
fs_initcall(acpi_event_init);
通过fs_initcall 可知是开机自动运行
static int acpi_event_genetlink_init(void)
{
return genl_register_family(&acpi_event_genl_family);
}
直接调用genl_register_family,因为我们不需要user space收到消息后回调所以没有必要使用genl_register_ops。
在调用__genl_register_family的时候会检查ops是否合法
int __genl_register_family(struct genl_family *family)
361 {
362 int err = -EINVAL, i;
363
364 if (family->id && family->id < GENL_MIN_ID)
365 goto errout;
366
367 if (family->id > GENL_MAX_ID)
368 goto errout;
369
370 err = genl_validate_ops(family);
371 if (err)
372 return err;
}
从genl_validate_ops 函数中可以看出,因为n_ops ==0 和 ops == NULL,这组条件也是合法的。所以在这种情况下就没有必要调用genl_register_ops
static int genl_validate_ops(const struct genl_family *family)
324 {
325 const struct genl_ops *ops = family->ops;
326 unsigned int n_ops = family->n_ops;
327 int i, j;
328
329 if (WARN_ON(n_ops && !ops))
330 return -EINVAL;
331
332 if (!n_ops)
333 return 0;
334
335 for (i = 0; i < n_ops; i++) {
336 if (ops[i].dumpit == NULL && ops[i].doit == NULL)
337 return -EINVAL;
338 for (j = i + 1; j < n_ops; j++)
339 if (ops[i].cmd == ops[j].cmd)
340 return -EINVAL;
341 }
342
343 return 0;
344 }
例如在acpi button的中就调用acpi_bus_generate_netlink_event 来向用户空间发送event
static void acpi_button_notify(struct acpi_device *device, u32 event)
{
keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
input_sync(input);
acpi_bus_generate_netlink_event(
device->pnp.device_class,
dev_name(&device->dev),
event, ++button->pushed);
}
而这里用的netlink其实是在acpi_event_init 中注册的。
static int __init acpi_event_init(void)
{
/* create genetlink for acpi event */
error = acpi_event_genetlink_init();
if (error)
printk(KERN_WARNING PREFIX
"Failed to create genetlink family for ACPI event\n");
return 0;
}
fs_initcall(acpi_event_init);
通过fs_initcall 可知是开机自动运行
static int acpi_event_genetlink_init(void)
{
return genl_register_family(&acpi_event_genl_family);
}
直接调用genl_register_family,因为我们不需要user space收到消息后回调所以没有必要使用genl_register_ops。
在调用__genl_register_family的时候会检查ops是否合法
int __genl_register_family(struct genl_family *family)
361 {
362 int err = -EINVAL, i;
363
364 if (family->id && family->id < GENL_MIN_ID)
365 goto errout;
366
367 if (family->id > GENL_MAX_ID)
368 goto errout;
369
370 err = genl_validate_ops(family);
371 if (err)
372 return err;
}
从genl_validate_ops 函数中可以看出,因为n_ops ==0 和 ops == NULL,这组条件也是合法的。所以在这种情况下就没有必要调用genl_register_ops
static int genl_validate_ops(const struct genl_family *family)
324 {
325 const struct genl_ops *ops = family->ops;
326 unsigned int n_ops = family->n_ops;
327 int i, j;
328
329 if (WARN_ON(n_ops && !ops))
330 return -EINVAL;
331
332 if (!n_ops)
333 return 0;
334
335 for (i = 0; i < n_ops; i++) {
336 if (ops[i].dumpit == NULL && ops[i].doit == NULL)
337 return -EINVAL;
338 for (j = i + 1; j < n_ops; j++)
339 if (ops[i].cmd == ops[j].cmd)
340 return -EINVAL;
341 }
342
343 return 0;
344 }