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

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

一、 进程的描述

  • 进程控制块PCB——task_struct

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

  • struct task_struct数据结构很庞大
  • Linux进程的状态与操作系统原理中的描述的进程状态似乎有所不同,比如就绪状态和运行状态都是TASK_RUNNING,为什么呢?
  • 进程的标示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一个进程的源代码
  • 回顾:
    • startkernel创建了cpuidle,也就是0号进程。而0号进程又创建了两个线程,一个是kernel_init,也就是1号进程,这个进程最终启动了用户态;
    • 另一个是kthreadd。这就是“道生一,一生二”。0号进程是固定的代码;
    • 1号进程是通过复制0号进程PCB之后在此基础上做修改得到的。
  • iret与int 0x80指令对应,一个是弹出寄存器值,一个是压入寄存器的值
  • 如果将系统调用类比于fork();那么就相当于系统调用创建了一个子进程,然后子进程返回之后将在内核态运行,而返回到父进程后仍然在用户态运行

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)
{
/* 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");
}
}

`

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

  1. fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;
  2. Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架:

    • 复制一个PCB——task_struct
    • err = arch_dup_task_struct(tsk, orig);
    • 要给新进程分配一个新的内核堆栈
    • `ti = allocthreadinfo_node(tsk, node);

      tsk->stack = ti;

      setupthreadstack(tsk, orig); //这里只是复制,而非复制内核堆`

  3. 要修改复制过来的进程数据,比如pid、进程链表等等都要改改吧,见copy_process内部。
  4. 从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和taskstruct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copythread in copy_process
  5. *childregs = *current_pt_regs(); //复制内核堆栈
  6. childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
  7. p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
  8. p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

使用gdb跟踪创建新进程的过程

  • 更新menu内核,然后删除test_fork.c以及test.c(以减少对之后实验的影响
  • 编译内核,可以看到fork命令
  • 启动gdb调试,并对主要的函数设置断点
  • 在MenuOS中执行fork,就会发现fork函数停在了父进程中
  • 继续执行之后,停在了dofork的位置。然后n单步执行,依次进入copyprocess、duptaskstruct。按s进入该函数,可以看到dst = src(也就是复制父进程的struct)
  • 在copythread中,可以看到把taskpg_regs(p)也就是内核堆栈特定的地址找到并初始化
  • 到了159、160行的代码就是把压入的代码再放到子进程中:

     `*children = *current_pt_regs();
    
      childregs->ax = 0;`
  • 164行,是确定返回地址 p->thread.ip = (unsigned long) ret_from_fork;
  • 最后输入finish运行完毕。

总结

本周主要就是课本的进程一章的拓展,通过实践来更加的运用完整,很有趣。

20135239益西拉姆 Linux内核分析 进程的描述和进程的创建的更多相关文章

  1. 20135239 益西拉姆 linux内核分析 进程的切换和系统的一般执行过程

    week 8 进程的切换和系统的一般执行过程 [ 20135239 原文请转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

  2. 20135239 益西拉姆 linux内核分析 可执行程序的装载

    益西拉姆 + 原创作品请勿转载 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” week 7 可 ...

  3. 20135239益西拉姆 Linux内核分析 汇编一个简单的c程序并分析其指令过程

    益西拉姆+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 第一周linux内核分析 学习笔记 一.计算机 ...

  4. 20135239益西拉姆 Linux内核分析 操作系统是怎样工作的?

    益西拉姆+ 原创作品+ <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 堆栈 堆栈是C语言程序运行时 ...

  5. 20135239 益西拉姆 linux内核分析 跟踪分析Linux内核的启动过程

    回顾 1.中断上下文的切换——保存现场&恢复现场 本节主要课程内容 Linux内核源代码简介 1.打开内核源代码页面 arch/目录:支持不同CPU的源代码:其中的X86是重点 init/目录 ...

  6. 20135239 益西拉姆 linux内核分析 读书笔记之第四章

    chapter 4 进程调度 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 多任务系统可以划分为两类: - 非抢占式多任务: - 进程会一直执行直到自己主动停止运行(这一 ...

  7. 20135239 益西拉姆 linux内核分析 扒开系统调用的三层皮(下)

    一. 给MenuOS增加time-asm命令 代码解释 1.-rf:强制删除 2.clone :重新克隆 3.time-asm:显示系统时间的汇编形式 给MenuOS增加time和time-asm命令 ...

  8. 20135239 益西拉姆 linux内核分析 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    https://drive.wps.cn/preview#l/759e32d65654419cb765da932cdf5cdc 本次直接在wps上写的,因为不能连同图片一起粘贴过来,一个一个粘比较费时 ...

  9. 《Linux内核分析》 第六节 进程的描述和进程的创建

    <Linux内核分析> 第六节 进程的描述和进程的创建 20135307 张嘉琪 原创作品转载请注明出处 +<Linux内核分析>MOOC课程http://mooc.study ...

随机推荐

  1. WebSocket抓包分析

    转载自:https://www.cnblogs.com/songwenjie/p/8575579.html Chrome控制台 (1)F12进入控制台,点击Network,选中ws栏,注意选中Filt ...

  2. windows离线补丁包下载路径-云盾安骑士

    我们有一台阿里云服务器,只有内网可以访问,无外网资源. 阿里云账户邮箱反复收到阿里云云盾的漏洞报警通知,推荐安装安骑士组件. 安骑士组件是收费服务.阿里云服务器,无法连上外网,无法自动安装补丁.需要将 ...

  3. Linux 磁盘与文件系统(EXT2)简介

    Linux 中,一切(或几乎一切)都是文件. 一.Linux 磁盘分区与文件系统 1.1 磁盘分区 磁盘的分区主要分为主分区和扩展分区 1)主分区:总共最多只能有四个主分区: 2)扩展分区:只能有一个 ...

  4. tree命令详解

    基础命令学习目录首页 原文链接:http://man.linuxde.net/tree -a:显示所有文件和目录:-A:使用ASNI绘图字符显示树状图而非以ASCII字符组合:-C:在文件和目录清单加 ...

  5. iOS 静态库生成(引用第三方SDK、开源库、资源包)

    一.静态库创建 打开Xcode, 选择File ----> New ---> Project  选择iOS ----> Framework & Library ---> ...

  6. 阿里nas挂载错误

    报错如下,解决:yum install nfs-utils 即可 mount: wrong fs type, bad option, bad superblock on 12080482f3-qra4 ...

  7. Notes of Daily Scrum Meeting(11.11)

    Notes of Daily Scrum Meeting(11.11) 今天是11月11号光棍节,不知道大家的购物热情被点燃没有,有没有买到自己心仪的东西.额,今天我们的团队任务进度和昨天差不多, 每 ...

  8. Daily Srum 10.21

    到目前为止,我们组处在学习阶段,很多知识点都还不太清楚,所以现在我们还在看相关书籍和博客,任务. 而我们此间主要是在阅读一些材料: 陈谋一直在看学长的代码,其中C#的很多方式我都不太明白(尽管和Jav ...

  9. 【CSAPP笔记】10. 代码优化

    写程序的主要目标是使它在所有可能的情况下都能正确运行(bug free),一个运行得很快但有 bug 的程序是毫无用处的.在 bug free 的基础上,程序员必须写出清晰简洁的代码,这样做是为了今后 ...

  10. Week2:阅读笔记与思考

    <构建之法>这本书的内容通俗易懂,每一个知识点都有许多事例佐证,阅读起来不像其他教科书那样枯燥无聊.但阅读过第一.二.十六章之后还是产生了几个疑问,以及更深层次的思考. 第一章 问题1: ...