pfa*_*fau 5 c linux-kernel sysfs
我的 raspi 内核模块是为了获得双光栅而编写的,如果两个输入 gpio\xc2\xb4s 边缘中的每一个都上升并且发生中断,则读取单调时间。时间值通过普通的 sysfs 文件传递到用户空间(而不是开发文件)。这很好用。
\n\n我的用户空间实现应该读取这些值并计算物体通过光栅的最终速度。目前,这个问题可以通过定期读取 sysfs 文件来解决。如果值发生变化,则会选取并使用新值。
\n\n为了节省资源,我想 poll() 相关 sysfs 文件上的 POLLPRI。在内核模块内部,sysfs_notify() 应该向用户空间提供相关 sysfs 文件的更改状态和值。
\n\n但是我在用户空间中的 poll() 永久阻塞。我也尝试将 POLLIN 作为事件。结果是 poll() 函数立即返回。
\n\n这是我的代码...
\n\n// [...]\n\nstatic struct kobject *gpio; // dir /sys/kernel/gpio\n\nstatic ssize_t gpio17s_show(struct kobject *kobj,struct kobj_attribute\n *attr,char *buf)\n{\n return sprintf(buf,"%li",sec1);\n}\n\nstatic ssize_t gpio17s_store(struct kobject *kobj,struct kobj_attribute\n *attr,const char *buf,size_t count)\n{\n sscanf(buf,"%li",&sec1);\n return count;\n}\n\n}\n\n// [...] (two more files)\n\nstatic ssize_t gpio26n_show(struct kobject *kobj,struct kobj_attribute\n *attr,char *buf)\n{\n sysfs_notify(gpio,NULL,"gpio26n"); // Is this the right place, the right invocation????\n // I saw this already in isr, but i believe this is not a good idea....\n // Has it perhaps to be in module_init function???\n // First arg(\'gpio\') is kobject of the dir containing files(attributes)..\n // This can not be right in my mind, but how do I find the right kobj??\n // The third param \'gpio26n\' if the file, on which I\'m polling.\n\n return sprintf(buf,"%li",nsec2);\n}\n\nstatic ssize_t gpio26n_store(struct kobject *kobj,struct kobj_attribute\n *attr,const char *buf,size_t count)\n{\n sscanf(buf,"%li",&nsec2);\n return count;\n}\n\nstatic int cleanup(int value,int ret) {\n\n switch(value) {\n case 5:\n free_irq(speed_irq2,NULL);\n case 4:\n free_irq(speed_irq1,NULL);\n case 3:\n gpio_free(PIN2);\n case 2:\n gpio_free(PIN1);\n case 1:\n kobject_put(gpio);\n }\n\n return ret;\n}\n\nstatic irqreturn_t speed_isr(int irq, void *data) {\n\n if(irq==speed_irq1) {\n getrawmonotonic(&ts1);\n sec1=ts1.tv_sec;\n nsec1=ts1.tv_nsec;\n }\n\n if(irq==speed_irq2) {\n getrawmonotonic(&ts2);\n sec2=ts2.tv_sec;\n nsec2=ts2.tv_nsec;\n }\n\n return IRQ_HANDLED;\n}\n\nstatic struct kobj_attribute gpio17s_attr = __ATTR(gpio17s,0644,\n gpio17s_show,gpio17s_store);\nstatic struct kobj_attribute gpio26n_attr = __ATTR(gpio26n,0644,\n gpio26n_show,gpio26n_store);\n\nstatic int __init d_init(void) {\n\n int ret=0;\n\n printk(KERN_INFO "Module successfully loaded...");\n\n gpio=kobject_create_and_add("gpio",kernel_kobj);\n if(!gpio) {\n printk(KERN_ERR "Failed to create \'gpio\'");\n return -ENOMEM;\n }\n\n ret=sysfs_create_file(gpio,&gpio17s_attr.attr);\n if(ret) {\n printk(KERN_ERR "Failed to create file \'gpio17s\'");\n return cleanup(1,2);\n }\n\n // [...] (two more files)\n\n ret=sysfs_create_file(gpio,&gpio26n_attr.attr);\n if(ret) {\n printk(KERN_ERR "Failed to create file \'gpio26n\'");\n return cleanup(1,5);\n }\n\n ret=gpio_request(PIN1,"gpio 17");\n if(ret) {\n printk(KERN_ERR "Failed to request \'gpio17\'");\n return cleanup(1,6);\n }\n\n ret=gpio_request(PIN2,"gpio 26");\n if(ret) {\n printk(KERN_ERR "Failed to request \'gpio26\'");\n return cleanup(2,7);\n }\n\n ret=gpio_to_irq(PIN1);\n if(ret<0) {\n printk(KERN_ERR "Unable to get irq for pin 17");\n return cleanup(3,8);\n }\n\n speed_irq1=ret;\n\n ret=gpio_to_irq(PIN2);\n if(ret<0) {\n printk(KERN_ERR "Unable to get irq for pin 26");\n return cleanup(3,9);\n }\n\n speed_irq2=ret;\n\n ret=request_irq(speed_irq1,speed_isr,IRQF_TRIGGER_RISING,\n "Speed trigger 17",NULL);\n if(ret) {\n printk(KERN_ERR "Unable to request irq for pin 17");\n return cleanup(3,10);\n }\n\n ret=request_irq(speed_irq2,speed_isr,IRQF_TRIGGER_RISING,\n "Speed trigger 26",NULL);\n if(ret) {\n printk(KERN_ERR "Unable to request irq for pin 26");\n return cleanup(4,10);\n }\n\n return 0;\n}\n\nstatic void __exit d_exit(void) {\n// [...]\n
Run Code Online (Sandbox Code Playgroud)\n\n和我的用户空间应用程序
\n\n// [...]\n\nint main() {\n\n int f ;\n char buf[16];\n struct pollfd pfd ;\n\n while(1) {\n memset(buf,0,sizeof(buf));\n\n if((f=open("/sys/kernel/gpio/gpio26n",O_RDONLY)) <0) {\n fprintf(stderr,"Failed to open sysfs file\\n");\n exit(1);\n }\n\n if((lseek(f,0L,SEEK_SET)) <0) {\n fprintf(stderr,"Failed to set pointer\\n");\n exit(2);\n }\n\n\n if((read(f,buf,1)) <0) {\n fprintf(stderr,"Failed to read from file\\n");\n exit(3);\n }\n\n pfd.fd = f ;\n pfd.events = POLLPRI;\n\n poll(&pfd,1,-1); // This should block until value has changed....\n close(f);\n\n\n // fopen, read new value etc.\n // [...]\n\n // Do some stuff, calculate speed, etc\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n问候普福
\n我放置 sysfs_notify() 函数是错误的。
在这种情况下,正确的位置是 ISR 内。
当中断发生时,ISR 被调用并通过 sysfs_notify() 通知用户空间新数据可读。poll() 解除阻塞并获取数据。
在我之前的星座中,用户空间 poll() 被阻止,直到调用 kobj_attribute show 函数。但只有从文件中读取数据时才会调用此函数。这意味着用户空间应用程序正在等待内核模块和签证 verce。
现在它工作正常。
这是我编辑的代码:
// [...]
static struct kobject *gpio; // dir /sys/kernel/gpio
static ssize_t gpio17s_show(struct kobject *kobj,struct kobj_attribute
*attr,char *buf)
{
return sprintf(buf,"%li",sec1);
}
static ssize_t gpio17s_store(struct kobject *kobj,struct kobj_attribute
*attr,const char *buf,size_t count)
{
sscanf(buf,"%li",&sec1);
return count;
}
}
// [...] (two more files)
static ssize_t gpio26n_show(struct kobject *kobj,struct kobj_attribute
*attr,char *buf)
{
return sprintf(buf,"%li",nsec2);
}
static ssize_t gpio26n_store(struct kobject *kobj,struct kobj_attribute
*attr,const char *buf,size_t count)
{
sscanf(buf,"%li",&nsec2);
return count;
}
static int cleanup(int value,int ret) {
switch(value) {
case 5:
free_irq(speed_irq2,NULL);
case 4:
free_irq(speed_irq1,NULL);
case 3:
gpio_free(PIN2);
case 2:
gpio_free(PIN1);
case 1:
kobject_put(gpio);
}
return ret;
}
static irqreturn_t speed_isr(int irq, void *data) {
if(irq==speed_irq1) {
getrawmonotonic(&ts1);
sec1=ts1.tv_sec;
nsec1=ts1.tv_nsec;
}
if(irq==speed_irq2) {
getrawmonotonic(&ts2);
sec2=ts2.tv_sec;
nsec2=ts2.tv_nsec;
sysfs_notify(gpio,NULL,"gpio26n"); // !! HERE IS THE RIGHT PLACE !!
}
return IRQ_HANDLED;
}
static struct kobj_attribute gpio17s_attr = __ATTR(gpio17s,0644,
gpio17s_show,gpio17s_store);
static struct kobj_attribute gpio26n_attr = __ATTR(gpio26n,0644,
gpio26n_show,gpio26n_store);
static int __init d_init(void) {
int ret=0;
printk(KERN_INFO "Module successfully loaded...");
gpio=kobject_create_and_add("gpio",kernel_kobj);
if(!gpio) {
printk(KERN_ERR "Failed to create 'gpio'");
return -ENOMEM;
}
ret=sysfs_create_file(gpio,&gpio17s_attr.attr);
if(ret) {
printk(KERN_ERR "Failed to create file 'gpio17s'");
return cleanup(1,2);
}
// [...] (two more files)
ret=sysfs_create_file(gpio,&gpio26n_attr.attr);
if(ret) {
printk(KERN_ERR "Failed to create file 'gpio26n'");
return cleanup(1,5);
}
ret=gpio_request(PIN1,"gpio 17");
if(ret) {
printk(KERN_ERR "Failed to request 'gpio17'");
return cleanup(1,6);
}
ret=gpio_request(PIN2,"gpio 26");
if(ret) {
printk(KERN_ERR "Failed to request 'gpio26'");
return cleanup(2,7);
}
ret=gpio_to_irq(PIN1);
if(ret<0) {
printk(KERN_ERR "Unable to get irq for pin 17");
return cleanup(3,8);
}
speed_irq1=ret;
ret=gpio_to_irq(PIN2);
if(ret<0) {
printk(KERN_ERR "Unable to get irq for pin 26");
return cleanup(3,9);
}
speed_irq2=ret;
ret=request_irq(speed_irq1,speed_isr,IRQF_TRIGGER_RISING,
"Speed trigger 17",NULL);
if(ret) {
printk(KERN_ERR "Unable to request irq for pin 17");
return cleanup(3,10);
}
ret=request_irq(speed_irq2,speed_isr,IRQF_TRIGGER_RISING,
"Speed trigger 26",NULL);
if(ret) {
printk(KERN_ERR "Unable to request irq for pin 26");
return cleanup(4,10);
}
return 0;
}
static void __exit d_exit(void) {
// [...]
Run Code Online (Sandbox Code Playgroud)
问候普福