您的位置:首页 > 运维架构 > Linux

20135316Linux内核学习笔记第六周

2016-03-30 22:11 531 查看
20135316王剑桥《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC 1000029000

一、进程控制块PCB——task_struct又称进程描述符,是操作系统用于管理控制进程的一个专门的数据结构,记录进程的各种属性,描述进程的动态变化过程,而PCB是系统感知进程存在的唯一标志

为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。

struct task_struct数据结构很庞大



Linux进程的状态与操作系统原理中的描述的进程状态似乎有所不同,比如就绪状态和运行状态都是TASK_RUNNING,为什么呢?

我们调用fork创建好一个新进程的时候,它的状态是TASK_RUNNING(就绪,但是没有在运行),当调度器选择我们新fork的这个进程的时候,它就切换到TASK_RUNNING(正在运行)

当进程是TASK_RUNNING这种状态的时候,也就是说它是可运行的,但它有没有在运行呢?这个取决于它有没有获得CPU的控制权,也就是说这个进程有没有在CPU上实际地执行,如果在CPU上实际地执行,那就是“正在运行”,如果被调度出去了,在等待,那就是“就绪,但是没有在运行”,这是和操作系统原理中描述的进程状态不同的地方

进程的标示pid

所有进程链表struct list_head tasks;



内核的双向循环链表的实现方法 - 一个更简略的双向循环链表

程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。进程描述符中有几个域用来表示这样的关系



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

进程处于内核态时使用,不同于用户态堆栈,即PCB中指定了内核栈,那为什么PCB中没有用户态堆栈?用户态堆栈是怎么设定的?

内核控制路径所用的堆栈很少,因此对栈和Thread_info来说,8KB足够了

struct thread_struct thread; //CPU-specific state of this task

文件系统和文件描述符

内存管理——进程的地址空间

二、操作系统三大功能:进程管理(核心)、内存管理、文件系统。

三、进程状态转换:



四、创建一个新进程在内核中的执行过程

Fork(在用户态创建一个子进程,在子进程和父进程中各返回一次)、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;

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,而非复制内核堆栈

要修改复制过来的进程数据,比如pid、进程链表等等都要改改吧,见copy_process内部。

从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copy_thread in copy_process

childregs = current_pt_regs(); //复制内核堆栈

childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!

p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶

p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址(子进程从这里开始执行)

五、道生一(start-kernel。。。cpu-idle),一生二(kernel-init和kthreadd),二生三(即前面的0,1,2号三个进程),三生万物(一号进程是所有用户态进程的祖先,二号进程是所有内核态进程的祖先)

六、系统调用回顾







七、实验截图

1.首先删除原有menu,并下载新的menu





2.查看fork系统调用





3.gdb调试





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: