第二次在内核中读取会覆盖第一个实例

时间:2016-10-05 22:45:16

标签: c linux linux-kernel

我编写了一个读取函数来将文件读入内核空间的缓冲区。

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的内容读入secondbuffer。

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);

问题是在第二个文件上调用read函数后,我的firstbuffer的内容被第二个缓冲区的内容覆盖了。

例如:如果firstfile的内容是

A
B
C

和secondfile的内容是

X
Y
Z

然后在第一次读取文件调用后,firstbuffer的内容为:

A
B
C

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

A
X
Y
Z

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

声明:

我知道我们不应该在内核空间中进行文件I / O.这纯粹是为了了解读取函数在内核空间中的工作原理。

2 个答案:

答案 0 :(得分:1)

kmalloc(sizeof(PAGE_SIZE), GFP_KERNEL)

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

如果要分配PAGE_SIZE个字节,请使用:

kmalloc(PAGE_SIZE, GFP_KERNEL)

答案 1 :(得分:-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 bug。缺少错误检查,但我们假设它是为了简洁而被删除。

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

为什么要分配 PAGE_SIZE ,但是读取 len

// Null terminate read string

无用的评论。

firstbuffer[bytesread] = '\0';

如果bytesread == PAGE_SIZE,这是一个一个接一个。

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

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