LinuxSir.cn,穿越时空的Linuxsir!

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

请问各位哥们 系统调用进入内核执行sys_*时,sys_*是怎样从寄存器中取得从用户态传来

[复制链接]
发表于 2005-5-11 09:29:16 | 显示全部楼层 |阅读模式
如题  一直不太理解sys_*是怎样从寄存器中取得参数的   用户态下发出的系统调用通过宏syscallN将参数传入寄存器中 但在进入内核后执行sys_*时 好像不能从sys_*中看出它是从寄存器中取得参数的  望大哥能否结合实例说明一下  不胜感激
发表于 2005-5-11 17:40:56 | 显示全部楼层
84 #define SAVE_ALL \
     85     cld; \
     86     pushl %es; \
     87     pushl %ds; \
     88     pushl %eax; \
     89     pushl %ebp; \
     90     pushl %edi; \
     91     pushl %esi; \
     92     pushl %edx; \
     93     pushl %ecx; \
     94     pushl %ebx; \
     95     movl $(__USER_DS), %edx; \
     96     movl %edx, %ds; \
     97     movl %edx, %es;

如果是一个参数,应该放在ebx,如果有两个,应该放在ecx和ebx,......
如下:
    324 #define _syscall1(type,name,type1,arg1) \
    325 type name(type1 arg1) \
    326 { \
    327 long __res; \
    328 __asm__ volatile ("int $0x80" \
    329     : "=a" (__res) \
    330     : "0" (__NR_##name),"b" ((long)(arg1))); \
    331 __syscall_return(type,__res); \
    332 }
    333
    334 #define _syscall2(type,name,type1,arg1,type2,arg2) \
    335 type name(type1 arg1,type2 arg2) \
    336 { \
    337 long __res; \
    338 __asm__ volatile ("int $0x80" \
    339     : "=a" (__res) \
    340     : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
    341 __syscall_return(type,__res); \
    342 }
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-11 23:28:43 | 显示全部楼层
谢谢楼上哥们回复 我想也许是我表述不够清楚吧 楼上哥们讲的是系统调用参数是怎样从用户态通过宏syscallN传入寄存器中从而进入内核 可本人想知道的是在已完成了这一步工作 参数已进入了寄存器中 系统正在执行sys_*(比如sys_open)时 sys_*(比如sys_open)是怎样从寄存器中取得参数的  在sys_*(比如sys_open)的代码中本人找不到从寄存器中拿参数的相关语句  问题也就正在这了  不知表述清了没 谢谢哥们回复
回复 支持 反对

使用道具 举报

发表于 2005-5-12 11:28:45 | 显示全部楼层
我想也许我忘了做解释吧 ^_^
像sys_*这样的函数不是从寄存器拿参数的,是从栈里面拿的,而上面的压栈过程已经很清楚参数是怎么样进栈的.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-12 12:26:26 | 显示全部楼层
对了哥们 你说的对  参数是通过寄存器传入内核压栈后再从栈里面拿的  可是在像sys_open这样的函数中我找不到相关的出栈取参数的操作呀 请哥们结合sys_open例子谈谈
asmlinkage long sys_open(const char __user * filename, int flags, int mode)
{
        char * tmp;
        int fd, error;

#if BITS_PER_LONG != 32
        flags |= O_LARGEFILE;
#endif
        tmp = getname(filename);
        fd = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
                fd = get_unused_fd();
                if (fd >= 0) {
                        struct file *f = filp_open(tmp, flags, mode);
                        error = PTR_ERR(f);
                        if (IS_ERR(f))
                                goto out_error;
                        fd_install(fd, f);
                }
out:
                putname(tmp);
        }
        return fd;

out_error:
        put_unused_fd(fd);
        fd = error;
        goto out;
}
这东东就是看不懂呀
回复 支持 反对

使用道具 举报

发表于 2005-5-12 12:54:41 | 显示全部楼层
Post by qqrilxk
对了哥们 你说的对  参数是通过寄存器传入内核压栈后再从栈里面拿的  可是在像sys_open这样的函数中我找不到相关的出栈取参数的操作呀 请哥们结合sys_open例子谈谈
asmlinkage long sys_open(const char __user * filename, int flags, int mode)
{
        char * tmp;
        int fd, error;

#if BITS_PER_LONG != 32
        flags |= O_LARGEFILE;
#endif
        tmp = getname(filename);
        fd = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
                fd = get_unused_fd();
                if (fd >= 0) {
                        struct file *f = filp_open(tmp, flags, mode);
                        error = PTR_ERR(f);
                        if (IS_ERR(f))
                                goto out_error;
                        fd_install(fd, f);
                }
out:
                putname(tmp);
        }
        return fd;

out_error:
        put_unused_fd(fd);
        fd = error;
        goto out;
}
这东东就是看不懂呀



————————————————————————————————————————————
一:你要看看汇编的书!
二:你没有搞清楚系统调用是怎么调用的
+++++++++++++++++++++++++++++++++++++++++++++++++++++
1:
在用户态通过int 0x80进入核心态!用的就是下面这些宏
324 #define _syscall1(type,name,type1,arg1) \
325 type name(type1 arg1) \
326 { \
327 long __res; \
328 __asm__ volatile ("int $0x80" \
329 : "=a" (__res) \
330 : "0" (__NR_##name),"b" ((long)(arg1))); \
331 __syscall_return(type,__res); \
332 }

2:
在核心态调用这些函数时(比如:sys_open),就跟普通的函数调用一样了!

3:
sys_open中参数,对应于那个寄存器,在用_syscall3时,就已经定好了,请看1中定义!
回复 支持 反对

使用道具 举报

发表于 2005-5-12 19:13:50 | 显示全部楼层
Post by qqrilxk
对了哥们 你说的对  参数是通过寄存器传入内核压栈后再从栈里面拿的  可是在像sys_open这样的函数中我找不到相关的出栈取参数的操作呀

你狠......
函数调用是怎么回事知道不?

你平时写的其它函数有显式出栈取参数的操作吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-13 12:28:31 | 显示全部楼层
谢谢哥们的热心 呵呵 俺有点脸红了 可是还是有点不解 但哥们说的我懂  我的意思是在发出了INT80中断向量后 在系统调用参数已进入了内核栈 sys_open在刚开始内核中运行时是需要与 内核栈 交互取得参数的 我的意思是这交互过程是怎样的  在代码中是看不出来的好像  
在核心态调用这些函数时(比如:sys_open),就跟普通的函数调用一样了!是呀 这个我也懂 只是我感觉它的参数是先放在内核栈中呀  此时
asmlinkage long sys_open(const char __user * filename, int flags, int mode)
中这个filename是指向哪呀 还有这个flags和mode是指向哪呀
在用户态下的调用open(filename,flags,mode,)  这个filename是一个文件名 它是在当前目录下搜索吧 而flags和mode是一个已确定的整数
唉 反正有点笨 还望各位大哥指点
不要骂我 每次我都有点脸红的  
谢谢了
回复 支持 反对

使用道具 举报

发表于 2005-5-13 13:23:06 | 显示全部楼层
看来你是真不明白函数调用是怎么回事呢
建议找本编译的书看看,先

ps:值传递和引用传递之类的概念有没有?
回复 支持 反对

使用道具 举报

发表于 2005-5-18 22:41:07 | 显示全部楼层
调用者将参数压入栈中,被调用者从栈里面取出传过来的参数,就是这样
至于你在asmlinkage long sys_open(const char __user * filename, int flags, int mode)
里面看不到取参数的代码,这就是C代码的优势了,C的编译器都帮你做了,取参数这样的工作
如果你非要看,那么就看从C代码编译出来的汇编代码,你就能看见汇编写的pop指令了
回复 支持 反对

使用道具 举报

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

本版积分规则

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