实验六:分析Linux内核创建一个新进程的过程

作者:王朝宪  《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

进程

1.进程即处于执行期的程序,并不局限于一个可执行的代码,是处于执行期程序以及其相关资源的总称。

2.Linux系统中,对于进程和线程并没有明显的区分,线程是一种特殊的进程。

3.Linux系统中,常用fork()进程创建子进程。调用fork()进程的成之为其子进程的父进程。

4.fork()继承实际上由clone()系统调用实现。最后通过exit()退出执行。

操作系统三大功能:

  • 进程管理
  • 内存管理
  • 文件系统

任务描述符及任务结构

1.进程描述符(PID),是每一个进程的唯一标识值

2.PID中state描述了进程当前的状态,每个进程都必然处于下列五中状态中的一种。

  TASK_RUNNING(可运行):标识该进程正在运行或等待运行,这是进程在用户空间执行的唯一可能状态。

  TASK_INTERRUPTLBLE:(可中断):进程在睡眠,等待某种条件的达成,等待被唤醒。

  TASK_UNINTERRUPTLBLR:(不可中断)

  _TASK_TRACED:被其他进程跟踪的进程

  _TASK_STOPPED:停止执行进程

进程创建

1.Linux将进程创建拆分为两个单独函数:fork()与exec(),前者拷贝当前进程创建子进程,后者负责读取可执行文件并将其载入地址空间开始运行。

2.Linux的fork()函数具有写时拷贝功能,只有在需要时,数据才会被复制。

3.fork()

  fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

1)在父进程中,fork返回新创建子进程的进程ID;
     2)在子进程中,fork返回0;
     3)如果出现错误,fork返回一个负值;

线程在Linux中实现

1.线程的创建和进程创建类似,但是在调用clone()时候需要传递一些参数标志来指明需要共享的资源。

2.传递的参数决定了新创建进程的行为方式和父子进程之间的共享种类。

3.内核线程与普通线程的区别在于:内核线程没有独立的地址空间,仅在内核空间运行。内核线程只能由其他内核线程创建,其祖先为kthreadd

Task running表示可以运行。是否在运行取决于他是否取得了内核的控制权

gdb跟踪分析一个fork系统调用内核处理函数sys_clone

启动menuos

cd LinuxKernel

rm menu -rf

git clone https://github.com/mengning/menu.git

cd menu

mv test_fork.c test.c

make rootfs


gdb调试fork命令

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb
file linux-3.18.6/vmlinux
target remote:1234



总结:

Linux通过复制父进程来创建一个新进程,通过调用do_ fork来实现并为每个新创建的进程动态地分配一个task_ struct结构。

1. 新进程的开始

从ret_from_fork处开始执行
  • dup_task_struct中为其分配了新的堆栈
  • copy_process中调用了sched_fork,将其置为TASK_RUNNING
  • copy_thread中将父进程的寄存器上下文复制给子进程,这是非常关键的一步,这里保证了父子进程的堆栈信息是一致的。
  • ret_from_fork的地址设置为eip寄存器的值,这是子进程的第一条指令。

2. 执行起点与内核堆栈保证一致

  • 在设置子进程的ip之前:

    *childregs = *current_ pt_ regs();
  • 将父进程的regs参数赋值到子进程的内核堆栈,*childregs的类型为pt_regs,其中存放了SAVE ALL中压入栈的参数。

3.大致框架

  • 复制一个PCB——task_struct

    p = dup_task_struct(current);//复制进程的PCB
    
    int __weak arch_dup_task_struct(struct task_struct *dst,struct task_struct *src)
    {
    *dst = *src;//通过赋值实现复制
    return 0;
    }
  • 给新进程分配一个新的内核堆栈

    ti = alloc_thread_info_node(tsk, node);
    tsk->stack = ti;
    setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
  • 修改复制过来的进程数据,比如pid、进程链表等(见copy_process内部)。

    /*copy_thread in copy_process*/
    /*拷贝内核堆栈数据和指定新进程的第一条指令地址*/
    *childregs = *current_pt_regs(); //复制内核堆栈,只复制了SAVE_ALL相关的部分
    childregs->ax = 0; //子进程的fork返回0的原因 p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
    p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

实验 六:分析linux内核创建一个新进程的过程的更多相关文章

  1. 第六周分析Linux内核创建一个新进程的过程

    潘恒 原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 task_struct结构: ...

  2. 20135202闫佳歆--week6 分析Linux内核创建一个新进程的过程——实验及总结

    week 6 实验:分析Linux内核创建一个新进程的过程 1.使用gdb跟踪创建新进程的过程 准备工作: rm menu -rf git clone https://github.com/mengn ...

  3. linux内核分析作业6:分析Linux内核创建一个新进程的过程

    task_struct结构: struct task_struct {   volatile long state;进程状态  void *stack; 堆栈  pid_t pid; 进程标识符  u ...

  4. Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程

    Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...

  5. 作业六:分析Linux内核创建一个新进程的过程

    分析Linux内核创建一个新进程的过程 进程描述符PCB----task_struct数据结构 操作系统:1.进程管理 2.内存管理 3 文件系统 一.新进程如何创建和修改task_struct数据结 ...

  6. 《Linux内核--分析Linux内核创建一个新进程的过程 》 20135311傅冬菁

    20135311傅冬菁 分析Linux内核创建一个新进程的过程 一.学习内容 进程控制块——PCB  task_struct数据结构 PCB task_struct中包含: 进程状态.进程打开的文件. ...

  7. Linux内核分析-分析Linux内核创建一个新进程的过程

    作者:江军 ID:fuchen1994 实验题目:分析Linux内核创建一个新进程的过程 阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/li ...

  8. 实验六:分析Linux内核创建一个新进程的过程

    原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 题目自拟,内容围绕对Linu ...

  9. 第六周——分析Linux内核创建一个新进程的过程

    "万子恵 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 &q ...

随机推荐

  1. Geth命令用法-参数详解 and 以太坊源码文件目录

    本文是对以太坊客户端geth命令的解析 命令用法 geth [选项] 命令 [命令选项] [参数-] 版本 1.7.3-stable 命令 account 管理账户 attach 启动交互式JavaS ...

  2. 解决The valid characters are defined in RFC 7230 and RFC 3986错误问题

    分析原因: 导致上述问题是因为tomcat自tomcat 8.0.35版本之后对URL参数做了比较规范的限制,必须遵循RFC 7230 and RFC 3986规范,对于非保留字字符(json格式的请 ...

  3. 宿主在Windows Service中的WCF(创建,安装,调用) (host到exe,非IIS)

    1. 创建WCF服务 在vs2010中创建WCF服务应用程序,会自动生成一个接口和一个实现类:(IService1和Service1) IService1接口如下:   using System.Ru ...

  4. 【转】 [置顶] Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)

    在Android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. ...

  5. Redux入门学习

    一.Redux三大原则 1. 单一数据源 应用中所有的state都以一个对象树的形式储存在一个单一的store中. 2. state只读 唯一改变state的办法是触发action.action是一个 ...

  6. WinForm中Component Class、User Control及Custom Control的区别和使用

    NET Framework 为您提供了开发和实现新控件的能力.除了常见的用户控件外,现在您会发现,您可以编写能执行自身绘图的自定义控件,甚至还可以通过继承扩展现有控件的功 能.确定创建何种类型的控件可 ...

  7. anaconda使用以及创建python3.7+pytorch1.0虚拟环境以及Jupyter notebook初级使用

    查看所有已安装的软件包$ conda list# packages in environment at S:\Users\jiangshan\Anaconda3:## Name Version Bui ...

  8. robotframe 自定义开发库

    site-packages(这个路径一定要在系统path路径中)下面创建一个UserDefineLibrary文件夹:目录结构如下 ---- ----- UserDefineLibrary __ in ...

  9. HDU 1811 Rank of Tetris(并查集+拓扑排序 非常经典)

    Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  10. bat 栈上限

    栈耗尽,递归会导致该问题. ****** B A T C H R E C U R S I O N exceeds STACK limits ******Recursion Count=1240, St ...