从内核空间将char *的2D数组复制到用户空间?

时间:2009-12-05 22:14:28

标签: c linux-kernel

在内核空间中,我有以下内容:

char * myData[MAX_BUF_SIZE][2];

我需要定义一个将这些数据复制到用户空间的内核方法。那么我该如何定义这个方法呢?我有以下内容,但我不太清楚我在做什么。

asmlinkage int sys_get_my_data(char __user ***data, int rowLen, int bufferSize) {
    if (rowLen < 1 || bufferSize < 1 || rowLen > MAX_BUF_SIZE || bufferSize
            > MAX_BUF_SIZE) {
        return -1;
    }

    if( copy_to_user( data, myData, rowLen * bufferSize * dataCounter * 2) )
    {
        printk( KERN_EMERG "Copy to user failure for get all minifiles\n" );
        return -1;
    }

    return 0;
}

帮助?

1 个答案:

答案 0 :(得分:2)

根据您的评论,这些char *值指向以空字符结尾的字符串。

现在,您不能只将整个fileDataMap内存块复制到用户空间 - 这只会为用户空间提供一堆指向内核空间的char *值,因此它不会实际上可以使用它们。您需要将字符串本身复制到用户空间,而不仅仅是指针(这是“深层复制”)。

现在,有几种方法可以解决这个问题。最简单的方法是将所有字符串一个接一个地打包到用户空间中的大char数组中。然后由用户空间扫描整个块,重建指针:

asmlinkage int sys_get_my_data(char __user *data, size_t bufferSize)
{
    size_t i;

    for (i = 0; i < MAX_BUF_SIZE; i++) {
        size_t s0_len = strlen(fileDataMap[i][0]) + 1;
        size_t s1_len = strlen(fileDataMap[i][1]) + 1;

        if (s0_len + s1_len > bufferSize) {
            return -ENOSPC;
        }

        if (copy_to_user(data, fileDataMap[i][0], s0_len)) {
            return -EINVAL;
        }

        data += s0_len;
        bufferSize -= s0_len;

        if (copy_to_user(data, fileDataMap[i][1], s1_len)) {
            return -EINVAL;
        }

        data += s1_len;
        bufferSize -= s1_len;
    }

    return 0;
}

这只有在总是 MAX_BUF_SIZE字符串对时才有效,因为用户空间需要知道它希望接收多少字符串才能安全扫描他们。如果不是这样的话,你必须以某种方式返回那些信息 - 也许系统调用的返回值可能是字符串对的数量?

如果你想让内核重建用户空间中的指针表,你必须复制上面的字符串,然后填写指针表 - 用户空间必须传递两个缓冲区,一个用于字符串本身,一个对于指针。