C 唤醒后内核空指针取消引用\u可中断

C 唤醒后内核空指针取消引用\u可中断,c,linux,linux-kernel,linux-device-driver,kernel-module,C,Linux,Linux Kernel,Linux Device Driver,Kernel Module,我试图应用LDD3书中的一些例子。但是,当我向设备写入时,我的模块崩溃。调用进程被终止,崩溃是由唤醒可中断呼叫引起的。 我正在使用内核5.3.0-42-generic。 整个代码: 下面是代码: ssize_t device_write(struct file* fd, const char __user* buf, size_t size, loff_t* offset) { printk(KERN_INFO "MyLinuxModule: device is being wr

我试图应用LDD3书中的一些例子。但是,当我向设备写入时,我的模块崩溃。调用进程被终止,崩溃是由唤醒可中断呼叫引起的。 我正在使用内核5.3.0-42-generic。
整个代码:
下面是代码:

ssize_t device_write(struct file* fd, const char __user* buf, size_t size,
    loff_t* offset)
{
    printk(KERN_INFO "MyLinuxModule: device is being written to, fd=%X.\n", fd);
    struct device_info mydevice = charDevices[MINOR(fd->f_inode->i_rdev)];
    if (*offset > DEVICE_BLOCK_SIZE) // reached Max size
    {
        return 0;
    }
    int true_len = min(size, DEVICE_BLOCK_SIZE - *offset);
    if (mutex_lock_interruptible(&mydevice.my_mutex))
        return -ERESTARTSYS;
    copy_from_user(mydevice.data, buf, true_len);
    mydevice.max_data_avaliable += true_len;
    mutex_unlock(&mydevice.my_mutex);
    printk(KERN_INFO "MyLinuxModule: my_queue=%X.\n", &mydevice.my_queue);
    wake_up_interruptible(&mydevice.my_queue);
    *offset += true_len;
    return true_len;
}
int setup_cdevice(int index)
{
    char* device_message = "Hello from the other side\n";
    // initiate the cdev struct
    cdev_init(&charDevices[index].chardev, &myfops);
    // initiate the data
    charDevices[index].data = kmalloc(DEVICE_BLOCK_SIZE, GFP_KERNEL);
    memcpy(charDevices[index].data, device_message, strlen(device_message));
    // initiate the semaphore & queue
    mutex_init(&charDevices[index].my_mutex);
    init_waitqueue_head(&charDevices[index].my_queue);
    charDevices[index].max_data_avaliable = 0;
    int err = cdev_add(&charDevices[index].chardev,
        MKDEV(MAJOR(majMin), MINOR(majMin) + index), numOfDevices);
    if (err) {
        printk(KERN_INFO "MyLinuxModule: cdev_add Error : %X\n", err);
        return -1;
    }
    return 0;
}


您是如何填写我的设备。我的队列的?每个条目都有一个
func
成员,该成员由
\uuuu wake\u up\u common()
调用。我打赌这是空的。我建议您发布驱动程序的全部源代码,因为错误似乎存在于您没有向我们展示的代码中。我试图添加全部代码,但stackoveflow editor告诉我,我的帖子主要是代码,我需要更多解释。无论如何,我添加了设置等待队列的函数。您也可以发布一个链接。
setup\u cdevice
看起来不错,因为
init\u waitqueue\u head
func
成员初始化为
default\u wake\u函数
。但是您不在其他地方向队列添加条目吗?例如,在设备读取功能中,如果没有可用数据,是否将读取任务添加到队列中?我会检查代码。
struct device\u info mydevice=…
行创建设备结构的副本。但是,与许多其他同步原语一样,waitqueues不能被复制。但是,您可以通过将行更改为
struct device\u info*mydevice=&charDevices[MINOR(fd->f_inode->i_rdev)]来存储指向设备的指针。您是如何填写我的设备。我的队列的?每个条目都有一个
func
成员,该成员由
\uuuu wake\u up\u common()
调用。我打赌这是空的。我建议您发布驱动程序的全部源代码,因为错误似乎存在于您没有向我们展示的代码中。我试图添加全部代码,但stackoveflow editor告诉我,我的帖子主要是代码,我需要更多解释。无论如何,我添加了设置等待队列的函数。您也可以发布一个链接。
setup\u cdevice
看起来不错,因为
init\u waitqueue\u head
func
成员初始化为
default\u wake\u函数
。但是您不在其他地方向队列添加条目吗?例如,在设备读取功能中,如果没有可用数据,是否将读取任务添加到队列中?我会检查代码。
struct device\u info mydevice=…
行创建设备结构的副本。但是,与许多其他同步原语一样,waitqueues不能被复制。但是,您可以通过将行更改为
struct device\u info*mydevice=&charDevices[MINOR(fd->f_inode->i_rdev)]来存储指向设备的指针
[ 8952.921117] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 8952.921119] #PF: supervisor instruction fetch in kernel mode
[ 8952.921120] #PF: error_code(0x0010) - not-present page
[ 8952.921121] PGD 0 P4D 0 
[ 8952.921123] Oops: 0010 [#7] SMP PTI
[ 8952.921137] CPU: 3 PID: 14892 Comm: main Tainted: G      D    OE     5.3.0-42-generic #34~18.04.1-Ubuntu