sys_fork()
来源:互联网 发布:知乎 重庆鸳鸯锅 编辑:程序博客网 时间:2024/06/03 23:43
eax作为返回值应该是gcc的约定吧,所以你先要把握这个约定才行~~之后才可能理解其他的代码~~
大概的变化过程是这个样子:
1、在 调用 fork 的时候,触发了系统调用 sys_fork (这个你要理解_syscall0这个宏才行)
2、接着进入了系统调用sys_fork(因为之前有注册系统调用0x80,为system_call,而system_call里头有根据系统调用编号来处理sys_fork的语句)
sys_fork:
call find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call copy_process
addl $20,%esp
1: ret
3、之后就是执行上面的代码,
先找出一个空的进程控制块结构和一个新的pid,如果发现没有找到,直接退出中断,否则把重要信息入栈,最后一个入栈的即为find_empty_process的返回值,即eax,里头刚好是那个空的进程控制块的编号。
这里的eax是进程控制块的编号~~
接着进入copy_process,在里头开始复制进程控制块。在分析copy_process之前,必须理解copy_process的参数传递问题。
copy_process有这么一大串的参数:
int nr,long ebp,long edi,long esi,long gs,long none,
long ebx,long ecx,long edx,
long fs,long es,long ds,
long eip,long cs,long eflags,long esp,long ss
都必须明确它们的来源才行,它们来自栈?自上而下分别是:
ss #这里是发生中断后cpu自动压入栈中的
esp
eflags
cs
eip #这个是cpu自动存入的,在发生中断时的下一条指令,即_syscall0中int 0x80之后的代码
# if (__res >= 0) return (type) __res;要注意,这里的eax跟__res是绑定的,你看看: "=a" (__res)就知道了,所以__res即eax
ds #这里开始到none都是从system_call那里开始压入栈中的
es
fs
edx
ecx
ebx
none # 这个是什么呢,我们根本没有找到对应的push指令,但是你有没有发现在call *sys_call_table(,%eax,4)跳转到sys_fork时,
# 等同于push eip; jmp *sys_call_table(,%eax,4),所以none就是call *sys_call_table(,%eax,4)的下一条指令
#不过这个东西仅仅是用来占位了,在copy_process中根本没有用到
gs #这里一直到nr都是从sys_fork那里亚入栈中的
esi
edi
ebp
nr --> eax
"addl $20, %esp"的地址
okay,参数理解以后,我们接着看下面的关键代码:
p->tss.eip = eip; ...
p->tss.eax = 0;
注意这两句,第一句是说进程1的TSS里头的eip即cpu压入到栈里头的eip,即if (__res >= 0) 的地址,而eax则是0
执行完copy_process以后,进程1就可以参与调度了,因为它的状态被设置成了TASK_RUNNING,见p->state = TASK_RUNNING
4、接着执行sys_fork的最后两条指令
addl $20,%esp
1: ret
第一条是把esp增加20,刚好是gs, esi,edi,ebp,eax,以及ip这几个寄存器所占的栈的空间,即4*5。另外,注意一下"addl $20, %esp"的地址已经被copy_process的返回指令ret弹出来了,所以这里不用管。
指定完 addl $20,%esp,下面就是ret,它接着从栈中弹出一个地址,即 none,也即是 call *sys_call_table(,%eax,4)的下一条指令,我们看到,刚好是 pushl %eax,我们发现这个 eax,刚好是 copy_process 返回之前 return 的 last_pid,
接着,将执行如下指令
movl current,%eax
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
后续的就是比较当前current,即子进程的状态是否可以运行,如果当前进程不再就绪状态就去执行调度程序,如果该任务在就绪状态但时间片用完了,也就执行调度程序。所有后续的情况是,我们无法确定进程0或者进程1先执行,但是返回值已经明显确定了。
即进程0的返回值为last_pid,即子进程的pid;而子进程,即进程1的返回值呢,则为0,因为在copy_proces的时候已经设置为了0。
- sys_fork()
- sys_fork() in os161
- 系统调用:sys_fork
- 窥探 kernel,just for fun --- sys_fork,sys_vfork,sys_clone,kernel_thread
- 窥探 kernel,just for fun --- sys_fork,sys_vfork,sys_clone,kernel_thread
- Sybase CEP:资本市场复杂事件处理技术
- 水晶报表的使用(转载)
- SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
- IPv6 地址格式
- Android的Task和Activity相关
- sys_fork()
- VSS (Visual Source Safe 2005) 用法详解
- 关于引用exchange webservice做二次开发的一些问题
- windows的分层驱动--内核实现的一种方式
- 程序设计原则(整理)
- 创建合同时获取可配置物料中选配的特性值
- [转载] Linux内核2.4.x的网络接口源码的结构
- Android常见布局控件之LinearLayout和TableLayout
- 三足鼎立