2009-12-05 4 views
1

В пространстве ядра, я следующее:Копирование 2D-массива char * в пространство пользователя из пространства ядра?

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

Все указывает на строки с нулевым завершением. Действительно, myData представляет два значения, которые соответствуют друг другу. То есть он содержит пары myData [i] [0] и myData [i] [1], которые являются нисходящими строками. Я не боюсь потерять данные здесь, поэтому, если я могу скопировать весь блок памяти фиксированного размера, это нормально. –

+0

Я точно не понимаю, вы правильно определили новый системный вызов? copy_to_user копирует данные из указателя ядра в буфер пространства пользователя. –

+0

Где файлDataMap? Разве это не должно быть myData? – mrduclaw

ответ

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 струнно-пар, потому что в пользовательском пространстве нужно знать, сколько строк он ожидает чтобы они могли безопасно сканировать их. Если это не так, вам придется каким-то образом вернуть эту информацию - возможно, возвращаемое значение syscall может быть числом строк-пар?

Если вы хотите, чтобы ядро ​​восстанавливало таблицу указателей в пользовательском пространстве, вам нужно скопировать строки, как указано выше, а затем заполнить таблицу указателей - в пользовательском пространстве необходимо будет передать два буфера, один для самих строк и один для указателей.

Смежные вопросы