微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么当我向虚拟字符设备写入字符时系统挂起?

如何解决为什么当我向虚拟字符设备写入字符时系统挂起?

我正在学习如何编写 Linux 设备驱动程序。
我写了一个虚拟字符设备驱动,实现了fops中的open、release、write、read;
当我从设备读取时,一切正常;
当我通过“echo xx >”写入设备时,操作系统挂起。
即使我注释掉了write函数中除了pr_alert和return语句之外的所有代码,它仍然挂起; 有人能帮我弄清楚吗?

#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/string.h>

struct hello_dev
{
    char *buffer;
    int length;
    dev_t dev;
    struct mutex lock;
    struct cdev *pcdev;
};

struct hello_dev *pHelloDev;

int open_device(struct inode *pinode,struct file *filp)
{

    filp->private_data = pHelloDev;

    return 0;
}

int close_device(struct inode *pinode,struct file *filp)
{
    struct hello_dev *pDev = filp->private_data;

    if (pDev->buffer != NULL)
        kfree(pDev->buffer);

    pDev->buffer = NULL;

    return 0;
}

ssize_t read_device(struct file *filp,char __user *buffer,size_t len,loff_t *loff)
{
    pr_alert("read\n");

    struct hello_dev *pDev = filp->private_data;

    mutex_lock(&pDev->lock);
    if (pDev->buffer == NULL)
    {
        mutex_unlock(&pDev->lock);
        return 0;
    }

    int length = strlen(pDev->buffer);

    // offset max than strlen in buffer,return
    if (*loff > (length - 1))
    {
        mutex_unlock(&pDev->lock);
        return 0;
    } else {

        // available to read
        int len2read = length - *loff;

        if (len < len2read)
        {// buffer length less than available data
            len2read = len;
        }

        int read = copy_to_user(buffer,pDev->buffer + *loff,len2read);
        if (read)
        {

            *loff = *loff + read;
            mutex_unlock(&pDev->lock);
            return read;
        } else {

            *loff = *loff + len2read;
            mutex_unlock(&pDev->lock);
            return len2read;
        }
    }
}

ssize_t write_device(struct file *filp,const char __user *buffer,loff_t* loff) {

    pr_alert("write %s\n",buffer);

    // struct hello_dev *pDev = filp->private_data;

    // mutex_lock(&pDev->lock);

    // if(pDev->buffer == NULL) {

    //  pDev->buffer = kmalloc(100,GFP_KERNEL);
    //  pDev->length = 100;
    // }

    // copy_from_user(pDev->buffer,buffer,len);

    // *loff = *loff + len;

    // mutex_unlock(&pDev->lock);

    return len;
}

struct file_operations fops = {
    .open = open_device,.release = close_device,.read = read_device,.write = write_device
};

int init_device(void)
{

    pr_alert("init device\n");

    pHelloDev = kmalloc(sizeof(struct hello_dev),GFP_KERNEL);
    pHelloDev->buffer = NULL;
    pHelloDev->length = 0;

    int ret = alloc_chrdev_region(&pHelloDev->dev,1,"hello");

    if (ret)
        goto alloc_error;

    if (pHelloDev == NULL)
        goto kmalloc_error;

    pHelloDev->pcdev = cdev_alloc();

    pHelloDev->pcdev->ops = &fops;

    mutex_init(&pHelloDev->lock);

    ret = cdev_add(pHelloDev->pcdev,pHelloDev->dev,1);

    if (ret)
        goto cdev_add_error;

    return 0;

alloc_error:
    pr_alert("alloc_chrdev_region error,%d\n",ret);
    return ret;

kmalloc_error:
    pr_alert("alloc struct hello_dev error");
    return -ENOMEM;

cdev_add_error:
    pr_alert("cdev_add error,ret);
    return ret;
}

void cleanup_device(void)
{

    pr_alert("unload ko\n");

    cdev_del(pHelloDev->pcdev);

    unregister_chrdev_region(pHelloDev->dev,1);
}

MODULE_LICENSE("GPL");

module_init(init_device);
module_exit(cleanup_device);

解决方法

我找到了写入设备挂起的原因。

 //this statements has problem
 //maybe there is no \0 in buffer
 //so I print it out,it will hang
 //I wrote a program to write something to device
 //and used strace to trace system call made by this program
 //and found it hangs at write(...) system call
 //and there was nothing printed out
 //so,it must be this statement causing the problem
 //when I removed this statement,everything was ok 
 pr_alert("write %s\n",buffer);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。