Linux 通信内核模块和用户空间(驱动程序)

Linux 通信内核模块和用户空间(驱动程序),linux,linux-kernel,linux-device-driver,kernel-module,soc,Linux,Linux Kernel,Linux Device Driver,Kernel Module,Soc,我正在使用SoC FPGA。过去我一直在通过轮询测试一些外围设备,现在我想处理中断 我已经学习了一些教程,现在我有了一个可以检测IRQ 72中断的驱动程序。问题是,我想回复IRQ,我一直在尝试不同的事情,但似乎没有一件有效 最后一次尝试是关于一个C程序,它将执行逻辑部分,我的意思是,当内核告诉它存在中断时,它将执行一些操作。这个程序正在把它的PID写在一个文件中,我想让内核读取PID,向程序发送一个SIGUSR1信号,然后程序将执行smth 内核模块: #include <linux/mo

我正在使用SoC FPGA。过去我一直在通过轮询测试一些外围设备,现在我想处理中断

我已经学习了一些教程,现在我有了一个可以检测IRQ 72中断的驱动程序。问题是,我想回复IRQ,我一直在尝试不同的事情,但似乎没有一件有效

最后一次尝试是关于一个C程序,它将执行逻辑部分,我的意思是,当内核告诉它存在中断时,它将执行一些操作。这个程序正在把它的PID写在一个文件中,我想让内核读取PID,向程序发送一个SIGUSR1信号,然后程序将执行smth

内核模块:

#include <linux/module.h>  // Needed by all modules
#include <linux/kernel.h>  // Needed for KERN_INFO
#include <linux/fs.h>      // Needed by filp
#include <asm/uaccess.h>   // Needed by segment descriptors
#include <linux/init.h>   /*Needed for the macros*/
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>

#define DEVNAME "test_int"

static irq_handler_t __test_isr(int irq, void *dev_id, struct pt_regs *regs){
    printk (KERN_INFO DEVNAME ": ISR\n");
    return (irq_handler_t) IRQ_HANDLED;
}

static int __test_int_driver_probe(struct platform_device* pdev){
    // Create variables
    struct file *f;
    char buf[128];
    mm_segment_t fs;
    int i;
    // Init the buffer with 0
    for(i=0;i<128;i++)
        buf[i] = 0;

    // PID file
    // It is an inteer, so i guess 4Bytes would be better
    f = filp_open("/home/root/modInt/miPID", O_RDONLY, 0);
    if(f == NULL)
        printk(KERN_ALERT "filp_open error!!.\n");
    else{
        // Get current segment descriptor
        fs = get_fs();
        // Set segment descriptor associated to kernel space
        set_fs(get_ds());
        // Read the file
        f->f_op->read(f, buf, 128, &f->f_pos);
        // Restore segment descriptor
        set_fs(fs);
        // See what we read from file
        printk("El PID es buf:%s\n",buf);
    }
    filp_close(f,NULL);
    int irq_num;
    irq_num = platform_get_irq(pdev, 0);
    printk(KERN_INFO DEVNAME ": La IRQ %d va a ser registrada!\n", irq_num);
    return request_irq(irq_num, (irq_handler_t) __test_isr, 0, DEVNAME, NULL);
}

static int __test_int_driver_remove (struct platform_device *pdev){
    int irq_num;
    irq_num = platform_get_irq (pdev, 0);
    printk(KERN_INFO "test_int: Abandonando la captura de la IRQ %d !\n", irq_num);
    free_irq(irq_num, NULL);
    return 0;
}

static const struct of_device_id __test_int_driver_id[] = {
    {.compatible = "altr , socfpga-mysoftip"},
    {}
};

static struct platform_driver __test_int_driver = {
    .driver= {
        .name = DEVNAME,
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr (__test_int_driver_id),
    },
    .probe = __test_int_driver_probe,
    .remove = __test_int_driver_remove
};

module_platform_driver (__test_int_driver);

MODULE_LICENSE("GPL");
我必须补充一点

ret = kernel_read(fp, offset, buf, 512);
为什么这是-22

printk("The PID is: %s", buf);
如果我打印这个,那么答案是:▒▒▒8A▒▒�@

printk("The PID is: %s", *buf);
如果把这个放进去,指针就会返回null


我做错了什么?

首先,不应该用NULL检查filp_open的返回值。您应该使用IS\u ERR检查调用是否成功

我相信打开的文件返回了一个错误指针,您正在尝试取消引用它

f->f_op->read(f, buf, 128, &f->f_pos);

或者,您可以使用addr2line查找导致内核死机的行

欢迎使用stackoverflow。你的问题需要进一步澄清。为什么要使用中断。确切地说,您希望向用户空间发送哪些数据以及发送哪些事件。清楚地解释一下方法。除此之外,只要考虑一下你文章标题中的问题,你就可以简单地使用一个角色驱动程序来完成这个交流。在驱动程序中使用filp是为了解决各种各样的问题。这个想法很糟糕,需要重新思考。我使用中断是因为我正在使用Altera Cyclone V SoC,我想了解它的不同选项。此外,FPGA必须具有快速响应,并且,由于我希望它在集成ARM处理器中进行一些操作,我希望测试这两种方法,轮询和中断。我也在测量投票的时间,我也想用中断来测量@0andriy,我是内核模块编程的乞丐。我将阅读有关filp命令的评论,但是。。。你建议做什么?我的意思是,你要求我重新思考,但我看不到更多的选项来与它们通信有很多内核用户空间机制来通信:固件加载程序、sysfs、IOCTL等等。。。您的选择应取决于您希望拥有的案例和最合适的数据和通信格式。filp是简单的no-go。此外,代码调用filp_closef,NULL;即使f是无效的。
printk("The PID is: %s", buf);
printk("The PID is: %s", *buf);
if (IS_ERR(f)) {
    pr_err("Error opening file")
}
f->f_op->read(f, buf, 128, &f->f_pos);