Linux进程创建详解

大家好,这里是Qyynerboomer,今天为大家讲解一下Linux基础之进程创建。

一.什么是进程:

进程就是正在运行的实例,简单来说,就是程序启动后,在内存里运行的程序的副本,主要包含以下几种元素:进程控制块,代码,数据。

二.为什么会存在进程控制块:

我们的操作系统上运行着很多的进程,必须要将他们行之有效地管理起来,操作系统于是做了以下操作:设定出进程控制块,这个进程控制块中包含着有关于进程的一切信息,并将其作为一个节点纳入名为运行队列,等待队列的链表中进行管理,这样,对于进程本身的管理(如唤醒进程,阻塞进程等等)就转换成了对于各种链表的增删查改,如果我们想让一个进程运行,操作系统就会将该进程的进程控制块纳入运行队列中进行管理,如果一个进程因为io阻塞了,那么操作系统就会将其纳入阻塞队列中进行管理。

三.如何创建进程:

在Linux系统中,我们使用fork函数来创建进程,接下来我们详细讲解一下fork()函数的功能:

fork函数是在用户态(普通用户可以进入的权限受限模式)可以调用的系统调用。底层封装了内核函数do_fork()。本质上是由这个do_fork函数来完成进程的创建。进程创建这个过程本身是在内核完成的。

do_fork函数做了以下几件事情:

1.调用alloc_task_struct()函数来获得8kb的union_thread_union内存区(在内核区);用这个东西来存储进程的进程控制块和内核栈(进程是可以在用户态和内核态之间切换的,这个东西就是用来保存进程在内核态执行的临时数据)。

2.do_fork内部定义的进程指针指向父进程的进程控制块,将其完全拷贝到子进程中。

3.进行检查:当前用户所拥有的进程数量是否超过了系统给其分配资源的限制。

4.此时子进程只是复制了父进程的信息,并没有进行本身的初始化,所以子进程的状态就会被设定为TASK_UNINTERRUPTIBLE,以保证它不会马上投入运行。

5.调用get_pid函数来分配一个有效的PID(注意这个函数是一个内核函数,只能在内核里面运行,是用来分配进程PID的,我们平常学的系统调用时getpid(),是用来查询进程的PID的)。

6.子进程的东西有些是不能和父进程一模一样的,比如子进程的父进程,子进程的兄弟进程等等,这时候就要进行更新,让子进程的信息不同于父进程。

7.所有东西准备好之后,子进程的进程控制块就被插入了内核全局进程链表和pidhash哈希表。

8.把子进程PCB的状态域设置成TASK_RUNNING,并调用wake_up_process( )把子进程插入到运行队列链表。

9.让父进程和子进程平分剩余的时间片。

10.对于父进程,函数会返回子进程的pid,而对于子进程,如果子进程创建成功,那么函数就会返回0,如果创建失败,那么函数就会返回一个负值来标识错误。

以上就是进程创建的全部过程

四.一些小疑问的讲解

可能大家已经注意到,当我们完成进程的创建的时候,会将进程同时插入两个数据结构当中,一个是链表结构,一个是哈希表结构,,一个节点怎么会同时隶属于两种结构呢?这里我们就要提到Linux一个特殊的设计,将节点作为进程控制块的一部分封装进进程控制块,这听起来十分抽象,但其实非常简单:

如图所示,进程控制块里面又封装了一个新的结构体,我们来看看这个结构体内部的结构

这个函数体内部十分简洁,仅仅包含两个指针,这看起来是不是非常熟悉,这就是我们在数据结构阶段接触到的双向链表指针结构啊,所以进程控制块内部封装了很多类似的节点,包括这样的双向链表指针节点,还有运行队列,等待队列等等,所以进程控制块可以做到隶属于多个数据结构。

那么这个pidhash哈希表有什么用?

我们都知道,链表的查询效率是比较低下的,而哈希表的查询效率是很高的,如果能知道进程的pid那么几乎是O(1)的时间复杂度我们就可以查询到我们所需要的进程控制块,那么是如何做到的呢?

首先操作系统定义了这样的一个宏,传入pid,也就是x,会根据下面的规则自动计算应该插入的下标位置

复制代码
#define pid_hashfn(x) \ 
	         ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))

之后就根据这个位置将进程控制块节点插入就好了。

可能大家会有疑惑,这不会产生冲突吗,难道不会有两个不同的pid的值,经过了上述运算之后,得到的下标是一样的吗?这样的情况当然会出现,操作系统的设计者也早就想到了这个问题,他们给出的解决方案是这个pidhash哈希表,每个元素并不是一个单纯的进程控制块节点,而是链表结构,所以每个哈希节点都是一条链表,这样的结构还有一种名字,叫做**哈希桶;**经过运算后相同的进程控制块,就插入对应的哈希桶当中,这样就解决了冲突。

以上就是关于linux进程创建的一篇简短博文,希望对大家的操作系统学习有所帮助,大家共同进步,一同进化

相关推荐
leiming611 小时前
linux 进程学习之信号
linux·运维·学习
若风的雨11 小时前
linux Page Table 和 TLB 操作总结
linux
AlenTech11 小时前
如何解决Ubuntu中使用系统pip报错的问题,error: externally-managed-environment
linux·ubuntu·pip
被遗忘的旋律.11 小时前
Linux驱动开发笔记(二十四)——(上)IIO + icm20608驱动
linux·驱动开发·笔记
Y1rong11 小时前
刷机与系统启动
linux
zandy101111 小时前
衡石科技Agentic BI实战:基于自然语言查询与自动化分析的新一代智能系统
运维·科技·自动化·agentic bi
南梦浅11 小时前
[特殊字符]️ Docker 镜像加速器完整配置流程下面是在 CentOS 7 系统上配置 Docker 镜像加速器的完整步骤
linux·docker·centos
AiTEN_Robot11 小时前
机器人叉车的技术落地与效率挖掘:仓储自动化的效能提升方案
运维·机器人·自动化
卓应米老师11 小时前
【网络配置实战】堆叠的配置
运维·服务器·网络·华为认证
乐维_lwops11 小时前
告别机房管理 “盲盒”!实现主动预判的可视化运维
运维