Linux第六周学习总结——进程额管理和进程的创建

作者:刘浩晨

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

一、 进程的描述

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

  1. 进程控制快PCB——进程描述符task_struct数据结构

    进程状态(五种状态)转化:

    注意:就绪状态和运行状态都是TASK_RUNNING,具体是就绪还是执行要看系统当前的资源分配情况。

  2. 进程标识符PID
    进程标识符pid_t pid唯一地标识进程
  3. 所有进程链表struct list_ head tasks;
    双向循环链表链接起了所有的进程,也表示了父子、兄弟等进程关系程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。
  4. Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_ info和进程的内核堆栈。内核控制路径所用的堆栈很少,因此对栈和Thread_ info来说,8KB足够了。
  5. 进程处于内核态时使用,不同于用户态堆栈,即PCB中指定了内核栈。
  6. struct thread_ struct thread; //与当前任务CPU状态相关,对进程上下文切换有关键性作用
  7. struct mm_struct mm, active_mm; //内存管理进程的地址空间
  8. struct files_struct *files; //打开文件描述符列表

二、 进程的创建

1. 进程的创建概览及fork一个进程的源代码

进程的起源回顾:

start_ kernel创建了cpu_ idle,即0号进程。0号进程又创建了两个线程,一个是kernel_ init,即1号进程,这个进程最终启动了用户态;另一个是kthreadd。0号进程是固定的代码,1号进程是通过复制0号进程PCB之后在此基础上做修改得到的。

2.fork代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{int pid;/* fork another process */pid = fork();if (pid < 0) { /* error occurred */fprintf(stderr,"Fork Failed!");exit(-1);} else if (pid == 0) //pid == 0和下面的else都会被执行到(一个是在父进程中即pid ==0的情况,一个是 在子进程中,即pid不等于0){/* child process */printf("This is Child Process!\n");} else {  /* parent process  */printf("This is Parent Process!\n");/* parent will wait for the child to complete*/wait(NULL);printf("Child Complete!\n");}
} 

3. 系统调用回顾



  • iret与int 0x80指令对应,一个是弹出寄存器值,一个是压入寄存器的值。
  • 如果将系统调用类比于fork();那么就相当于系统调用创建了一个子进程,然后子进程返回之后将在内核态运行,而返回到父进程后仍然在用户态运行。

4.创建一个新进程在内核中的执行过程

fork、vork和clone三个系统调用都可以创建一个新进程,都通过调用do_fork()实现进程创建。

Linux通过复制父进程创建新进程:

• 复制一个PCB——task_struct

err = arch_dup_task_struct(tsk, orig);

• 给新进程分配一个新的内核堆栈

ti = alloc_ thread_ info_ node(tsk, node);

tsk->stack = ti;

setup_ thread_ stack(tsk, orig); //这里只是复制thread_ info,而非复制内核堆栈

• 从用户态的代码看fork(),函数返回了两次,即在父子进程中各返回一次。这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的——copy_thread in copy_process

*childregs = *current_pt_regs(); //复制内核堆栈,并不是全部,只是regs结构体(内核堆栈栈底的程序)
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!

p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址,也就是说返回的就是子进程的空间了

5.创建的新进程从哪里开始执行?

一个新创建的子进程,获得CPU之后,从哪一行代码进程执行:

• 与之前写过的my_ kernel相比较,kernel中是可以指定新进程开始的位置(也就是通过eip寄存器指定代码行)。fork中也有相似的机制

• 这涉及子进程的内核堆栈数据状态和task_ struct中thread记录的sp和ip的一致性问题,这是在copy_ thread in copy_ process设定的

*childregs = *current_pt_regs(); //复制内核堆栈,并不是全部,只是regs结构体(内核堆栈栈底的程序)
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!

p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址,也就是说返回的就是子进程的空间了

三、 实验——分析Linux内核创建一个新进程的过程

1.更新menu内核,删除test_fork.c以及test.cc,并重新执行make rootfs

2.比原先多出fork命令,编译内核查看:

3.启动gdb跟踪调试内核,在一些重要函数处设置断点:

4.在MenuOS中执行fork,停在父进程中。继续执行后,停在do_fork的位置:

5.n命令进行单步执行,依次进入copy_process、dup_task_struct。此时父进程的PCB(task_struct数据结构)已经复制过来。s命令进入函数,可以看到dst = src:

6.copy_thread函数中,把task_pg_regs(p)也就是内核堆栈特定的地址找到并初始化

7.当前进程的内核堆栈寄存器中的值复制到子进程中

8.164行:p->thread.ip = (unsigned long) ret_from_fork; //确定返回地址

9.当程序跳转到syscall_exit,就不能再继续gdb跟踪调试,输入finish使得进程运行完。

总结:

1.Linux通过复制父进程来创建一个新进程,通过调用do_fork来实现。

2.Linux为每个新创建的进程动态地分配一个task_struct结构。

3.为了把内核中的所有进程组织起来,Linux提供了几种组织方式,其中哈希表和双向循环链表方式是针对系统中的所有进程(包括内核线程),而运行队列和等待队列是把处于同一状态的进程组织起来。

4.fork()函数被调用一次,但返回两次。

转载于:https://www.cnblogs.com/lhc-java/p/5340414.html

Linux第六周学习总结——进程额管理和进程的创建相关推荐

  1. 20135337朱荟潼 Linux第六周学习总结——进程的描述和进程的创建

    朱荟潼 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课http://mooc.study.163.com/course/USTC 1000029000 第六周 进程的描述 ...

  2. 2018-2019-1 20165214 《信息安全系统设计基础》第六周学习总结

    20165214 2018-2019-1 <信息安全系统设计基础>第六周学习总结 教材学习内容总结 1.输入操作是从I/O设备复制数据到主存,而输出操作是从主存复制数据到I/O设备 2.U ...

  3. 2018-2019-1 20165203 《信息安全系统设计基础》第六周学习总结

    2018-2019-1 20165203 <信息安全系统设计基础>第六周学习总结 教材学习内容总结 重要知识点 I/O:在主存和外部设备(例如磁盘存储器.终端和网络)之间复制数据的过程. ...

  4. 20155305乔磊2016-2017-2《Java程序设计》第六周学习总结

    20155305乔磊2016-2017-2<Java程序设计>第六周学习总结 教材学习内容总结 InputStream与OutputStream 串流设计 1.串流:Java将输入/输出抽 ...

  5. 20155322 2017-2018-1《信息安全系统设计》第六周学习总结

    # 20155322 2017-2018-1<信息安全系统设计>第六周学习总结 教材学习内容总结 第八章: 什么是异常控制流: 控制流:控制转移序列. 控制转移:从一条指令到下一条指令. ...

  6. 达拉草201771010105《面向对象程序设计(java)》第十六周学习总结

    达拉草201771010105<面向对象程序设计(java)>第十六周学习总结 第一部分:理论知识 1.程序与进程的概念: (1)程序是一段静态的代码,它是应用程序执行的蓝 本. (2)进 ...

  7. 杨玲 201771010133《面向对象程序设计(java)》第十六周学习总结

    <面向对象程序设计(java)>第十六周学习总结 第一部分:理论知识学习部分 1.程序是一段静态的代码,它是应用程序执行的蓝本.进程是程序的一次动态执行,它对应了从代码加载.执行至执行完毕 ...

  8. 20159313网络攻击与防范第六周学习总结

    课本第五章TCP/IP网络协议攻击总结 1.网络安全属性 网络安全是指网络系统的硬件.软件及其系统受到保护,不受偶然的或者恶意的原因而遭到破坏.更改.泄漏,系统连续可靠正常运行,网络服务不被中断.网络 ...

  9. 20169212 2016-2017-2 《网络攻防实践》第六周学习总结

    20169212 2016-2017-2 <网络攻防实践>第六周学习总结 教材学习内容总结 本周学习了第五.六章内容,主要包含TCP/IP网络协议攻击及网络安全防范技术.了解了TCP/IP ...

最新文章

  1. Android踩坑日记:使用Fesco图片加载库在GridView上的卡顿优化
  2. 读入一个数列和N值,返回按优先级排序的N个数 满足...Python解法
  3. GDCM:将文件封装在RawData中的测试程序
  4. php 扩展apc 参数优化
  5. Javascript 获取字符串字节数的多种方法
  6. 初探函数式编程和面对对象式编程
  7. Oracle忽略hint的几种情形
  8. 课程设计之第二次冲刺----第一天
  9. Atitit.异步编程技术原理与实践attilax总结
  10. 存储区域网络(Storage Area Network,简称SAN)
  11. 八皇后问题(回溯算法)
  12. matlab输入syms有错,matlab的问题:当我输入 syms x;f=x*x 按回车后就出错,这是怎么回事啊?请大家帮帮...
  13. python 图片识别_Python—识别图片中的文字
  14. python考试名词解释_程序设计(python)_章节测验,期末考试,慕课答案查询公众号...
  15. 教师查询系统C语言,C语言教师管理系统代码
  16. 走进Prime Time系列 - PT的Timing exception 03
  17. 溢出overflow和空间定位z-index
  18. html css设计网页初步
  19. 变异系数(测算数据离散程度相对指标)
  20. 给武则天找凤凰的java游戏,女皇武则天:我不愿被 extends

热门文章

  1. Python之与众不同
  2. mahout基于Hadoop的CF代码分析(转)
  3. PHP闭包(Closure)初探
  4. WAS6集群部署及初步测试
  5. Spring AOP之ThrowsAdvice
  6. 在国外读phd 的时候和supervisor沟通的时候需要注意的点
  7. 【转】光栅化操作阶段
  8. Java中的Runnable、Callable、Future、FutureTask
  9. 谈论linux同组多用户操作问题
  10. 从零开始学 Web 之 DOM(六)为元素绑定与解绑事件