第六周——进程描述和进程控制

【洪韶武 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 】

第六周 进程描述和进程控制

一、进程描述


1.进程控制块PCB和进程描述符struct task_struct

2.pid_t pid又叫进程标识符,唯一地标识进程

3.双向循环链表链接起了所有的进程,也表示了父子、兄弟等进程关系

4.struct mm_struct 指的是进程地址空间,涉及到内存管理(对于X86而言,一共有4G的地址空间)

5. Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info和进程的内核堆栈

6.进程状态

  进程描述符中的state域描述了进程的当前状态

  • TASK_RUNNING(运行)-进程可执行,进程正在或者等待执行
  • TASK_INTERRUPTIBLE(可中断)-进程被阻塞
  • TASK_UNINTERRUPTIBLE(不可中断)-对信号不做响应
  • _TASK_TRACED-被其他进程跟踪
  • _TASK_STOPPED(停止)-进程停止执行

二、进程创建


1.创建一个新进程在内核中的执行过程
(1)fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;
(2)Linux通过复制父进程来创建一个新进程,给理解这一个过程提供一个想象的框架:

  • 复制一个PCB——task_struct
  1. err = arch_dup_task_struct(tsk, orig);
  • 要给新进程分配一个新的内核堆栈
  1. ti = alloc_thread_info_node(tsk, node);
  2. tsk->stack = ti;
  3. setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈

2.fork代码

 

3.创建新进程的框架

fork,vfork,clone都可以创建新进程,他们都是通过调用do_fork来实现的

  • dup_thread复制父进程的PCB
  • copy_process修改复制的PCB以适应子进程的特点,也就是子进程的初始化
  • 分配一个新的内核堆栈(用于存放子进程数据)
  • 内核堆栈的一部分也要从父进程中拷贝
  • 根据拷贝的内核堆栈情况设置eip,esp寄存器的值

三、实验内容


更新menu内核,然后删除test_fork.c以及test.c,编译内核,可以看到fork命令

 

启动gdb调试,并对主要的函数设置断点


在MenuOS中执行fork,就会发现fork函数停在了父进程中

继续执行之后,停在了do_fork的位置。然后n单步执行,依次进入copy_process、dup_task_struct。按s进入该函数,可以看到dst = src(也就是复制父进程的struct),在copy_thread中,把task_pg_regs(p)也就是内核堆栈特定的地址找到并初始化,到了159、160行的代码就是把压入的代码再放到子进程中:

*children = *current_pt_regs();
childregs->ax = 0;
164行,是确定返回地址p->thread.ip = (unsigned long) ret_from_fork;

此后,可以输入finish使得进程运行完。

 

posted @ 2016-04-02 21:06  5219hsw  阅读(303)  评论(0编辑  收藏  举报