进程原理及系统调用

我也要当昏君 原创小能手 2022-04-05 16:54:19

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习
@

进程原理及系统调用

  • 进程概念
  • 进程四要素与线程区别
  • 进程生命周期
  • task_struct数据结构
  • 进程优先级
  • 进程系统调用
  • 进程复制
  • 内核线程
  • 退出进程

进程概念

操作系统作为硬件的使用层,提供使用硬件资源的能力,进程作为操作系统使用层, 提供使用操作系统抽象出的资源层的能力。
进程:是指计算机中已运行的程序。进程本身不是基本的运行单位,而是线程的容器。 程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。

  • 进程是处于执行时期的程序。
  • 内核调度的对象是线程,不是进程。

进程四要素与线程区别

  1. 有一段程序代其执行;
  2. 有进程专用的系统堆栈空间;
  3. 在内核有task_struct数据结构;
  4. 进程有独立的存储空间,拥有专有的用户空间;
    如果具备前面三条而缺少第四条,那就称为"线程"。如果完全没有用户空间,那就称为"内核线程";如果共享用户空间则就称为"用户线程"。

进程生命周期

Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行。而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件时会属于不同的状态。进程之间的状态关系:
运行 :该进程此刻正在执行。
等待:进程能够运行,但没有得到许可,因为CPU分配给另一个进程。调度器可以在 下一次任务切换时选择该进程。
睡眠 :进程正在睡眠无法运行,因为它在等待一个外部事件。调度器无法在下一次任 务切换时选择该进程。

【进程状态之间转换】如下:

在这里插入图片描述

task_struct数据结构

Linux内核涉及进程和程序的所有算法都围绕一个名为task_struct的数据结构建立,该结构定义在include/linux/sched.h中。这是系统中主要的一个结构。在阐述调度器的实现之前,了解一下Linux管理进程的方式是很有必要的。 task_struct包含很多成员,将进程与各个内核子系统联系,task_struct定义如下:

在这里插入图片描述

请添加图片描述

进程优先级

并非所有进程都具有相同的重要性。除了大多数我们所熟悉的进程优先级之外,进程 还有不同的关键度类别,以满足不同需求。首先进行比较粗糙的划分,进程可以分为实时进程 和非实时进程(普通进程)。 实时进程优先级(0-99)都比普通 进程的优先级(100-139)高。当系统中有实时进程 运行时,普通进程几乎无法分到赶时间片(只能分到5%的CPU时间)。

进程系统调用

讨论fork和exec系列系统调用的实现。通常这些调用不是由应用程序直接发出的,而是通过一个中间层调用,即负责与内核通信的C标准库。从用户状态切换到核心态的方法,依不同的体系结构而各有不同。

在这里插入图片描述

进程复制

传统的UNIX中用于复制进程的系统调用是fork。但它并不是Linux为此实现的唯一调用, 实际上Linux实现了3个
(1) fork是重量级调用,因为它建立了父进程的一个完整副本,然后作为子进程执行。 为减少与该调用相关的工作量,Linux使用了写时复制(copy-on-write)技术。
(2) vfork类似于fork,但并不创建父进程数据的副本。相反,父子进程之间共享数据。 这节省了大量CPU时间(如果一个进程操纵共享数据,则另一个会自动注意到)。
(3) clone产生线程,可以对父子进程之间的共享、复制进行精确控制。

在这里插入图片描述


只有在不得不复制数据内容时才去复制数据内容,这就是写时复制核心思想,可以看到因为修改页Z导致子进程不得不去复制原页Z来保证父子进程互不干扰
内核只为新生成的子进程创建虚拟空间结构,它们来复制于父进程的虚拟结构,但是不为这些分配物理内存,它们共享父进程的物理空间,当父进程中有更改相应段的行为发生时,再为子进程相应段分配物理空间

【写时复制】
内核使用了写时复制(Copy-On-Write,COW)技术,以防止在fork执行时将父进程的所有数据 复制到子进程。在调用fork时,内核通常对父进程的每个内存页,都为子进程创建一个相同的副本。
【执行系统调用】
fork、vfork和clone系统调用的入口点分别是sys_fork、sys_vfork和sys_clone函数。其定义依赖于 具体的体系结构,因为在用户空间和内核空间之间传递参数的方法因体系结构而异。
【do_fork实现】
所有3个fork机制最终都调用kernel/fork.c中的do_fork(一个体系结构无关的函数),其代码流程 如图所示。

在这里插入图片描述

在这里插入图片描述

内核线程

内核线程是直接由内核本身启动的进程。内核线程实际上是将内核函数委托给独立的进程,与系统中其他进程“并行”执行(实际上,也并行于内核自身的执行)。内核线程经常称之为(内核)守护进程。它们用于执行下列任务。
周期性地将修改的内存页与页来源块设备同步(例如,使用mmap的文件映射)。
如果内存页很少使用,则写入交换区。
管理延时动作(deferred action)。
实现文件系统的事务日志。

退出进程

进程必须用exit系统调用终止。这使得内核有机会将该进程使用的资源释放回系统。见kernel/exit.c------>do_exit。简而言之, 该函数的实现就是将各个引用计数器减1,如果引用计数器归0而 没有进程再使用对应的结构,那么将相应的内存区域返还给内存管理模块。

在这里插入图片描述

...全文
2104 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
 本课程的主题是: 透析Linux系统编程    不同于市面上的课程,只会把核心主题放到函数的讲解,本课程的核心主题是 Linux系统编程的经验总结 ;    当你在系统编程中,调用一个系统调用来解决问题时,是否考虑过 该系统调用是否会对系统性能带来影响?是否还有最优的方式?    当你在系统编程过程中,遇到问题,是否只是检查代码逻辑,而不会去深入底层去查找问题 ?    本课程将一一解决系统编程带给你的难点,疑点?    比如控制文件IO章节,给出系统文件操作的默认行为,应用中如何修改这些行为,给出文件IO操作的最优方式;   比如系统调用,给出系统调用原理系统调用的正确使用方式等   比如进程实现,结合底层,对比线程,深入理解两者;给出进程使用经验总结;   比如线程同步,不仅引出互斥锁 条件变量 自旋锁 读写锁使用方式,同时给出各个机制的应用场景 ;   比如 进程间通信,引出各个进程间通信的机制原理,给出各个进程间通信的应用场景;   比如 信号,给出信号在进程中信号处理处理函数的正确使用方式,给出在多线程中信号处理的正确方式;   比如 共享库,给出共享库的实现机制,给出共享库的正确使用方式;   同时 会讲解 系统安全问题 ; 可执行程序的静态布局和动态布局 ;灵活使用内存映射和虚拟内存;系统事件跟踪;   给出程序性能的调优思路;    丰富的项目实例讲解 ,提供宝贵的商业项目开发经验 ; 

273

社区成员

发帖
与我相关
我的任务
社区描述
零声学院,目前拥有上千名C/C++开发者,我们致力将我们的学员组织起来,打造一个开发者学习交流技术的社区圈子。
nginx中间件后端 企业社区
社区管理员
  • Linux技术狂
  • Yttsam
  • 零声教育-晚晚
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

请新加入的VIP学员,先将自己参加活动的【所有文章】,同步至社区:

【内容管理】-【同步至社区-【零声开发者社区】

试试用AI创作助手写篇文章吧