如何从内核缓冲区打印字符串?我正在使用copy_from_user()对吗?

如何从内核缓冲区打印字符串?我正在使用copy_from_user()对吗?,c,linux-kernel,kernel,driver,linux-device-driver,C,Linux Kernel,Kernel,Driver,Linux Device Driver,大家好,我正在为我的角色驱动程序编写一个write()方法,我想知道为什么当我将数据从用户复制到内核缓冲区时,缓冲区包含随机jibberish。下面是我正在使用的方法 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->

大家好,我正在为我的角色驱动程序编写一个write()方法,我想知道为什么当我将数据从用户复制到内核缓冲区时,缓冲区包含随机jibberish。下面是我正在使用的方法

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\u t dev\u write(结构文件*filp,常量字符*user*buff,大小计数,loff\u t*offp){//此函数看起来不错
struct my\u char\u structure*my\u dev=filp->private\u data;
char*offset;//这指向我的缓冲区
size\u t np,left\u to\u print=count;//这些是要写入的剩余字节
//my_dev->set.write是指向以下句子的双指针:
//set.write=数组[句子编号][句子中的字符]
//set.write如果set.write指向未分配的内存,则句子编号为空
//我的设备总共只能容纳100个句子
如果(my_dev->set.write==NULL){//write是指向
printk(KERN_ALERT“设备没有更多空间”);
return-ENOMEM;//查找
}
//你可以忽略注释掉的东西,但我想检查一下我是否引用了
//一个已经填好的句子。另一方面,这个句子是空的,可能是空的
//我将在以后的代码中添加此代码以遍历句子。
/*if(*(my_dev->set.write)!=NULL){
my_dev->set.write++;
开发写入(filp、buff、count、offp);
出口0;
}*/
if(向下可中断(&my\u dev->sem))
返回-ERESTARTSYS;
//这里我引用了一个内存段,它充当指向一个句子的指针
//我写入。*(my_dev->set.write)是指向我将放置字符的字符buff的指针
//这基本上是我的字符串
*(my_dev->set.write)=kmalloc(计数,GFP_内核);
offset=*(my_dev->set.write);//我的偏移量也指向该缓冲区
//一个句子只能是count的大小,由用户传递
//这就是我为内存分配计数字节的原因。
如果((np=从用户复制(偏移、缓冲、左向打印))<0)
去埃罗_了;
左至右打印-=(计数np);
偏移量+=(计数np);
offp+=(计数np);
//为了消除错误,我有printk()。但是,我的偏移量指向缓冲区
//打印jibberish。在用户空间中,我在字符串末尾插入\0。
printk(KERN_ALERT“4::write&&left是…%ld。字符串%s”,left_to_print,offset);//%s打印jibberish
返回左\u到\u打印;//更改为计数
erro_out://如果有错误,我将释放句子,以便将其写入。
kfree(*(my_dev->set.write));
printk(内核警报“打印错误%ld”,np);
return-EFAULT;//查找这个
}
如果我的方法有点迂回,下面将对我的方法进行总结。这对于第一次写入设备应该很好

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     
}
ssize\u t dev\u write(结构文件*filp,常量字符*user*buff,大小计数,loff\u t*offp){//此函数看起来不错
struct my\u char\u structure*my\u dev=filp->private\u data;
静态字符*偏移量;
if(向下可中断(&my\u dev->sem))
返回-ERESTARTSYS;
*(my_dev->set.write)=kmalloc(计数,GFP_内核);
偏移量=*(my_dev->set.write);
if(从用户处复制(偏移、缓冲、左打印)<0)
去埃罗_了;
//这是我的问题,为什么%s打印jibberish
printk(KERN_ALERT“4::write&&left是…%ld.字符串%s”,left_to_print,offset);
返回0;//更改为计数
错误:
kfree(*(my_dev->set.write));
printk(内核警报“打印错误%ld”,np);
return-EFAULT;//查找这个
}
我使用echo“我的句子”>/dev/my_dev向我的设备写入内容。我不在乎echo是否有效。我只希望printk()显示“我的句子”,这意味着copy_from正在工作。此外,我还尝试使用echo“my Session\0”>/dev/my_dev遵守在字符串末尾粘贴空字符的规则


感谢您的帮助。

从用户复制的第一个参数需要一个目标地址。通过如下方式传递偏移量:

    if((np = copy_from_user(offset,buff,left_to_print)) < 0)
if((np=copy_from_user(offset,buff,left_to_print))<0)
你给它的地址不对。您应该传递缓冲区,如:

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

请确保分配了足够的空间,以便可以将
偏移量
添加到地址,并注意,我假设缓冲区的数据类型
sizeof
的计算结果为1。

从用户复制的第一个参数需要一个目标地址。通过如下方式传递偏移量:

    if((np = copy_from_user(offset,buff,left_to_print)) < 0)
if((np=copy_from_user(offset,buff,left_to_print))<0)
你给它的地址不对。您应该传递缓冲区,如:

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

请确保分配了足够的空间,以便可以将
偏移量
添加到地址中,并注意,我假设您的缓冲区属于
sizeof
计算结果为1的数据类型。

感谢您花时间查看此内容。最初我设置偏移量=缓冲区的开始。我想这是一种误导,因为我的偏移量实际上不是我的偏移量,而是我的起始地址。我这样做只是为了测试,但我会修正,因为你是对的,它不在我的原始代码中。好的,如果你做
memset(offset,0,count)
,会显示垃圾吗?谢谢你花时间看这个。最初我设置偏移量=缓冲区的开始。我想这是一种误导,因为我的偏移量实际上不是我的偏移量,而是我的起始地址。我这样做只是为了测试,但我会修正,因为你是对的,它不在我的原始代码中。好的,如果你做
memset(offset,0,count)
,会显示垃圾吗?