2019-2020-1 20199306《Linux内核原理与分析》第七周作业

进程的描述和进程的创建

进程的描述

1、操作系统内核实现操作系统的三大管理功能:

  • 进程管理

  • 内存管理

  • 文件系统

其中最核心的功能是进程管理。

2、对进程的描述:在操作系统原理中,通过进程控制块PCB描述进程。在Linux内核中通过一个数据结构struct task_struct来描述进程,称其为进程描述符。

3、对进程状态的描述:

  • 在操作系统原理中,进程有就绪态、运行态和阻塞态3种基本状态;

  • 在Linux内核中,当时用fork()系统调用来创建一个进程时,新进程的状态是TASK_RUNNING(就绪态但没有运行)。就绪态和运行态在Linux内核中都是TASK_RUNNING状态,此状态下进程是可运行的,也就是就绪态,是否在运行取决于它有没有获得CPU的控制权,即这个进程有没有在CPU中实际执行。如果在CPU中实际执行了,进程状态就是运行态;如果被内核调度出去了,在等待队列里就是就绪态。

  • 对于一个正在运行的进程,调用用户态库函数exit()会陷入内核执行该内核函数do_exit(),进程会进入TASK_ZOMBIE状态,即进程的终止状态。TASK_ZOMBIE状态的进程一般叫做僵尸进程,Linux内核会在适当的时候把僵尸进程处理掉,然后释放进程描述符。

  • 一个正在运行的进程在等待特定事件或资源时会进入阻塞态,阻塞态分为两种:

    • TASK_INTERRUPTIBLE

    • TASK_UNINTERRUPTIBLE

前者可以被信号和wake_up()唤醒,后者只能被wake_up()唤醒。

进程的创建

1、0号进程的初始化:
init_task为第一个进程(0号进程)的进程描述符结构体变量,它的初始化是通过硬编码方式固定下来的,除此之外的其它进程的初始化都是通过do_fork复制父进程的方式初始化的。

2、fork、vfork、clone这3个系统调用和kernel_thread内核函数都可以创建一个新进程,而且都是通过do_fork函数来创建进程的,只不过传递的参数不同。

3、进程的创建过程:

利用fork()系统调用来创建新进程,把当前进程的描述符等相关进程资源复制一份,从而产生一个子进程,并根据子进程的需要对复制的进程描述符做一些修改,然后把创建好的子进程放入运行队列。在进程调度时,新创建的子进程处于就绪状态有机会被调度执行。

4、进程创建过程中的重要函数或数据结构:

  • do_fork():主要完成调用copy_process()复制父进程信息、获得pid、调用wake_up_new_task将子进程加入调度器队列等待获得分配CPU资源运行、通过clone_flags标志做一些辅助工作。
  • copy_process():主要完成调用dup_task_struct复制当前进程(父进程)描述符task_struct、信息检查、初始化、把进程状态设置为TASK_RUNNING(就绪态)、采用写时复制技术逐一复制所有其他进程资源、调用copy_thread初始化子进程内核栈、设置子进程pid等。
  • dup_task_struct():复制当前进程(父进程)描述符task_struct和copy_thread初始化子进程内核栈。
  • thread_info:小型的进程描述符,占据连续的两个页框,通过task指针指向进程描述符。内核栈有高地址到低地址增长,thread_info结构有低地址到高地址增长。
  • copy_thread():完成内核栈关键信息的初始化。如果创建的是内核线程,则子进程开始执行的起点是ret_from_kernel_thread;如果创建的是用户态进程,则子进程开始执行的起点是ret_from_fork。

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

1、增加fork系统调用

cd LinuxKernel
rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu
make rootfs

2、启动内核

3、gdb跟踪

启动gdb,将内核加载进来,建立连接,并在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork处各设置断点。

总结

进程的创建过程大致是复制进程描述符、一一复制其它进程资源(采用写时复制技术)、分配子进程的内核堆栈并对内核堆栈关键信息进行初始化。
问题是fork、vfork、clone这三种系统调用的不同,通过查阅资料发现:

  • fork():子进程拷贝父进程的数据段,代码段,父子进程的执行次序不确定;
  • vfork():创建的子进程与父进程共享数据段,而且子进程将先于父进程运行;
  • clone():是则可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享。

猜你喜欢

转载自www.cnblogs.com/Huyiming/p/11779115.html
今日推荐