内核空间和应用空间:get_user和put_user
时间:2008-12-11
来源:互联网
为什么内核空间读应用空间的数据要用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;
}
如下面这个装载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;
}
作者: qiaoye95 发布时间: 2008-12-11
当使用swap机制的时候,内核访问的地址可能已经被换了出去,所以访问不到。
作者: hanchao3c 发布时间: 2008-12-16
我觉得是因为内核和USER SPACE用的是不同的地址空间,他们的PAGE TABLE是不同的,所以用户空间的地址直接拿到KERNEL里面用是没有意义的。
作者: zephyr.zhao 发布时间: 2009-02-03
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28