Chinaunix首页 | 论坛 | 博客
  • 博客访问: 528266
  • 博文数量: 96
  • 博客积分: 2102
  • 博客等级: 上尉
  • 技术积分: 1695
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:12
文章分类

全部博文(96)

文章存档

2014年(2)

2012年(94)

分类:

2012-04-13 19:21:25

        我们先前学过用fork() vfork() 来创建进程,在OS中提到过对于进程的调度绝大多数都是根据他的优先级进行判断的,是不定的。但是,在vfork函数中,确提到必须先让子进程先运行完,父进程才能运行,着实有点让人费解?其实,这与该函数的实现有关。对于fork 和 vfork 实现,都是基于调用do_fork 函数,其实 还有一个函数clone。也是用来创建进程的。
他们三者的区别:(clone_flag)
fork : 对于用户空间(中的资本资源)是进行复制的。
vfork:对于用户空间通过指针全部进行共享。
clone :根据传递的参数,来判断哪些进行共享,哪些进程复制。

对于vfork函数来讲clone_flag 的值为: SIGCHILD|CLONE_VFORK前一个信号表示子进程死亡之后要给父进程发一个信号,而一个表示vfork因为,对于vfork函数来讲,父子进程的用户空间完全共享,因此无论谁对用户空间数据的修改对于双方都是可见,更加严重的是,在子函数的调用中会用到 栈,父子进程最后可能因为访问越界而死亡。因此,必须只能让一个进程在用户空间能运行。直到它死亡或者父子进程之间的用户空间不再共享为止。如果,父进程先死亡,那么,子进程便会变成孤儿进程(最后由init进程接管)。对于有些程序是不合理的。所以先扣留‘父进程’,让子进程先运行。

而对于该过程是通过信号量进行实现的。
在do_fork开始的地方申请了一个变量将其赋给了currnet-> vfork_sem 变量。并且他的值为0。
current->vfork_sem = DECLARE_ MUTEX_LOCKED( sem )

#define DECLARE_MUTEX(name) __DECLARE_SEMAPTHORE_GENERIC(name ,1)  通常信号量的值为1
#define DECLARE_ MUTEX_LOCKED( name ) __DECLARE_SEMAPTHORE_GENERIC(name ,0)

但是current->vfork_sem的值为0,因此只要父进程执行一次down()操作就会进入睡眠状态而达到被扣留的目的。
@
      在do_fork()函数尾部有关于clone_flags 中 VFORK的判断。如果是,调用down函数
if (( & ) && ( > 0))
            (&); @
直到执行up()操作被唤醒。

up操作:如果进程执行execve则是在真正意义上与父进程的“分道扬镳”。在装载可执行文件的时候,会创建自己的用户空间,此时会通过 mm_release()函数来判断,如果此进程是通过vfork()创建的,会执行up操作。

因此如果使用了vfork()函数,子进程需要调用函数exit()进行退出。否则可能出现下列错误:
             cxa_atexit.c:100: __new_exitfn: Assertion `l != ((void *)0)' failed.
             已放弃


阅读(1257) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~