put_user() linux 内核

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5536486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:30:24  来源:igfitidea点击:

put_user() linux kernel

linuxlinux-kernelkernel

提问by Pawan

After doing put_user(message[i], buf+i);how can I access message from user space?

完成后put_user(message[i], buf+i);如何从用户空间访问消息?

I really don't understand where the string message is to be accessed from and what I can do with it?

我真的不明白从哪里访问字符串消息以及我可以用它做什么?

采纳答案by ZelluX

put_user (x, ptr). Here xis the value to copy to user space, while ptris the destination address, in user space.

put_user (x, ptr). 这里x是复制到用户空间的值,ptr而是用户空间中的目标地址。

So in user application the message can be accessed by buf+i.

因此,在用户应用程序中,可以通过buf+i.

回答by sarnold

put_user()should only be called in the context of a process making a system call.

put_user()应该只在进行系统调用的进程的上下文中调用。

Consider an application calling ptrace(2)(see kernel/ptrace.c).

考虑一个应用程序调用ptrace(2)(请参阅 参考资料kernel/ptrace.c)。

The kernel will call into an architecture-specific ptracehelper:

内核将调用特定于体系结构的ptrace帮助程序:

SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
            unsigned long, data) 
{
    /* arch-independent code */
    /* ... */
    ret = arch_ptrace(child, request, addr, data);

On the x86 platform, arch_ptrace()is defined in arch/x86/kernel/ptrace.c:

在 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;
    }

When a process calls ptrace(2)and asks to perform a PTRACE_PEEKUSR, the kernel needs to return information (ret) back to the user. The kernel uses the datappointer to a user supplied bufferto know where in the process to write the value of tmp.

当进程调用ptrace(2)并要求执行 a 时PTRACE_PEEKUSR,内核需要将信息 ( ret) 返回给用户。内核使用datap指向用户提供的缓冲区的指针来知道在进程中的何处写入 的值tmp

Almost every case of calling put_user()will be initiated by a userland process. Sending signals to userspace is an obvious difference, where the kernel initiates sending the signal, but the kernel has code (see arch/x86/kernel/signal.cfunction __setup_frame()) to find the stack frame and write into it the need to handle a signal.

几乎所有的调用情况put_user()都会由用户态进程发起。向用户空间发送信号是一个明显的区别,内核开始发送信号,但内核有代码(见arch/x86/kernel/signal.c函数__setup_frame())来查找堆栈帧并将处理信号的需要写入其中。

So, after a long-winded discussion: You will access your data in your process via whatever buffer you gave to the kernel to write into-- it could be a buffer for a driver-specific ioctl(2), it could be a buffer argument to a new system call you create, you have a lot of choices.

因此,经过冗长的讨论:您将通过给内核写入的任何缓冲区访问进程中的数据——它可以是特定于驱动程序的缓冲区ioctl(2),也可以是新的缓冲区参数您创建的系统调用,您有很多选择。