LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2746|回复: 2

内核空间和应用空间:get_user和put_user

[复制链接]
发表于 2008-12-10 23:58:16 | 显示全部楼层 |阅读模式
为什么内核空间读应用空间的数据要用get_user(),而传到应用空间要用put_user()这二个宏呢。查了很多书都没说明,书上只是说内核空间和应用空间不能直接读写,要通过这二个宏来实现(char,int,long类型的数),但没说明为什么,我看了这二个宏的ASM,实现也是通过间接地址实现的,内核空间在0XC0000000地址上面,应用空间在0XC0000000下面,为什么不能直接用直接用C语言的 *dst=*src 来实现呢,这点一直没弄明白。有那位兄弟指点一下我这个菜鸟。

   如下面这个装载a.out文件执行格式建立程序运行之前的堆栈的函数,在内核空间读用户空间的数据,又把它cp到用户空间去,为什么不能用 *dst = *src实现呢。

static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
{
        char **argv, **envp;
        unsigned long * sp;
        int argc = bprm->argc;
        int envc = bprm->envc;

        sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
#ifdef __sparc__
        /* This imposes the proper stack alignment for a new process. */
        sp = (unsigned long *) (((unsigned long) sp) & ~7);
        if ((envc+argc+3)&1) --sp;
#endif
#ifdef __alpha__
/* whee.. test-programs are so much fun. */
        put_user(0, --sp);
        put_user(0, --sp);
        if (bprm->loader) {
                put_user(0, --sp);
                put_user(0x3eb, --sp);
                put_user(bprm->loader, --sp);
                put_user(0x3ea, --sp);
        }
        put_user(bprm->exec, --sp);
        put_user(0x3e9, --sp);
#endif
        sp -= envc+1;
        envp = (char **) sp;
        sp -= argc+1;
        argv = (char **) sp;
#if defined(__i386__) || defined(__mc68000__) || defined(__arm__) || defined(__arch_um__)
        put_user((unsigned long) envp,--sp);
        put_user((unsigned long) argv,--sp);
#endif
        put_user(argc,--sp);
        current->mm->arg_start = (unsigned long) p;
        while (argc-->0) {
                char c;
                put_user(p,argv++);
                do {
                        get_user(c,p++);
                } while (c);
        }
        put_user(NULL,argv);
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
        while (envc-->0) {
                char c;
                put_user(p,envp++);
                do {
                        get_user(c,p++);
                } while (c);
        }
        put_user(NULL,envp);
        current->mm->env_end = (unsigned long) p;
        return sp;
}
发表于 2008-12-16 14:49:51 | 显示全部楼层
当使用swap机制的时候,内核访问的地址可能已经被换了出去,所以访问不到。
回复 支持 反对

使用道具 举报

发表于 2009-2-3 00:50:05 | 显示全部楼层
我觉得是因为内核和USER SPACE用的是不同的地址空间,他们的PAGE TABLE是不同的,所以用户空间的地址直接拿到KERNEL里面用是没有意义的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表