《Linux内核分析》 第六节 进程的描述和进程的创建
《Linux内核分析》 第六节 进程的描述和进程的创建
20135307 张嘉琪 原创作品转载请注明出处 +《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
一、进程的描述
操作系统的三大功能:
- 进程管理(核心)
- 内存管理
- 文件系统
进程描述符task_struct数据结构
进程控制块PCB——task_struct
为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。
- struct task_struct数据结构很庞大
- 进程的标示pid
- 所有进程链表struct list_head tasks;
- 内核的双向循环链表的实现方法 - 一个更简略的双向循环链表
程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。进程描述符中有几个域用来表示这样的关系
Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info和进程的内核堆栈
二、进程的创建
进程的创建概览及fork一个进程的用户态代码
- 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");
}
}
创建新进程的框架
- fork,vfork,clone都可以创建新进程,他们都是通过调用do_fork来实现的。
- copy_process修改复制的PCB以适应子进程的特点,也就是子进程的初始化

分配一个新的内核堆栈(用于存放子进程数据)
- 内核堆栈的一部分也要从父进程中拷贝
- Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架: 复制一个PCB——taskstruct
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();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和taskstruct中thread记录的sp和ip的一致性问题,这是在哪里设定的?
copythread in copy_process
阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;
实验报告
- 特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
- 答:
1 *childregs = *current_pt_regs(); //复制内核堆栈
2 childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
3
4 p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
5 p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址
即新进程是从ret_from_fork开始执行的。
- 分析fork函数对应的内核处理过程sysclone,理解创建一个新进程如何创建和修改taskstruct数据结构
由于创建新进程是由复制当前进程实现的,所以父子进程的PCB_task_struct是一样的。但是进程pid,内核堆栈,进程链表和ip、sp的位置是不能一样的, 他们是不同的进程。
- 使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解
- 更新menu内核,然后删除test_fork.c以及test.c

- 编译内核,可以看到fork命令

- 启动gdb调试,并对重要函数设置断点

- 继续执行之后,停在了do_fork的位置。然后n单步执行,依次进入copy_process、dup_task_struct。按s进入该函数,可以看到dst =src(也就是复制父进程的struct)



总结
Linux通过复制父进程来创建一个新进程,通过调用do_fork来实现,Linux为每个新创建的进程动态地分配一个task_struct结构.为了把内核中的所有进程组织起来,Linux提供了几种组织方式,其中哈希表和双向循环链表方式是针对系统中的所有进程(包括内核线程),而运行队列和等待队列是把处于同一状态的进程组织起来
《Linux内核分析》 第六节 进程的描述和进程的创建的更多相关文章
- LINUX内核分析第六周学习总结——进程的描述与创建
LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...
- LINUX内核分析第六周学习总结——进程的描述和进程的创建
LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- linux内核分析第六周学习笔记
LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- Linux内核分析实验六
Linux内核分析实验六 进程控制块PCB——task_struct(进程描述符) 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. struct task_s ...
- Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...
- Linux内核分析第六周学习总结:进程的描述和进程的创建
韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.进程的描述 ...
- 20135327郭皓--Linux内核分析第六周 进程的描述和进程的创建
进程的描述和进程的创建 一.进程的描述 操作系统三大功能: 进程管理 内存管理 文件系统 进程描述符task_struct数据结构 task _ struct:为了管理进程,内核必须对每个进程进行清晰 ...
- "Linux内核分析"第六周实验报告
张文俊 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1.进程的描述 ...
- 【MOOC EXP】Linux内核分析实验六报告
程涵 原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的描述和进程的创建 知识点梳理: ...
随机推荐
- 【2017下集美大学软工1412班_助教博客】团队编程2-需求分析&原型设计团队成绩公示
作业要求 团队作业2:需求分析&原型设计 团队评分结果 团队名称 作业标题 Total DY SM NABCD FG YX GF SP PHILOSOPHER 团队作业2--需求分析 5.5 ...
- php 两个二维数组重组新数组,数组下标不同
Array ( [0] => Array ( [PosNum] => 27025008 [start_time] => 20180328164929 [type] => 0 ) ...
- Postman-自动化传参
一,自动化传参 在实现接口自动测试的时候,会经常遇到接口参数依赖的问题,例如调取登录接口的时候,需要先获取登录的key值,而每次请求返回的key值又是不一样的,那么这种情况下,要实现接口的自动化,就要 ...
- Dubbo -- 系统学习 笔记 -- 安装手册
安装手册 示例提供者安装 示例消费者安装 Zookeeper注册中心安装 Redis注册中心安装 简易注册中心安装 简易监控中心安装 管理控制台安装 推荐使用Zookeeper注册中心 你可以只运行D ...
- android 自定义listview无法响应点击事件OnItemClickListener
如果你的自定义ListViewItem中有Button或者Checkable的子类控件的话,那么默认focus是交给了子控件,而ListView的Item能被选中的基础是它能获取Focus,也就是说我 ...
- C#游戏开发中快速的游戏循环
C#游戏开发中快速的游戏循环的实现.参考<精通C#游戏编程>一书. using System; using System.Collections.Generic; using System ...
- Ubuntu16.04 kaldi的简单配置
1.什么是kaldi kaldi是使用c++写的语音识别的工具,apache 授予了v2.0的证书(果真应验,apache旗下无弱将).kaldi旨在供语音识别研究员使用.kaldi在目标和范围上和H ...
- 一,ESP8266下载和刷固件(基于Lua脚本语言)
用自己的小板测试...... 安排上呢 一, ESP8266下载和刷固件(Lua开发----体验一下lua开发的魅力所在) 二, 控制一个灯亮灭 三, TCP服务器 四, TCP客户端 五, UDP ...
- 大数据入门第二十二天——spark(一)入门与安装
一.概述 1.什么是spark 从官网http://spark.apache.org/可以得知: Apache Spark™ is a fast and general engine for larg ...
- 7、mysql高级特性
7.1.分区表 7.1.1 分区表的原理 7.1.2分区表的类型 7.1.3如何使用分区表 7.1.4什么情况下出问题 7.1.5查询优化 使用explain 来分析sql使用的分区表 7.1.6合并 ...