在内核空间中,我有以下内容:
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;
}
帮助?
答案 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
字符串对时才有效,因为用户空间需要知道它希望接收多少字符串才能安全扫描他们。如果不是这样的话,你必须以某种方式返回那些信息 - 也许系统调用的返回值可能是字符串对的数量?
如果你想让内核重建用户空间中的指针表,你必须复制上面的字符串,然后填写指针表 - 用户空间必须传递两个缓冲区,一个用于字符串本身,一个对于指针。