我正在尝试在内核驱动程序和用户空间程序之间进行异步通信(我知道这里有很多问题需要类似的信息,但是找不到与sysfs_notify相关的信息)。
我将在这里留下Vilhelm的编辑,但是将源代码添加到一个使用sysfs的简单驱动程序中,并在一个用户空间程序中对其进行轮询。驱动程序工作正常(我从网络上获得了大部分钱;它缺少功劳,但是我回去添加功劳时找不到它们)。不幸的是,轮询程序无法正常工作。它总是立即返回成功。有趣的是,如果我在轮询之前不执行两次读取,则revents成员将设置为POLLERR
| 在程序输出中看到的是POLLIN,而不仅仅是POLLIN。
程序输出:
root @ ubuntu:/ home / wmulcahy / demo#./readhello已
触发
属性文件值:74(t)[0]
清除[0]:00000001
清除[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 );
}
即将推出的sysfs增强功能。
在内部,补丁程序向系统上的每个kobject添加了一个等待队列头。将该队列插入到轮询表中,以响应poll()调用。sysfs代码无法知道,但是,任何给定sysfs属性的值何时更改,因此实现可轮询属性的子系统必须对以下内容进行显式调用:
void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
谢谢李
阻止民意调查来自用户方。用户代码可以简单地告诉内核它感兴趣的属性,然后将其阻塞poll()
直到其中一个被更改为止。
这sysfs_notify()
是一个释放用户空间的内核端调用poll()
。调整内核属性值之后,只需调用sysfs_notify()
以允许任何用户空间应用程序响应其未完成的请求poll()
。
可以将其poll()
视为“订阅”以关注感兴趣的属性的变化,并可以将sysfs_notify()
其“发布”给任何订户。
通过io的requestAbs方法调用/调用/使用REST API的vertx实现。vertx。果心http。vertx-core-3.2.0中的HttpClient类。jar导致HTTP错误::302,响应数据为HTML Erro响应。 不确定requestAbs方法的行为,因为没有引发异常,也没有写入任何日志。此外,还随附了使用vertx JAR的此方法的源代码。如果方法实现有bug,是否有问
我有以下要求 在Login.html页面-登录btn并忘记密码btn 如果登录btn点击, 应该完成用户名和pswd文本字段验证。 如果验证成功-调用LoginServlet 如果LoginServlet成功验证用户- 我正在努力寻找过去3天的解决方案,我已经推荐了SO和其他门户网站的帮助,但仍然缺乏最终输出 登录名。html LoginServlet
如果读者使用delphi(本文使用的是delphi2009,其他的delphi版本请读者自行测试)调用支持会话的WebService时有一些差别。经笔者测试,使用delphi调用WebService,将scope属性值设为transportsession和application都可以实现跨服务的会话管理,这一点和Java与C#不同,Java和C#必须将scope属性值设为application才支
从理论上说,WebService可以被任何支持SOAP协议的语言调用。在Visual Studio中使用C#调用WebService是在所有语言中最容易实现的(VB.net的调用方法类似,也同样很简单)。 新建一个Visual Studio工程,并在引用Web服务的对话框中输入如下的URL,并输入Web引用名为“WebService”: http://localhost:8080/axis2/se
Git 也提供了两个工具来辅助你调试项目中的问题。 由于 Git 被设计成适用于几乎所有类型的项目,这些工具是比较通用的,但它们可以在出现问题的时候帮助你找到 bug 或者错误。 文件标注 如果你在追踪代码中的一个 bug,并且想知道是什么时候以及为何会引入,文件标注通常是最好用的工具。 它展示了文件中每一行最后一次修改的提交。 所以,如果你在代码中看到一个有问题的方法,你可以使用 git bla
使用 XCode 调试 Debugging with XCode 为调试源代码生成Xcode项目(无法从Xcode构建代码) Run gn gen with the --ide=xcode argument. $ gn gen out/Debug --ide=xcode This will generate the electron.ninja.xcworkspace. You will have