[转帖]FORK()函数的两次返回的具体情况
2007-05-16 21:00
197 查看
[转帖]FORK()函数的两次返回的具体情况
对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用fork的父进程来说,如果fork出来的子进程没有得到调度,那么父进程从fork系统调用返回,同时分析sys_fork知道,fork返回的是子进程的id。再看fork出来的子进程,由copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点上返回),返回值直接置为0。所以当子进程得到调度的时候,也从fork返回,返回值为0。
关键注意两点:1.fork返回后,父进程或子进程的执行位置。(首先会将当前进程eax的值做为返回值)2.两次返回的pid存放的位置。(eax中)
进程调用copy_process得到lastpid的值(放入eax中,fork正常返回后,父进程中返回的就是lastpid)
子进程任务状态段tss的eax被设置成0,
fork.c 中
p->tss.eax=0;(如果子进程要执行就需要进程切换,当发生切换时,子进程tss中的eax值就调入eax寄存器,子进程执行时首先会将eax的内容做为返回值)
当子进程开始执行时,copy_process返回eax的值。
fork()后,就是两个任务同时进行,父进程用他的tss,子进程用自己的tss,在切换时,各用各的eax中的值.
所以,“一次调用两次返回”是2个不同的进程!
例子:
int main()
{
pid_t pid;
pid=fork();
if ( pid < 0 ) {
fprintf( stderr, "Fork Failed" );
exit( -1 );
}
else
if ( pid == 0 ) {
printf( "child process//n");
}
else
{
printf( "parent process//n" );
}
return 0;
}
这个程序执行为什么总是显示:child process
parent process
而不会先是parent 后是child呢?
答:看这一句:pid=fork()
当执行这一句时,当前进程进入fork()运行,此时,fork()内会用一段嵌入式汇编进行系统调用:int 0x80(具体代码可参见内核版本0.11的unistd.h文件的133行_syscall0函数)。这时进入内核根据此前写入eax的系统调用功能号便会运行sys_fork系统调用。接着,sys_fork中首先会调用C函数find_empty_process产生一个新的进程,然后会调用C函数copy_process将父进程的内容复制给子进程,但是子进程tss中的eax值赋值为0(这也是为什么子进程中返回0的原因),当赋值完成后,copy_process会返回新进程(该子进程)的pid,这个值会被保存到eax中。这时子进程就产生了,此时子进程与父进程拥有相同的代码空间,程序指针寄存器eip指向相同的下一条指令地址,当fork正常返回调用其的父进程后,因为eax中的值是新创建的子进程号,所以,fork()返回子进程号,执行else(pid>0);当产生进程切换运行子进程时,首先会恢复子进程的运行环境即装入子进程的tss任务状态段,其中的eax值(copy_process中置为0)也会被装入eax寄存器,所以,当子进程运行时,fork返回的是0执行if(pid==0)。
先显示child process应该和内核机制有关,当fork一个新的进程后都会进行进程的重新调度,此时总是子进程先运行(和进程优先级有关?)
对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用fork的父进程来说,如果fork出来的子进程没有得到调度,那么父进程从fork系统调用返回,同时分析sys_fork知道,fork返回的是子进程的id。再看fork出来的子进程,由copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点上返回),返回值直接置为0。所以当子进程得到调度的时候,也从fork返回,返回值为0。
关键注意两点:1.fork返回后,父进程或子进程的执行位置。(首先会将当前进程eax的值做为返回值)2.两次返回的pid存放的位置。(eax中)
进程调用copy_process得到lastpid的值(放入eax中,fork正常返回后,父进程中返回的就是lastpid)
子进程任务状态段tss的eax被设置成0,
fork.c 中
p->tss.eax=0;(如果子进程要执行就需要进程切换,当发生切换时,子进程tss中的eax值就调入eax寄存器,子进程执行时首先会将eax的内容做为返回值)
当子进程开始执行时,copy_process返回eax的值。
fork()后,就是两个任务同时进行,父进程用他的tss,子进程用自己的tss,在切换时,各用各的eax中的值.
所以,“一次调用两次返回”是2个不同的进程!
例子:
int main()
{
pid_t pid;
pid=fork();
if ( pid < 0 ) {
fprintf( stderr, "Fork Failed" );
exit( -1 );
}
else
if ( pid == 0 ) {
printf( "child process//n");
}
else
{
printf( "parent process//n" );
}
return 0;
}
这个程序执行为什么总是显示:child process
parent process
而不会先是parent 后是child呢?
答:看这一句:pid=fork()
当执行这一句时,当前进程进入fork()运行,此时,fork()内会用一段嵌入式汇编进行系统调用:int 0x80(具体代码可参见内核版本0.11的unistd.h文件的133行_syscall0函数)。这时进入内核根据此前写入eax的系统调用功能号便会运行sys_fork系统调用。接着,sys_fork中首先会调用C函数find_empty_process产生一个新的进程,然后会调用C函数copy_process将父进程的内容复制给子进程,但是子进程tss中的eax值赋值为0(这也是为什么子进程中返回0的原因),当赋值完成后,copy_process会返回新进程(该子进程)的pid,这个值会被保存到eax中。这时子进程就产生了,此时子进程与父进程拥有相同的代码空间,程序指针寄存器eip指向相同的下一条指令地址,当fork正常返回调用其的父进程后,因为eax中的值是新创建的子进程号,所以,fork()返回子进程号,执行else(pid>0);当产生进程切换运行子进程时,首先会恢复子进程的运行环境即装入子进程的tss任务状态段,其中的eax值(copy_process中置为0)也会被装入eax寄存器,所以,当子进程运行时,fork返回的是0执行if(pid==0)。
先显示child process应该和内核机制有关,当fork一个新的进程后都会进行进程的重新调度,此时总是子进程先运行(和进程优先级有关?)
相关文章推荐
- fork()函数的两次返回的具体情况
- FORK()函数的两次返回的具体情况
- 关于多进程编程中fork()函数返回两次的探究
- 一次调用,两次返回--fork函数学习总结
- fork()函数两次返回
- fork函数的两次返回和父子进程的执行顺序简介
- fork()函数,一次调用,两次返回
- Linux编程中fork()函数返回两次的探究
- 函数返回值的几种情况
- socket recv()函数返回0的一种情况
- Linux 文件系统(三)---dup和fork函数执行后的文件情况
- 创建进程时,为什么fork会返回两次?
- 为什么fork调用会返回两次
- fork()两次不同返回值的实现
- c/c++: c++函数返回类型什么情况带const
- fork如何做到返回两次
- 有关socket编程里,recv函数返回值为-1的情况
- fork()两次不同返回值的实现
- fork函数的返回值实际只有一个值,看似两个值是因为在不同的进程中返回
- c++函数在传入对象参数和返回对象时候的内存调用情况