2016-10-05 71 views
1

我已经写入了一个读取函数来在内核空间中将文件读入缓冲区。第二次读取内核会覆盖第一个实例

int readfile(const char *filename, void *buf, int len, int offset) 
{ 
    struct file *filp; 
    mm_segment_t oldfs; 
    int bytes; 
    filp = NULL; 
    filp = filp_open(filename, O_RDONLY, 0); 
    if(!filp || IS_ERR(filp)) { 
     printk(" Error in reading file %s. Error = %d\n", filename, \ 
       (int) PTR_ERR(filp)); 
     return -1; 
    } 
    filp->f_pos = offset; 
    oldfs = get_fs(); 
    set_fs(get_ds()); 
    bytes = vfs_read(filp, buf, len, &filp->f_pos); 
    set_fs(oldfs); 
    filp_close(filp, NULL); 
    return bytes; 
} 

现在,这个功能确实很好,我能够读取文件名保存到buf的内容从我的系统调用

char *firstbuffer; 
firstbuffer = kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL); 

bytesread = readfile(firstfile, firstbuffer, len, 0); 

// Null terminate read string 
firstbuffer[bytesread] = '\0'; 
printk("first buffer = %s\n",firstbuffer); 

然后调用这个函数,我再次调用此函数读取secondfile的内容转换为第二缓冲区。

char *secondbuffer; 
secondbuffer = kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL); 
bytesread2 = readfile(secondfile, secondbuffer, len, 0); 
// Null terminate read string 
secondbuffer[bytesread2] = '\0'; 
printk("second buffer %s", secondbuffer); 

的问题是,呼吁secondfile读功能之后,我firstbuffer的内容越来越与secondbuffer的内容覆盖。

例如:如果firstfile的内容是

A 
B 
C 

和secondfile的内容是

X 
Y 
Z 

然后第一读取文件调用后,firstbuffer的含量为:

A 
B 
C 

然后在第二次读文件调用后,firstbuffer的内容是:

A 
X 
Y 
Z 

现在,我不确定这里出了什么问题,但是在第二次读取函数调用后,firstbuffer的内容与第二缓冲区的内容合并。我该如何解决?

免责声明:

我知道我们不应该做的文件I/O在内核空间。这纯粹是为了学习读取函数如何在内核空间中工作。

+0

你可以打印'firstbuffer'和'secondbuffer'的值吗?例如,'printf(“1:%p \ n2:%p \ n”,firstbuffer,secondbuffer);' – jxh

+0

@jxh:是的,我可以打印它们的值。使用printk(“%s \ n,firstbuffer)和printk(”%s \ n,secondbuffer)来做到这一点 – Piyush

+0

@JohnKugelman:完成。增加了mcv的例子。 – Piyush

回答

1
kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL) 

这个分配sizeof(PAGE_SIZE)字节。现在,PAGE_SIZE是一个整数,所以它可能是4个字节长,所以你分配4个字节。

如果你想分配PAGE_SIZE字节,使用方法:

kmalloc(PAGE_SIZE, GFP_KERNEL) 
+0

啊,非常感谢你。这解决了这个问题。多么愚蠢的错误。现在,我甚至不确定该计划如何工作。我确信我一直在写超过4个字节。无论如何,再次感谢@immibis – Piyush

+1

@Piyush分配4个字节意味着4个字节为您保留,但这并不意味着只有4个字节存在。您可以在保留4个字节后写入,然后写入其他人的内存或未使用的内存。 – immibis

-1
int readfile(const char *filename, void *buf, int len, int offset) 
{ 
    struct file *filp; 
    mm_segment_t oldfs; 
    int bytes; 
    filp = NULL; 

为什么?这是立即覆盖下面的行。

filp = filp_open(filename, O_RDONLY, 0); 
    if(!filp || IS_ERR(filp)) { 

filp_open不会返回NULL。

 printk(" Error in reading file %s. Error = %d\n", filename, \ 
       (int) PTR_ERR(filp)); 

缺少日志级别(例如KERN_WARNING)。坏消息,它表明实际读取失败。 PTR_ERR已经返回一个int。

 return -1; 

为什么返回-1而不是PTR_ERR(filp)?

} 
    filp->f_pos = offset; 

现在这是一个奇怪的滥用。为什么你在文件对象中设置了f_pos?如果你像pread一样检查消费者,你会看到你应该有一个专门的偏移量变量,并离开该领域独自一人。

oldfs = get_fs(); 
    set_fs(get_ds()); 
    bytes = vfs_read(filp, buf, len, &filp->f_pos); 
    set_fs(oldfs); 
    filp_close(filp, NULL); 
    return bytes; 
} 

现在的另一部分:

char *firstbuffer; 
firstbuffer = kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL); 

sizeof运算错误已经提到。缺少错误检查,但为了简洁起见,我们假设它已被切断。

bytesread = readfile(firstfile, firstbuffer, len, 0); 

为什么你分配PAGE_SIZE,但读len个

// Null terminate read string 

无用评论。

firstbuffer[bytesread] = '\0'; 

这是一个off-by-one if bytesread == PAGE_SIZE。

printk("first buffer = %s\n",firstbuffer); 
[snip] 
printk("second buffer %s", secondbuffer); 

错误的调试printfs。如果你需要转储这些东西,你应该以某种方式将它包含在内。 “[%S]”。缺少firstbuffer之前的空间。信息不一致 - 一个有“=”,而另一个没有。

相关问题