Я пытаюсь общаться асинхронно между драйвером ядра и программой для пространства пользователя (я знаю, что здесь есть много вопросов, которые запрашивают подобную информацию, но я не мог найти ничего, что связано с sysfs_notify).Использование вызова sysfs_notify Linux
Я оставляю здесь редактирование Vilhelm, но добавляя источник как к простому драйверу, использующему sysfs, так и к программе пользовательского пространства для опроса. Драйвер отлично работает (я получил большую часть из сети, он не получил кредитов, но я не мог найти их, когда возвращался, чтобы добавить их). К сожалению, программа опроса не работает. Он всегда возвращает успех немедленно. Интересно, что, если я не буду выполнять два чтения перед опросом, члены-регенерации будут установлены в POLLERR | POLLIN вместо просто POLLIN, как видно на выходе программы.
выход программы:
корень @ Ubuntu:/Главная/wmulcahy/демо # ./readhello
вызвало
значение атрибута файла: 74 (т) [0]
revents [0]: 00000001
revents [1]: 00000001
Здесь вы водитель: hello.c (вы можете увидеть, где я начал ...)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
struct my_attr {
struct attribute attr;
int value;
};
static struct my_attr notify = {
.attr.name="notify",
.attr.mode = 0644,
.value = 0,
};
static struct my_attr trigger = {
.attr.name="trigger",
.attr.mode = 0644,
.value = 0,
};
static struct attribute * myattr[] = {
¬ify.attr,
&trigger.attr,
NULL
};
static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
printk("hello: show called (%s)\n", a->attr.name);
return scnprintf(buf, PAGE_SIZE, "%s: %d\n", a->attr.name, a->value);
}
static struct kobject *mykobj;
static ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len)
{
struct my_attr *a = container_of(attr, struct my_attr, attr);
sscanf(buf, "%d", &a->value);
notify.value = a->value;
printk("sysfs_notify store %s = %d\n", a->attr.name, a->value);
sysfs_notify(mykobj, NULL, "notify");
return sizeof(int);
}
static struct sysfs_ops myops = {
.show = show,
.store = store,
};
static struct kobj_type mytype = {
.sysfs_ops = &myops,
.default_attrs = myattr,
};
static struct kobject *mykobj;
static int __init hello_module_init(void)
{
int err = -1;
printk("Hello: init\n");
mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL);
if (mykobj) {
kobject_init(mykobj, &mytype);
if (kobject_add(mykobj, NULL, "%s", "hello")) {
err = -1;
printk("Hello: kobject_add() failed\n");
kobject_put(mykobj);
mykobj = NULL;
}
err = 0;
}
return err;
}
static void __exit hello_module_exit(void)
{
if (mykobj) {
kobject_put(mykobj);
kfree(mykobj);
}
printk("Hello: exit\n");
}
module_init(hello_module_init);
module_exit(hello_module_exit);
MODULE_LICENSE("GPL");
А вот программа опрос: readhello.c
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <poll.h>
#define TEST_SYSFS_TRIGGER "/sys/hello/trigger"
#define TEST_SYSFS_NOTIFY "/sys/hello/notify"
int main(int argc, char **argv)
{
int cnt, notifyFd, triggerFd, rv;
char attrData[100];
struct pollfd ufds[2];
// Open a connection to the attribute file.
if ((notifyFd = open(TEST_SYSFS_NOTIFY, O_RDWR)) < 0)
{
perror("Unable to open notify");
exit(1);
}
// Open a connection to the attribute file.
if ((triggerFd = open(TEST_SYSFS_TRIGGER, O_RDWR)) < 0)
{
perror("Unable to open trigger");
exit(1);
}
ufds[0].fd = notifyFd;
ufds[0].events = POLLIN;
ufds[1].fd = triggerFd;
ufds[1].events = POLLIN;
// Someone suggested dummy reads before the poll() call
cnt = read(notifyFd, attrData, 100);
cnt = read(triggerFd, attrData, 100);
ufds[0].revents = 0;
ufds[1].revents = 0;
if ((rv = poll(ufds, 2, 10000)) < 0)
{
perror("poll error");
}
else if (rv == 0)
{
printf("Timeout occurred!\n");
}
else if (ufds[0].revents & POLLIN)
{
printf("triggered\n");
cnt = read(notifyFd, attrData, 1);
printf("Attribute file value: %02X (%c) [%d]\n", attrData[0], attrData[0], cnt);
}
printf("revents[0]: %08X\n", ufds[0].revents);
printf("revents[1]: %08X\n", ufds[1].revents);
close(triggerFd);
close(notifyFd);
}
Some upcoming sysfs enhancements.
Внутренний патч добавляет очередь очереди ожидания к каждому объекту в системе ; эта очередь вставляется в таблицу опроса в ответ на вызов poll(). Код sysfs не имеет никакого способа знать, однако, когда значение любого заданного sysfs атрибут изменился, поэтому подсистема реализации Pollable атрибут должен сделать явные вызовы:
void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
Спасибо, Lee
Не 'sysfs_poll' автоматически вызывается для атрибутов sysfs? –
Да, опрос пользователя() подключается через VFS и в конечном итоге к sysfs_poll(). Это сторона, которая ждет изменений. Сторона, которая производит изменения, вызывает sysfs_notify(), чтобы активировать активную sysfs_poll(). – Peter
Спасибо вам за ваше редактирование и ответ.Я уже видел эту ссылку, Вильхельм, и понял, о чем вы говорите, Питер. Я собираюсь изменить вопрос, чтобы сфокусироваться. У меня есть примеры кода, которые были вычеркнуты из Интернета и написаны самим собой, что не работают. Может быть, вы можете взглянуть. – Digilee