put_user()
следует вызывать только в контексте процесса, выполняющего системный вызов.
Рассмотрим приложение, вызывающее ptrace(2)
(см. kernel/ptrace.c
).
Ядро вызовет вспомогательный для архитектуры ptrace
:
SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
unsigned long, data)
{
/* arch-independent code */
/* ... */
ret = arch_ptrace(child, request, addr, data);
На платформе x86 arch_ptrace()
определяется в arch/x86/kernel/ptrace.c
:
long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
int ret;
unsigned long __user *datap = (unsigned long __user *)data;
switch (request) {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
ret = -EIO;
if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
break;
tmp = 0; /* Default return condition */
if (addr < sizeof(struct user_regs_struct))
tmp = getreg(child, addr);
else if (addr >= offsetof(struct user, u_debugreg[0]) &&
addr <= offsetof(struct user, u_debugreg[7])) {
addr -= offsetof(struct user, u_debugreg[0]);
tmp = ptrace_get_debugreg(child, addr / sizeof(data));
}
ret = put_user(tmp, datap);
break;
}
Когда процесс вызывает ptrace(2)
и просит выполнить PTRACE_PEEKUSR
, ядру необходимо вернуть информацию (ret
) обратно пользователю. Ядро использует указатель datap
на предоставленный пользователем буфер , чтобы знать, куда в процессе записать значение tmp
.
Почти каждый случай вызова put_user()
будет инициирован процессом пользователя . Отправка сигналов в пользовательское пространство является очевидной разницей, когда ядро инициирует отправку сигнала, но у ядра есть код (см. arch/x86/kernel/signal.c
функция __setup_frame()
), чтобы найти кадр стека и записать в него необходимость обработки сигнала.
Итак, после долгого обсуждения: вы получите доступ к своим данным в своем процессе через из любого буфера, который вы дали ядру для записи в - это может быть буфер для конкретного драйвера ioctl(2)
, это может быть буферный аргумент для нового системного вызова, который вы создаете, у вас есть много вариантов.