进程管理(一) fork系统调用
来源:互联网 发布:图文识别软件 编辑:程序博客网 时间:2024/05/02 01:14
Linux下用于创建进程的API有三个fork,vfork和clone,这三个函数分别是通过系统调用sys_fork,sys_vfork以及sys_clone实现的
注:这里目前讨论的都是基于x86架构的
fork
- int sys_fork(struct pt_regs *regs)
- {
- return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
- }
vfork
- int sys_vfork(struct pt_regs *regs)
- {
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
- NULL, NULL);
- }
clone
- int sys_vfork(struct pt_regs *regs)
- {
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
- NULL, NULL);
- }
由以上代码可知,最终这三个系统调用,都是通过do_fork来实现的,只是传入了不同的参数。
那么接下来先看看do_fork的实现
- long do_fork(unsigned long clone_flags,
- unsigned long stack_start,
- struct pt_regs *regs,
- unsigned long stack_size,
- int __user *parent_tidptr,
- int __user *child_tidptr)
- {
- struct task_struct *p;
- int trace = 0;
- long nr;
- /*
- * Do some preliminary argumentand permissions checking before we
- * actually start allocating stuff
- */
- if (clone_flags& CLONE_NEWUSER){
- if (clone_flags& CLONE_THREAD)
- return -EINVAL;
- /* hopefully this check will go away when userns supportis
- * complete
- */
- if (!capable(CAP_SYS_ADMIN)|| !capable(CAP_SETUID)||
- !capable(CAP_SETGID))
- return -EPERM;
- }
- /*
- * When called from kernel_thread, don'tdo user tracing stuff.
- */
- if (likely(user_mode(regs)))
- trace = tracehook_prepare_clone(clone_flags);
- 1)
- p = copy_process(clone_flags, stack_start, regs, stack_size,
- child_tidptr, NULL, trace);
- /*
- * Do this prior waking up the new thread- the thread pointer
- * might get invalid after that point,if the thread exits quickly.
- */
- if (!IS_ERR(p)){
- struct completion vfork;
- trace_sched_process_fork(current, p);
- 2)
- nr = task_pid_vnr(p);
- if (clone_flags& CLONE_PARENT_SETTID)
- put_user(nr, parent_tidptr);
- if (clone_flags& CLONE_VFORK){
- p->vfork_done= &vfork;
- init_completion(&vfork);
- }
- audit_finish_fork(p);
- tracehook_report_clone(regs, clone_flags, nr, p);
- /*
- * We set PF_STARTING at creation in case tracing wants to
- * use this to distinguish a fully live task from one that
- * hasn't gottento tracehook_report_clone() yet.Now we
- * clear it and set the child going.
- */
- p->flags&= ~PF_STARTING;
- wake_up_new_task(p, clone_flags);
- tracehook_report_clone_complete(trace, regs,
- clone_flags, nr, p);
- if (clone_flags& CLONE_VFORK){
- freezer_do_not_count();
- wait_for_completion(&vfork);
- freezer_count();
- tracehook_report_vfork_done(p, nr);
- }
- } else{
- nr = PTR_ERR(p);
- }
- return nr;
- }
代码不是很长,但是涉及到很多工作,这里简单讲解一下主体流程,细节方面的东西后面再解释:
1、copy_process:这个步骤主要是执行生成新进程的主要工作,并根据指定的标志重用父进程的一些数据;
- p = copy_process(clone_flags, stack_start, regs, stack_size,
- child_tidptr, NULL, trace);
2、确定PID:注意这里不是生成新的PID,而是确定局部PID;
- nr = task_pid_vnr(p);
3、init_completion:初始化vfork的完成处理程序(即是vfork调用时设置的CLONE_VFORK标志)和ptrace标志;
- if (clone_flags& CLONE_VFORK){
- p->vfork_done= &vfork;
- init_completion(&vfork);
- }
4、wake_up_new_task:这个是保证子进程在父进程之前调用,如果子进程立即调用exec,这样可以极大的减少复制内存页的工作量;
- wake_up_new_task(p, clone_flags);
5、wait_for_completion:跟上面的init_completion对应,让父进程在该task_struct的vfork_done成员上进入睡眠状态,直到子进程退出或者执行exec调用时,内核才会调用complete(vfork_done),这样就会唤醒父进程(也包含其他因该变量睡眠的进程)。
- if (clone_flags& CLONE_VFORK){
- freezer_do_not_count();
- wait_for_completion(&vfork);
- freezer_count();
- tracehook_report_vfork_done(p, nr);
- }
0 0
- 进程管理(一) fork系统调用
- fork--用于进程管理的系统调用
- 【进程管理】系统调用fork(),vfork()与clone()
- fork系统调用创建进程
- 【进程管理】系统调用execve()
- 【进程管理】系统调用exit()
- 【进程管理】系统调用wait4()
- 进程管理--fork函数
- 避免linux系统调用fork后产生僵死进程
- 从系统调用fork,到进程的创建与终止
- Linux 系统调用之 fork()——进程的创建
- 进程系统调用——fork函数深入理解
- 进程控制——fork系统调用学习笔记
- 系统编程之进程管理 fork—pid
- fork系统调用
- fork()系统调用
- linux fork系统调用
- fork系统调用
- hdu1102Constructing(最小生成树详解)
- 2016/5/26
- C++的一些简单示例(3)
- sdut 3274 山理工第七届校赛--完美素数
- HDOJ1301 prim
- 进程管理(一) fork系统调用
- PyQt5:控件的基本属性(2)
- 杭电OJ 1056 float 和double 相等以及大小的比较
- Linux下安装配置hadoop
- 21个经典的哲理故事
- 推送平台的架构
- 挖地雷_1996年分区联赛提高组之三_ssl1071_dfs
- S2SH项目实现分页功能
- if语句