Linux内核分析——进程的描述和进程的创建
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核分析——进程的描述和进程的创建相关的知识,希望对你有一定的参考价值。
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、实验内容
-
阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;
-
分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构;
-
使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解,推荐在实验楼Linux虚拟机环境下完成实验。
-
特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
-
根据本周所学知识分析fork函数对应的系统调用处理过程,撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”,博客内容的具体要求如下:
-
题目自拟,内容围绕对Linux系统如何创建一个新进程进行;
-
可以结合实验截图、绘制堆栈状态执行流程图等;
-
博客内容中需要仔细分析新进程的执行起点及对应的堆栈状态等。
4. 总结部分需要阐明自己对“Linux系统创建一个新进程”的理解
二、实验准备
3.1进程
1.进程即处于执行期的程序,并不局限于一个可执行的代码,是处于执行期程序以及其相关资源的总称。
2.Linux系统中,对于进程和线程并没有明显的区分,线程是一种特殊的进程。
3.Linux系统中,常用fork()进程创建子进程。调用fork()进程的成之为其子进程的父进程。
4.fork()继承实际上由clone()系统调用实现。最后通过exit()退出执行。
3.2任务描述符及任务结构
1.任务队列实质上是进程的列表,是一种双向循环链表,其中每一项的类型均为task_struct.
2.Linux通过slab分配器分配task_struct结构,
3.进程描述符(PID),是每一个进程的唯一标识值,最大值32768.
4.PID中state描述了进程当前的状态,每个进程都必然处于下列五中状态中的一种。
TASK_RUNNING(可运行):标识该进程正在运行或等待运行,这是进程在用户空间执行的唯一可能状态。
TASK_INTERRUPTLBLE:(可中断):进程在睡眠,等待某种条件的达成,等待被唤醒。
TASK_UNINTERRUPTLBLR:(不可中断)
_TASK_TRACED:被其他进程跟踪的进程
_TASK_STOPPED:停止执行进程
5.内核一般使用set_task_state(state,task)来调整进程状态
3.3进程创建
1.Linux将进程创建拆分为两个单独函数:fork()与exec(),前者拷贝当前进程创建子进程,后者负责读取可执行文件并将其载入地址空间开始运行。
2.Linux的fork()函数具有写时拷贝功能,只有在需要时,数据才会被复制。
3.fork()
fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。此时,两个进程都从fork开始往下执行,只是pid不同。
3.4线程在Linux中实现
1.线程的创建和进程创建类似,但是在调用clone()时候需要传递一些参数标志来指明需要共享的资源。
2.传递的参数决定了新创建进程的行为方式和父子进程之间的共享种类。
3.内核线程与普通线程的区别在于:内核线程没有独立的地址空间,仅在内核空间运行。内核线程只能由其他内核线程创建,其祖先为kthreadd
Task running表示可以运行。是否在运行取决于他是否取得了内核的控制权三、实验过程
其中主要有如下内容:
task:进程链表的管理
tty:控制台
fs:文件系统
files:打开的文件
mm: 内存管理的描述
signal:进程间通讯信号的描述
使用系统调用SyS_clone(或fork,vfork)系统调用创建一个新进程,而且都是通过调用do_fork来实现进程的创建;.Linux通过复制父进程PCB--task_struct来创建一个新进程,要给新进程分配一个新的内核堆栈;要修改复制过来的进程数据,比如pid、进程链表等等执行copy_process和copy_thread.p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶 p->thread.ip = (unsigned long)ret_from_fork;
四.实验总结:
fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建,在设置子进程被调度的ip,即子进程的起点(ret_form_fork),通过实验的学习,我更加清楚了进程的创建过程,希望继续加深印象,在linux内核的学习上更加深入。
以上是关于Linux内核分析——进程的描述和进程的创建的主要内容,如果未能解决你的问题,请参考以下文章
20135239益西拉姆 Linux内核分析 进程的描述和进程的创建