第六章 进程的描述和进程的创建

  • 操作系统内核实现操作系统的三大管理功能,对应了3个抽象概念:
    • **进程管理——进程 **
    • 内存管理——虚拟内存
    • 文件系统——文件
  • 使用PCB描述进程。描述进程的机构,在Linux中使用数据结构struct task_struct描述进程,包含state进程状态,stack堆栈,fs文件系统等的描述。
    +
struct list_head tasks;//所有的进程用双向链表链起来


+

struct mm_struct *mm,*active_mm;//mm和active_mm是和进程地址空间、内存管理相关的数据结构指针
+ 进程之间的父子、兄弟关系
struct list_head __rcu *real_parent;//当前进程的父进程
struct list_head __rcu *parent;
struct list_head children;//当前进程的子进程
struct list_head sibling;//当前进程的兄弟进程
struct list_head *group_leader;//每一个进程是一些进程组的成员之一,进程组组都有一个进程组长(group leader)。进程组的所有 IO 输入输出都会引导到进程组长进程那里去。当一个进程被创建时,父进程的进程组长也看作是子进程的进程组长。系统初始化的时候,init 进程既是它自己的进程组长,同时也是其他所有进程的进程组长。
+ 保存进程上下文中CPU相关的一些状态信息的数据结构
struct thread_struct thread;//sp用来保存进程上下文中ESP寄存器的状态,ip用来保存进程上下文中EIP寄存器的状态
  • 在Linux系统中,TASK_RUNNING包括两种状态:进程就绪和进程运行。这两种状态的区分取决于进程是否获得CPU的分配权
  • 阻塞态: TASK_INTERRUPTIBLE 可以被信号或wake_up()唤醒。TASK_UNINTERRUPTIBLE:只能被wake_up()唤醒。
  • 0号进程的初始化
set_task_stack_end_magic(&init_task);

内核的第一个进程0号进程iinit_task的进程描述符结构体变量的初始化是通过硬编码方式确定下来的,所有其他的进程都是通过do_fork的方式复制父进程来初始化的。

  • 进程的创建
    • 用户态创建进程的方法-fork系统调用
      • fork,vfork,clone 都是通过do_fork()函数创建进程

      • fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。

      • fork()函数最大的特点就是被调用一次,返回两次

      • 父子进程共享内存存储空间

    • do_fork()函数
      • clone_flags:子进程创建的相关标志,通过此标志对父进程资源进行有选择的复制。
      • **stack_start **:子进程用户态堆栈地址
      • reg:指向pt_regs结构体的指针。(pt_regs结构体中保存的是int指针和SAVE_ALL等压入栈的CPU寄存器的值)
      • **stack_size **:用户栈大小。通常为0.
      • *parent_tidptr: 指向父进程pid的指针
      • ***child_tidptr **:指向子进程pid的指针

实验部分-跟踪分析进程创建过程

  • 删除原有的menu,克隆新的menu
  • 编译运行出来可以看到fork命令
  • 按照5.2中的方法,首先启动内核
  • 在sys_clone,do_fork_,do_task_struct,copy_process,copy_thread,ret_from_fork等处设置断点并继续执行。
 posted on 2019-10-29 21:39  捞起月亮的渔民  阅读(111)  评论(0编辑  收藏  举报