linux进程创造 - 创建进程API及过程
来源:互联网 发布:淘宝联盟链接转换工具 编辑:程序博客网 时间:2024/05/17 23:24
1. 创建进程函数API
1.1 创建进程fork()
fork的翻译为“叉子,分叉”,其实在unix编程中,我们来创建进程的时候是深有体会的,感觉创建一个进程就像是走到了一个岔路口,父进程和子进程在叉路口分道扬镳,所以我想这就是前辈为什么要用fork来表示创建一个进程的缘由吧。
通过fork(),除了task_struct和堆栈,子进程和父进程共享所有的资源,相当于复制了一个父进程,但是由于linux采用了写时复制技术,复制工作不是立即就执行,提高了效率。在unix编程中,调用fork实际上相当于创建了一个进程。
(kernel/fork.c)
SYSCALL_DEFINE0(fork){#ifdef CONFIG_MMU return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0);#else /* can not support in nommu mode */ return -EINVAL;#endif}
1.2 创建进程vfork()
vfork类似于fork,但并不创建父进程数据的副本,相反,父子进程之间共享数据,这节省了大量CPU时间。
vfork设计用于子进程形成后立即执行execve加载新程序的情形。在子进程退出或开始新程序之前,内核保证父进程处于阻塞状态。但是由于fork使用了写时复制技术,vfork速度方面不再有优势,因此应该避免使用它。
(kernel/fork.c)
SYSCALL_DEFINE0(vfork){ return _do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 0, NULL, NULL, 0);}
1.3 创建线程clone()
clone翻译为“克隆”,从字面理解就是照着父进程的样子重新生成一个子进程,但是子进程是一个新的个体,和父进程已经少了许多关系。
clone产生线程,可以对父子进程之间的共享、复制进行精确控制。
(kernel/fork.c)
#ifdef CONFIG_CLONE_BACKWARDSSYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, int __user *, parent_tidptr, unsigned long, tls, int __user *, child_tidptr)#elif defined(CONFIG_CLONE_BACKWARDS2)SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls)#elif defined(CONFIG_CLONE_BACKWARDS3)SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, int, stack_size, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls)#elseSYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls)#endif{ return _do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr, tls);}
1.4 进程创建部分标志的含义
2. _do_fork
上述创建进程的API最后调用的函数都是_do_fork,下面来介绍此函数的工作
(kernel/fork.c)
long _do_fork(unsigned long clone_flags,unsigned long stack_start,unsigned long stack_size,int __user *parent_tidptr,int __user *child_tidptr,unsigned long tls){ struct task_struct *p; int trace = 0; long nr; /* * Determine whether and which event to report to ptracer. When * called from kernel_thread or CLONE_UNTRACED is explicitly * requested, no event is reported; otherwise, report if the event * for the type of forking is enabled. */ if (!(clone_flags & CLONE_UNTRACED)) { if (clone_flags & CLONE_VFORK) trace = PTRACE_EVENT_VFORK; else if ((clone_flags & CSIGNAL) != SIGCHLD) trace = PTRACE_EVENT_CLONE; else trace = PTRACE_EVENT_FORK; if (likely(!ptrace_event_enabled(current, trace))) trace = 0; } p = copy_process(clone_flags, stack_start, stack_size,----------------复制父进程的一些数据 child_tidptr, NULL, trace, tls); /* * 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; struct pid *pid; trace_sched_process_fork(current, p); pid = get_task_pid(p, PIDTYPE_PID); nr = pid_vnr(pid); if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); get_task_struct(p); } wake_up_new_task(p);-----------------------------------------------使进程加入运行队列,被调度 /* forking complete and child started to run, tell ptracer */ if (unlikely(trace)) ptrace_event_pid(trace, pid); if (clone_flags & CLONE_VFORK) {-----------------------------------如果有标志CLONE_VFORK,就等待让子进程先运行 if (!wait_for_vfork_done(p, &vfork)) ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); } put_pid(pid); } else { nr = PTR_ERR(p); } return nr;}
3. copy_process
static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *child_tidptr, struct pid *pid, int trace, unsigned long tls)
copy_process的流程图如下所示,其中代码细节部分会在文章系列的子部分详细说明:
change log
1 0
- linux进程创造 - 创建进程API及过程
- linux进程创造 - 内核进程初始化及创建
- linux 进程(二) --- 进程的创建及相关api
- linux 进程(二) --- 进程的创建及相关api
- linux 进程(二) --- 进程的创建及相关api
- Linux 进程创建及多进程
- 进程的创建及相关api
- inux 进程2 --- 进程的创建及相关api
- 伪代码说明Linux进程创建过程
- Linux下守护进程的创建过程
- 伪代码说明Linux进程创建过程
- linux创建新进程的过程
- linux进程创建过程与原理
- linux进程创建过程与原理
- linux进程创建过程与原理
- linux创建新进程的过程
- linux进程创建过程与原理
- Unix/Linux 初始创建进程过程
- java8新特性(八):Optional
- 如何通过编程发现Java死锁
- 欢迎使用CSDN-markdown编辑器
- 双栈共享
- 操作系统引论
- linux进程创造 - 创建进程API及过程
- js完美实现身份证号的有效验证
- SpringBoot快速构建微服务架构体系
- 【步兵 工具篇】二进制读写 源码
- 有了百度为什么还要读书
- 如何避免“野指针”
- 反射的简单应用三
- UML之类图(更新中)
- Node.js基础(二)