对于子进程生成过程的理解

目录

内存管理

实现shell

  生成子进程

  子进程号

  进程代码、数据、栈从何而来

  execv如何组织加工进程需要的数据

  子进程的的LDT段及LDT在GDT的段选择子

  共享打开的文件

从终端接收命令


内存管理

  说是内存管理,其实仅仅是为了实现shell、生成子进程而对内存空间简单的划分了一下。用作者的话说就是划格子,每个进程划出来1M的内存装载镜像。还有页表也都是线性映射,线性地址和物理地址都是一致的。但是不管多么简单,能达到目的就是好的设计。


实现shell

  想一想shell是什么东西?好像就是能接受用户输入的命令然后执行这个命令。那么”执行这个命名”是什么意思?就是说这个命令其实是一个程序的名字,执行它就是生成一个子进程来运行这个程序,而且这个程序要放在系统能搜索的几个路径下。

生成子进程

  为了shell接收和响应用户的一次输入后依然能够继续处理用户的下次输入,那就必须要要通过某一种方式让shell走两条分支,一条是去处理上次的用户输入,还有一条分支是继续等待用户的下次输入,如果把这两个分支全部都杂糅到给shell,恐怕逻辑会很复杂。

  我不知道当初的子进程概念是由于什么需求而引出的。但是它用来配合shell的实现是再合适不过了。我们仅仅需要在代码上安排两条分支,在进入分支之前,克隆一个子进程出来,子进程进入处理用户的的分支,而shell本身则可以继续接收用户的输入。

子进程号

  那么用什么来分流父子进程呢?也就是克隆出了一个进程后,怎么确定哪个是父进程哪个是子进程呢?这就是子进程号的功能,内核将子进程号返回给父进程,返回给子进程的却是0,所以通过这种方式,分流了父子进程逻辑。

进程代码、数据、栈从何而来

  那进程需要的数据从哪里来呢?那就是execv函数的功能了,其实shell的代码还是不复杂的,仅仅是将用户的输入用空格分隔开来,将每个字符串你的其实地址赋值给一个指针数组的相应元素。然后传给execv函数,剩下的就是execv函数的职责。

execv如何组织加工进程需要的数据

  相比较于linux 0.12来说,不用考虑太大的文件,不用考虑页表映射,更不用考虑缺页异常,仅仅是把逻辑地址加上每个进程的线性地址就是指令、数据或者栈的物理地址了。

  代码、数据:读取命令程序在硬盘上的镜像文件,然后按照elf文件的格式放到子进程空间的相应位置。

  栈:shell传递过来的是参数的指针数组,字符串本身还在另一段地址上,execv要做的就是把指针数组和字符串本身组合到一块,这样内核随后复制参数给子进程方便一些,不用一个字符串一个字符串的复制了。全部一股脑的都拿过来用就好了。

子进程的的LDT段及LDT在GDT的段选择子

  不知道大家有没有想过,用LDT来寻址,那LDT本身是在进程表里面存放的,我们克隆子进程的时候可没有克隆进程表啊,只是在进程表数组中找了一个空闲的表项给子进程用。而且克隆的时候也没有动GDT,那子进程是如何能正确运转呢?

  这又是一个鸡和蛋的问题?既然大家都相互牵扯纠缠不清,倒不人为的把最开始的状态确定下来,以便后来的流程能运转起来。

  那就提前在初始化过程中,把进程表中的LDT和GDT中LDT描述符都初始化好,等分配给子进程的时候就可以直接用了。

共享打开的文件

  还有一个问题,就是父进程打开的文件,子进程同样继承了下来,这个时候就要告诉TASK_FS了,把父进程的文件描述符的引用数都加1。


从终端接收命令

那么shell在从终端接受用户的输入时候,是如何构造指针数组的呢?

  1. 将用户的输入都读到一个缓冲区上
  2. 定义一个指针数组
  3. 按照空格分隔字符串,将每一个字符串的起始地址赋值给2中指针数组相应的位置,这样最初的栈数据就有了。到execv中只需要把两者放到一起就好了。
时间: 2024-10-23 03:39:58

对于子进程生成过程的理解的相关文章

Nginx 多进程连接请求/事件分发流程分析

Nginx使用多进程的方法进行任务处理,每个worker进程只有一个线程,单线程循环处理全部监听的事件.本文重点分析一下多进程间的负载均衡问题以及Nginx多进程事件处理流程,方便大家自己写程序的时候借鉴. 一.监听建立流程 整个建立监听socket到accept的过程如下图: 说明: 1.main里面调用ngx_init_cycle(src/core/ngx_cycle.c),ngx_init_cycle里面完成很多基本的配置,如文件,共享内存,socket等. 2.上图左上角是ngx_ini

linux安全第六周总结

20135336 王维臻 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.总结部分 操作系统内核三大功能: 进程管理,内存管理,文件系统 最核心的是进程管理,为了管理,首先要对每一个进程进行描述.进程描述符提供了所有内核需要了解的信息. 进程控制模块:task_struct(抽象task_struct的简化图) next_task,prev_task进程链表的管理 tty_struct控制台 fs_stru

linux及安全第六周总结——20135227黄晓妍

总结部分: 操作系统内核三大功能: 进程管理,内存管理,文件系统 最核心的是进程管理 为了管理,首先要对每一个进程进行描述.进程描述符提供了所有内核需要了解的信息. 进程控制模块:task_struct(抽象task_struct的简化图) next_task,prev_task进程链表的管理 tty_struct控制台 fs_struct文件系统描述 file_struct打开的文件描述符 mm_struct内存管理的描述 signal_struct信号的描述 Linux-3.18.6/inc

Unix环境——进程管理小结(一)

一.进程的基本概念 1.进程与程序 程序是存储在磁盘上的文件,它是包含要执行的机器指令和数据的静态实体. 进程是一个正在运行的程序,一个程序可能包含多个进程(多任务.多进程),进程在操作系统中是一个执行任务的单位. 2.进程的分类 交互进程:需要用户输入数据,也会显示一些结果给用户看. 批处理进程:用来执行脚本的进程,例如Makefil. 守护进程:它是一种一直活跃的进程,一般是后台的,由操作系统启动时通过开过开机脚本加载或由超级用户加载. 二.在linux下的一些关于进程的命令 ps:显示当用

1shell变量的作用域

Shell 局部变量 Shell 全局变量 shell全局变量的易错点: linux shell中./a.sh , sh a.sh , source a.sh, . ./a.sh的区别 Shell 环境变量 shell配置文件 Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围).Shell 变量的作用域可以分为三种: 有的变量只能在函数内部使用,这叫做局部变量(local variable): 有的变量可以在当前 Shell 进程中使用,这叫做全局变量(g

Shell变量的作用域:Shell全局变量、环境变量和局部变量

Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱.但是如果同一个班级中有两个叫小明的同学,就必须用类似于“大小明”.“小小明”这样的命名来区分他们. Shell 变量的作用域可以分为三种: 有的变量只能在函数内部使用,这叫做局部变量(local variable)

一个关于系统父进程与子进程的理解案例

代码实例 #include<stdio.h> #include<unistd.h> /*程序输出结果 主进程id:8377 进程id:8377,父进程id:3290,插曲 进程id:8377,父进程id:3290,Bye 进程id:8378,父进程id:8377,hello 进程id:8378,父进程id:8377,Bye 进程id:8379,父进程id:1397,插曲 进程id:8379,父进程id:1397,Bye 进程id:8380,父进程id:1397,hello 进程id

八幅漫画理解使用 JSON Web Token 设计单点登录系统

原文出处: John Wu 上次在<JSON Web Token – 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家理解如何设计正常的用户认证系统,然后再延伸到单点登录系统. 如果还没有阅读<JSON Web Token – 在Web应用间安全地传递信息>,我强烈建议你花十分钟阅读它,理解JWT的生成过程和原理. 用户认证八步走 所谓用户认证(Authentication),就是让用户登录,并且在接下来的一段时

Linux系统理解以及Linux系统学习心得

原创作品转载请注明出处  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 作者:严哲璟 说一下我对Linux系统的理解 1.加载Linux内核准备:在加载基本输入输出模块(BIOS)之后,从磁盘的引导扇区读入操作系统的代码文件块到内存中,之后开始整个系统的初始化. 2.main.c的start_kernel函数是整个操作系统的入口,这也与Linux是基于C语言的特性相符,start_kernel具体做的动作很多