#memory-management #linux-kernel #kernel
#управление памятью #linux-ядро #ядро
Вопрос:
Допустим, у меня есть данные пользовательского контекста, хранящиеся в указателе памяти ядра. Скажем, у меня также есть указатель на символ пользовательского пространства *. Затем я создаю поток ядра, и поток ядра может иметь эти два указателя. Могу ли я из потока получить доступ к данным пользовательского пространства с помощью указателя? Я могу получить к ним доступ в системном вызове, но вопрос в том, могу ли я получить к ним доступ из потока ядра? Как насчет доступа к ним из рабочей очереди?
Скажем, мой пользовательский процесс вызывает системный вызов
//User Application
char* abc = "This is data.";
syscall(340, p);
в обработчике системного вызова
void sys_340(void* p) {
th = kthread_run("kth", kt_func, p);
//might also store process context as I am in system call!! How?
}
void kt_func(void *p) {
while(1){ printk("Line: %sn",p); sleep(1000); }
}
Я хочу, чтобы kt_func печатал «Это данные» каждые 1 секунду.
Ответ №1:
Потоки ядра могут обращаться к любой части памяти пользовательского пространства (при условии, что у них есть соответствующий указатель на нее). Поскольку ваш код предполагает, что в рамках системного вызова вы хотите запустить новый поток ядра и позволить ему печатать что-то каждые 1 секунду. Я предполагаю, что после создания потока ядра вы вернетесь из системного вызова. Проблема здесь заключается в следующем: после возврата из системного вызова пользовательский процесс также может получить доступ к памяти, на которую указывает p, и поток ядра также может получить к ней доступ. Как бы вы обеспечили доступ к синхронизации указателя p? (Возможно, через другой системный вызов).
Хотя я не вижу ни одного варианта использования того, что вы делаете?
Комментарии:
1. Давайте забудем о проблеме синхронизации. Проблема в том, что после возврата системного вызова в ядро я больше не получаю правильное значение, указанное p. p — это виртуальный адрес пользовательского пространства, который может быть преобразован в физический адрес с использованием контекста процессора. Потоки ядра выполняются в другом контексте процессора. Поэтому, просто используя * p, я не могу получить доступ к значению. Мой вопрос в том, как я могу получить доступ к значению при условии, что я могу сохранить текущий указатель task_struct процесса вместе с указателем p.
Ответ №2:
В вашем обработчике системного вызова вы могли бы сделать что-то вроде
struct mm_struct *mm = get_task_mm(current);
чтобы скрыть отображение памяти процесса, выполняющего системный вызов. Затем позже в вашем потоке ядра вы можете сделать что-то вроде
access_remote_vm(mm, p, my_kernel_buf, length, 0);
для выполнения эквивалента copy_from_user()
в памяти исходной задачи.
Комментарии:
1. Это именно мой вопрос. Как сделать access_remote_vm. Существует ли какая-либо конкретная реализация в ядре 2.6?
2. Не уверен, что вы имеете в виду: да,
access_remote_vm()
в ядре 2.6 есть функция, которую вы можете вызвать.3. Извините, я искал функцию access_remote_vm в LXR для 2.6.38 и не смог ее найти. Но теперь я нашел функцию access_remote_vm в LXR для 2.6.39. Попробую это.