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