使用Linux sysfs_notify调用

我试图在内核驱动程序和用户空间程序之间进行asynchronous通信(我知道这里有很多问题需要类似的信息,但是我找不到任何与sysfs_notify有关的问题)。

我在这里离开Vilhelm的编辑,但是将源代码添加到使用sysfs的简单驱动程序和用户空间程序来轮询它。 司机工作正常(我从网上获得了大部分,它是缺less信用,但我回去添加他们时找不到他们)。 不幸的是,投票程序不起作用。 它总是立即返回成功。 有趣的是,如果我在调查之前没有执行两次读取,则revents成员将设置为POLLERR | POLLIN而不是像在程序输出中看到的POLLIN。

节目输出:

root @ ubuntu:/ home / wmulcahy / demo#./readhello
触发
属性文件值:74(t)[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[] = { &notify.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 ); } 

一些即将到来的sysfs增强 。

在内部,修补程序为系统上的每个kobject添加一个等待队列头; 该队列被插入到轮询表中以响应poll()调用。 但是,sysfs代码无法知道任何给定的sysfs属性的值是否已更改,因此实现pollable属性的子系统必须显式调用:

 void sysfs_notify(struct kobject *kobj, char *dir, char *attr); 

谢谢李先生

Solutions Collecting From Web of "使用Linux sysfs_notify调用"

阻止民意调查来自用户方面。 用户代码可以简单地告诉内核它感兴趣的属性,然后阻塞poll()直到其中一个已经改变。

sysfs_notify()是释放用户空间poll()的内核端调用。 调整内核属性值后,只需调用sysfs_notify()以允许任何用户空间应用程序响应其未完成的poll()

poll()看作是“订阅”感兴趣属性的改变的通知,将sysfs_notify() “发布”给任何订阅者。