【问题标题】:How do I print a string from kernel buffer? Am I using copy_from_user() right?如何从内核缓冲区打印字符串?我使用 copy_from_user() 对吗?
【发布时间】:2012-04-06 12:18:21
【问题描述】:

嗨,我正在为我的字符驱动程序编写一个 write() 方法,我想知道为什么当我将数据从用户复制到我的内核缓冲区时,我的缓冲区包含随机的乱码。 Bellow是我正在使用的方法。

ssize_t dev_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp){// This function looks good
    struct my_char_structure *my_dev = filp->private_data;
    char *offset; // This points to my buffer
    size_t np, left_to_print = count; // These are the bytes left to write


//my_dev->set.write is a double pointer to a sentence where
//set.write = array[sentence number][character in sentence]
//set.write if set.write points to non-allocated memory, the sentence number is NULL
//My device only holds 100 sentences in all

    if(my_dev->set.write == NULL){// Write is a double pointer that points
        printk(KERN_ALERT "Device has no more room");
        return -ENOMEM; // Look up
    }


//you can ignore the commented out stuff but I want to check to see if I'm referencing
//a sentence that has been filled out. other wise the sentence is null and may be 
//written to. I will add this to my code later for traversing sentences.
    /*if(*(my_dev->set.write) != NULL){
        my_dev->set.write ++;
        dev_write(filp,buff,count,offp);
        exit 0;

    }*/

    if (down_interruptible(&my_dev->sem))
        return -ERESTARTSYS;

// Here I'm referencing a memory segment that acts as a pointer to a sentence which
//I write to. *(my_dev->set.write) is a pointer to a char buff which I will place chars
// which is essentially my string

    *(my_dev->set.write) = kmalloc(count,GFP_KERNEL);
    offset = *(my_dev->set.write); // my offset points to that buffer as well

//A sentence can only be the size of count, which is passed by the user
//thats why I allocate count bytes for memory.


        if((np = copy_from_user(offset,buff,left_to_print)) < 0)
            goto erro_out;

        left_to_print -= (count-np);
        offset += (count-np);
        offp += (count-np);

//For debbuging purposes I have printk(). My offset points to my buffer, however
//prints jibberish. In user space I insert \0 at the end of the string.

            printk(KERN_ALERT " 4 :: write && left is ... %ld. The string %s", left_to_print, offset); // %s prints jibberish

    return left_to_print; // change to count

    erro_out:// if there was an error I free the sentence so that it may be written to.

        kfree(*(my_dev->set.write));
        printk(KERN_ALERT "Print error %ld",np);
        return -EFAULT; // look this up
}

如果我的方法有点啰嗦,我的方法总结如下所示。这应该适合第一次写入设备。

ssize_t dev_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp){// This function looks good
    struct my_char_structure *my_dev = filp->private_data;
    static char *offset;

    if (down_interruptible(&my_dev->sem))
        return -ERESTARTSYS;

    *(my_dev->set.write) = kmalloc(count,GFP_KERNEL);
    offset = *(my_dev->set.write);

        if(copy_from_user(offset,buff,left_to_print) < 0)
            goto erro_out;

// This is my question, why does %s print jibberish

            printk(KERN_ALERT " 4 :: write && left is ... %ld. The string %s", left_to_print, offset); 

    return 0; // change to count

    erro_out:
        kfree(*(my_dev->set.write));
        printk(KERN_ALERT "Print error %ld",np);
        return -EFAULT; // look this up     
}

我使用 echo "my sentence">/dev/my_dev 写入我的设备。我不在乎 echo 是否有效。我只想让 printk() 显示“我的句子”,这意味着 copy_from 正在工作。我也尝试过使用 echo "my sentence\0">/dev/my_dev 来遵守在字符串末尾粘贴空字符的规则。

感谢您的帮助。

【问题讨论】:

    标签: c linux-kernel kernel driver linux-device-driver


    【解决方案1】:

    copy_from_user 的第一个参数需要一个目标地址。通过像这样传递偏移量:

        if((np = copy_from_user(offset,buff,left_to_print)) < 0)
    

    你给它写错了地址。你应该传递你的缓冲区,比如:

        if((np = copy_from_user(_my_buffer_ + offset,buff,left_to_print)) < 0)
    

    确保您分配了足够的空间,以便您可以将offset 添加到地址中,并注意我假设您的缓冲区是sizeof 评估为 1 的数据类型。

    【讨论】:

    • 感谢您抽出宝贵时间查看此内容。最初我设置偏移量 = start_of_buffer。我认为它具有误导性,因为我的偏移量不是真正的偏移量,而是我的起始地址。我这样做只是为了测试目的,但我会解决这个问题,因为你是对的而且它不在我的原始代码中。
    • ok,如果你memset(offset, 0, count),会显示垃圾吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多