Копирование 2D массива char * в пространство пользователя из пространства ядра? - PullRequest
1 голос
/ 06 декабря 2009

В пространстве ядра у меня есть следующее:

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 Ответ

2 голосов
/ 06 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...