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进程创建的一篇简短博文,希望对大家的操作系统学习有所帮助,大家共同进步,一同进化

相关推荐
知已难寻2 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
默|笙2 小时前
【Linux网络】网络层协议 IP(1)理解报头、网段划分
linux·网络·tcp/ip
修己xj5 小时前
nslookup 使用指南:两种模式与常用查询技巧
linux
唠玖馆7 小时前
文件系统详解
linux·文件系统·ext2
GeW7 小时前
当Linux内核开始“确定性”,制造高端化才有了底层语法
linux
星恒随风9 小时前
MySQL 从零入门(三):表的约束详解
linux·服务器·数据库·笔记·mysql
Alluxio9 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
StarsGreen11 小时前
libva在intel平台上的前端流程简介
linux
坤坤子吖13 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
Sayai13 小时前
Neo4j 图数据质量检查实战:环路检测、孤立节点与连通分量,两条 Cypher 引出的数据体检清单(含变长路径性能陷阱)
运维·neo4j·图数据库·数据质量·cypher