C 使用“复制到用户”计时器处理程序函数失败,为什么?

C 使用“复制到用户”计时器处理程序函数失败,为什么?,c,linux-kernel,copy,C,Linux Kernel,Copy,如果我在ioctl函数中使用copy_to_user,我可以将数据复制到用户空间,但是如果我将copy_to_user放入超时处理程序函数中,那么copy_to_user将无法成功。为什么? #include <linux/init.h> ... #define GLOBAL_MEMSIZE 0x1000//4K ... static struct timer_list mytimer; ... typedef struc

如果我在ioctl函数中使用copy_to_user,我可以将数据复制到用户空间,但是如果我将copy_to_user放入超时处理程序函数中,那么copy_to_user将无法成功。为什么?

    #include <linux/init.h>
    ...

    #define  GLOBAL_MEMSIZE 0x1000//4K
    ...
    static struct timer_list mytimer;
    ...

    typedef struct globalmem_dev{
        struct cdev cdev;
        unsigned char mem[GLOBAL_MEMSIZE];
    } Glo_dev, *Pglo_dev;

    Pglo_dev globalmem_devp;//global pointer
在ioctl函数中,copy_to_用户可以正常工作

    /*ioctl*/
    static long int globalmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {

        /*if(copy_to_user((void __user *)arg, globlmem_devp->mem, 8))
        {
             printk("copy_to_user fial\n");
        }*/
        setup_timer(&mytimer, timer_func, arg);
        mytimer.expires = jiffies + HZ;
        add_timer(&mytimer);

        return 0;
    }

    static struct file_operations hello_ops = {
        ...
    };

    /*init function*/
    static int __init hello_init(void)
    {
        ...
        globalmem_devp = kmalloc(sizeof(Glo_dev), GFP_KERNEL);//
        if(NULL == globalmem_devp)
        {
            return -ENOMEM; 
        }
        ...
        return 0;
    }        

    static void  __exit hello_exit(void)
    {
        ...
    }

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("test");

    module_init(hello_init);
    module_exit(hello_exit);
copy_to_user将数据复制到当前用户空间进程的内存中,因此它只能用于从该进程调用的某些代码中

中断处理程序可以随时运行,因此可能没有当前进程,或者更糟糕的是,当前进程是其他进程。

此外,复制到用户可以睡眠,这在中断处理程序中是不允许的。
    /*ioctl*/
    static long int globalmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {

        /*if(copy_to_user((void __user *)arg, globlmem_devp->mem, 8))
        {
             printk("copy_to_user fial\n");
        }*/
        setup_timer(&mytimer, timer_func, arg);
        mytimer.expires = jiffies + HZ;
        add_timer(&mytimer);

        return 0;
    }

    static struct file_operations hello_ops = {
        ...
    };

    /*init function*/
    static int __init hello_init(void)
    {
        ...
        globalmem_devp = kmalloc(sizeof(Glo_dev), GFP_KERNEL);//
        if(NULL == globalmem_devp)
        {
            return -ENOMEM; 
        }
        ...
        return 0;
    }        

    static void  __exit hello_exit(void)
    {
        ...
    }

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("test");

    module_init(hello_init);
    module_exit(hello_exit);