linux进程调度(一)-进程概述

一、什么是进程
进程是指计算机已运行的程序。程序本身只是指令、数据及其组织形式的描述。进程就是一个程序的执行实例,也就是正在执行的程序。在linux操作系统的中,进程就是一个担当分配系统资源CPU时间、内存的实体。进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态之间的转换等功能。进程在运行中不断地改变其运行状态。一个进程在运行期间,不断地从一种状态转换到另一种状态,它可以多次处于就绪状态和执行状态,也可以多次处于阻塞状态。
目前,只有CPU的资源管理器能主动发起调度,而其他资源像内存,网络,显卡等资源管理器都是提供申请服务调度的,所以要必须理解我们常说的进程调度都是指调度CPU。

进程发展史的主要内容:

  1. 单道批处理系统时期:早期的计算机只支持运行单个程序,从磁带或卡片读入程序,由操作员操作控制运行。这种系统被称为单道批处理系统,没有多个程序共同运行的概念,也没有进程的概念。

  2. 多道批处理系统时期:20世纪60年代早期,随着计算机技术的发展,多道批处理操作系统应运而生,允许多个程序同时进入内存并在CPU上运行。这里的每个程序称为一个作业(Job),但是没有进程的概念。

  3. 分时操作系统时期:20世纪60年代中期,分时操作系统应运而生,引入了多用户的概念,这为进程的发展铺平了道路。在分时系统中,操作系统可以运行多个进程并为它们提供时间片,每个进程只有在它的时间片内获得CPU的控制权。这一时期UNIX系统的开发者对进程进行了深入的研究。

  4. 多任务操作系统时期:20世纪80年代,多任务操作系统开始出现,这种操作系统允许多个进程同时运行,每个进程都有自己的地址空间、寄存器和堆栈等。操作系统必须管理和控制各个进程的运行状态,这为进程的实现和管理提供了更大的灵活性和可控性。

  5. 现代操作系统时期:21世纪以来,随着计算机技术的不断发展,操作系统和进程的概念也在不断更新和完善。现代操作系统支持多核处理器、多线程和分布式系统等技术,允许进程在不同的计算机上运行,进一步增强了进程的灵活性和可扩展性。同时,在容器技术的发展下,进程管理变得更加高效和简单,如Docker等。

二、进程的生命周期
Linux操作系统是一个多任务操作系统。 系统中的各个进程可以分时复用CPU时间片,通过有效的进程调度策略,实现多任务并行执行。进程并不总是可以立即运行。有时候它必须等待来自外部信号源、不受其控制的事件,例如在文本编辑器中等待键盘输入。在事件发生之前,进程无法运行。进程可能有以下几种状态:
1.创建状态:创建新进程。
2.等待状态:进程能够运行,但没有得到许可,因为CPU分配给另一个进程。调度器可以在下一次任务切换时选择该进程。
3.运行状态:进程正在cpu中执行。
4.睡眠状态:进程正在睡眠无法运行,因为它在等待一个外部事件。
5.终止状态:进程消亡。

系统将所有进程保存在一个进程表中,无论其状态是运行、睡眠或等待。但睡眠进程会特别标记出来,调度器会知道它们无法立即运行。睡眠进程会分类到若干队列中,因此它们可在适当的时间唤醒,例如在进程等待的外部事件已经发生时。详细的进程状态间关系图如下所示:

在这里插入图片描述
Linux内核在include/linux/sched.h文件中也为进程定义了多种状态:

/* Used in tsk->state: */
#define TASK_RUNNING                    0x0000
#define TASK_INTERRUPTIBLE              0x0001
#define TASK_UNINTERRUPTIBLE            0x0002
#define __TASK_STOPPED                  0x0004
#define __TASK_TRACED                   0x0008
/* Used in tsk->exit_state: */
#define EXIT_DEAD                       0x0010
#define EXIT_ZOMBIE                     0x0020
#define EXIT_TRACE                      (EXIT_ZOMBIE | EXIT_DEAD)
/* Used in tsk->state again: */
#define TASK_PARKED                     0x0040
#define TASK_DEAD                       0x0080
#define TASK_WAKEKILL                   0x0100
#define TASK_WAKING                     0x0200
#define TASK_NOLOAD                     0x0400
#define TASK_NEW                        0x0800
#define TASK_STATE_MAX                  0x1000

其中比较常用的就是下面的5种:

  • TASK_RUNNING(可运行状态):对应上图的等待状态或者运行状态。它是指进程处于可运行的状态,或许正在运行,或许在就绪队列(本书中也称为调度队列)中等待运行。
  • TASK_INTERRUPTIBLE(可中断睡眠态):对应上图的睡眠状态。进程进入睡眠状态(被阻塞)来等待某些条件的达成或者某些资源的就位,一旦条件达成或者资源就位,内核就可以把进程的状态设置成TASK_RUNNING并将其加入就绪队列中。也有人将这个状态称为浅睡眠状态。
  • TASK_UNINTERRUPTIBLE(不可中断态):对应上图的睡眠状态。这个状态和上面的TASK_INTERRUPTIBLE状态类似,唯一不同的是,进程在睡眠等待时不受干扰,对信号不做任何反应,所以这个状态称为不可中断态。通常使用ps命令看到的被标记为D状态的进程,就是处于不可中断态的进程,不可以发送SIGKILL信号使它们终止,因为它们不响应信号。也有人把这个状态称为深度睡眠状态。
  • EXIT_ZOMBIE(僵尸态):对应上图的终止状态。进程已经消亡,但是task_struct数据结构还没有释放,这个状态叫作僵尸态。
  • __TASK_STOPPED(终止态):对应上图的终止状态。进程停止运行。task_struct中的资源包括task_struct数据已经释放完了。
    三、进程优先级
    并非所有进程都具有相同的重要性。除了大家熟悉的进程优先级之外,进程还有不同的关键度类别,以满足不同需求。首先要知道linux的进程分为以下几种,每一种的优先级都是不一样的:
    1.期限进程:优先级为-1。优先级最高。
    2.实时进程:优先级1-99,优先级数值越大便是优先级越高。
    3.普通进程:优先级为100-139,优先级数值越小便是优先级越高。可以通过nice值改变普通进程优先级。
    4.空闲进程:优先级为140。优先级最低。

四、进程表示
Linux内核涉及进程和程序的所有算法都围绕一个名为 task_struct 的数据结构建立,该结构定义在 include/linux/sched.h 中。这是系统中主要的一个结构。task_struct 包含很多成员,将进程与各个内核子系统联系起来,我们看看代码:


struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK/** For reasons of header soup (see current_thread_info()), this* must be the first element of task_struct.*/struct thread_info		thread_info;//把thread_info从栈中抽出来,方便current宏的实现
#endif/* -1 unrunnable, 0 runnable, >0 stopped: */volatile long			state; //表示进程的状态标志/** This begins the randomizable portion of task_struct. Only* scheduling-critical items should be added above here.*/randomized_struct_fields_startvoid				*stack;//指向内核栈的指针refcount_t			usage;//进程描述符使用计数,被置为2时,表示进程描述符正在被使用而且其相应的进程处于活动状态/* Per task flags (PF_*), defined further below: */unsigned int			flags;//标记,表示进程的类型unsigned int			ptrace;#ifdef CONFIG_SMPstruct llist_node		wake_entry;int				on_cpu;
#ifdef CONFIG_THREAD_INFO_IN_TASK/* Current CPU: */unsigned int			cpu;//当前运行的cpuid
#endifunsigned int			wakee_flips;unsigned long			wakee_flip_decay_ts;struct task_struct		*last_wakee;/** recent_used_cpu is initially set as the last CPU used by a task* that wakes affine another task. Waker/wakee relationships can* push tasks around a CPU where each wakeup moves to the next one.* Tracking a recently used CPU allows a quick search for a recently* used CPU that may be idle.*/int				recent_used_cpu;//上一次调度时使用的cpuidint				wake_cpu;
#endifint				on_rq;int				prio;//进程的当前优先级。一般等于normal_prio,但是当进程A占有互斥锁并且进程B在等待锁的时候,会把A进程的优先级临时提高int				static_prio;//普通进程的静态优先级,就是120+nice,若是限期进程或者实时进程则为0int				normal_prio;//普通进程的正常优先级,一般等于static_prio,若是限期进程则为-1,若是实时进程,则为99-rt_priorityunsigned int			rt_priority;//实时进程的优先级,数值越大优先级越高,如果是限期进程或者普通进程,则为0const struct sched_class	*sched_class;//进程的调度类struct sched_entity		se;//普通进程的调度实体struct sched_rt_entity		rt;//实时进程的调度实体
#ifdef CONFIG_CGROUP_SCHEDstruct task_group		*sched_task_group;//指向进程所在的cgroup
#endifstruct sched_dl_entity		dl;//deadline进程的调度实体#ifdef CONFIG_UCLAMP_TASK/* Clamp values requested for a scheduling entity */struct uclamp_se		uclamp_req[UCLAMP_CNT];/* Effective clamp values used for a scheduling entity */struct uclamp_se		uclamp[UCLAMP_CNT];
#endif#ifdef CONFIG_PREEMPT_NOTIFIERS/* List of struct preempt_notifier: */struct hlist_head		preempt_notifiers;
#endif#ifdef CONFIG_BLK_DEV_IO_TRACEunsigned int			btrace_seq;
#endifunsigned int			policy;//进程调度策略int				nr_cpus_allowed;//该进程允许使用的cpu的数量const cpumask_t			*cpus_ptr;//表示该进程允许在哪个cpu上运行cpumask_t			cpus_mask;//表示该进程不允许在哪个cpu上运行...struct sched_info		sched_info;//记录进程运行时的实时信息struct list_head		tasks;//进程链表
#ifdef CONFIG_SMPstruct plist_node		pushable_tasks;struct rb_node			pushable_dl_tasks;
#endifstruct mm_struct		*mm;//指向内存描述符,如果是内核进程,则为空struct mm_struct		*active_mm;//指向内存描述符,如果是内核进程,则指向从进程借用的内存描述符/* Per-thread vma caching: */struct vmacache			vmacache;#ifdef SPLIT_RSS_COUNTINGstruct task_rss_stat		rss_stat;
#endifint				exit_state;//进程的退出状态,int				exit_code;//进程的终止代号int				exit_signal;//进程接受到的退出信号/* The signal sent when the parent dies: */int				pdeath_signal;//表示当父进程死亡时要发送的信号,然后托管给0进程/* JOBCTL_*, siglock protected: */unsigned long			jobctl;
...unsigned long			atomic_flags; /* Flags requiring atomic access. */struct restart_block		restart_block;pid_t				pid;//表示该进程的进程号pid_t				tgid;//表示该进程的线程号#ifdef CONFIG_STACKPROTECTOR/* Canary value for the -fstack-protector GCC feature: */unsigned long			stack_canary;
#endif/** Pointers to the (original) parent process, youngest child, younger sibling,* older sibling, respectively.  (p->father can be replaced with* p->real_parent->pid)*//* Real parent process: */struct task_struct __rcu	*real_parent;//指向创建进程的进程描述符(生父进程),如果生父进程不存在了,指向进程1(systemd进程)/* Recipient of SIGCHLD, wait4() reports: */struct task_struct __rcu	*parent;//指向进程的当前父进程,一般和real_parent一致,只有在调试的时候指向调试的进程/** Children/sibling form the list of natural children:*/struct list_head		children;//指向该进程的子进程链表struct list_head		sibling;//指向进程的兄弟进程struct task_struct		*group_leader;//一般是指向自己,如果该进程是用户创建的线程,则指向创建线程的进程.../* Process credentials: *//* Tracer's credentials at attach: */const struct cred __rcu		*ptracer_cred;/* Objective and real subjective task credentials (COW): */const struct cred __rcu		*real_cred;//指向客观和真实的主观任务凭证/* Effective (overridable) subjective task credentials (COW): */const struct cred __rcu		*cred;//指向有效的主观任务凭证#ifdef CONFIG_KEYS/* Cached requested key. */struct key			*cached_requested_key;
#endif/** executable name, excluding path.** - normally initialized setup_new_exec()* - access it with [gs]et_task_comm()* - lock it with task_lock()*/char				comm[TASK_COMM_LEN];//进程的名称struct nameidata		*nameidata;#ifdef CONFIG_SYSVIPCstruct sysv_sem			sysvsem;//用于信号量struct sysv_shm			sysvshm;//用于共享内存
#endif
#ifdef CONFIG_DETECT_HUNG_TASKunsigned long			last_switch_count;unsigned long			last_switch_time;
#endif/* Filesystem information: */struct fs_struct		*fs;//指向进程的当前工作目录/* Open file information: */struct files_struct		*files;//打开的文件/* Namespaces: */struct nsproxy			*nsproxy;//命名空间/* Signal handlers:主要用于信号处理 */struct signal_struct		*signal;//指向进程的信号描述符struct sighand_struct		*sighand;//指向进程的信号处理程序描述符sigset_t			blocked;//表示被阻塞信号的掩码sigset_t			real_blocked;//临时掩码/* Restored if set_restore_sigmask() was used: */sigset_t			saved_sigmask;//使用了set_restore_sigmask()则恢复的掩码struct sigpending		pending;//存放私有挂起信号的数据结构unsigned long			sas_ss_sp;//信号处理程序备用堆栈的地址size_t				sas_ss_size;//堆栈的大小unsigned int			sas_ss_flags;//堆栈的标志位struct callback_head		*task_works;
...
#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH			48ULu64				curr_chain_key;int				lockdep_depth;//表示获取大内核锁的次数unsigned int			lockdep_recursion;struct held_lock		held_locks[MAX_LOCK_DEPTH];
#endif
...
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/166828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka报错under-replicated partitions

1 under-replicated partitions异常原因 Kafka报错under replicated partitions意味着某些分区的副本数量未达到预期的复制因子。 主要有两种原因, Broker故障 如果某个Kafka Broker发生故障,导致其中一些分区的副本不再可用,那么这些分区就…

2023年微软开源八个人工智能项目

自2001年软件巨头微软前首席执行官史蒂夫鲍尔默对开源(尤其是Linux)发表尖刻言论以来,微软正在开源方面取得了长足的进步。继ChatGPT于去年年底发布了后,微软的整个2023年,大多数技术都是面向开发人员和研究人员公开发…

Towhee介绍

官方网站:Towhee | Home - Towhee Towhee 是一个尖端框架,旨在通过使用基于大型语言模型 (LLM) 的管道编排来简化非结构化数据的处理。它具有独特的优势,可以从各种非结构化数据类型(包括冗长的文本、图像…

浅谈进程与线程

文章目录 一. 进程🍎什么是程序?什么是进程?🍋程序的并发性和并行性🍉进程诞生的原因🍑PCB 二. 线程🍥什么是线程?🍦为什么引入线程? 三. 进程与线程的区别与…

HarmonyOS 设备管理开发:USB 服务开发指导

基本概念 USB 服务是应用访问底层的一种设备抽象概念。开发者根据提供的 USB API,可以获取设备列表、控制设备访问权限、以及与连接的设备进行数据传输、控制命令传输等。 运作机制 USB 服务系统包含 USB API、USB Service、USB HAL。 图 1 USB 服务运作机制 ●…

【SpringBoot3+Vue3】五【完】【实战篇】-前端(配合后端)

目录 一、环境准备 1、创建Vue工程 2、安装依赖 2.1 安装项目所需要的vue依赖 2.2 安装element-plus依赖 2.2.1 安装 2.2.2 项目导入element-plus 2.3 安装axios依赖 2.4 安装sass依赖 3、目录调整 3.1 删除部分默认目录下文件 3.1.1 src/components下自动生成的…

JeecgBoot3.5漏洞升级—快速文档

近几年来,黑客攻击行为呈现出日益复杂和隐蔽的趋势,对个人和组织的安全造成了严重威胁。黑客们不断寻找新的漏洞和安全漏洞,利用各种手段进行网络攻击,包括恶意软件、网络钓鱼、勒索软件等。因此,我们每个人都需要关注…

Windows系统下载并安装 Windows PowerShell

PowerShell下载地址 一 windows7 版本 **若要确定您正在使用的 Microsoft PowerShelll 版本,请在 Windows 7 或 Windows Server 2008R2 或 Windows Server 2012 计算机上执行以下操作: 单击“开始”,单击“所有程序”,单击“附件”,单击“Windows PowerShell”,然后单击…

渲染农场渲染一分钟动画需要多少钱?需要渲染多少时间?

现在很公司都开始使用渲染农场渲染动画,但是还是有很多人不知道渲染农场渲染动画需要多少钱,需要渲染多少时间。在这篇文章中我们将为你一一解答,为你提供一个清晰的参考。 渲染农场的收费通常是按照渲染的使用时间收费,渲染十分…

华大基因助力乌兹别克斯坦精准医学发展,共筑健康丝绸之路

今年上半年,中国与中亚五国元首齐聚陕西西安,举办中国-中亚峰会。过去的20年里,中国已经成为中亚国家的主要投资来源国,总投资额接近400亿美元。乌兹别克斯坦是中国-中亚合作机制的重要参与者,乌…

elasticsearch命令大全

1、查询全部索引 GET /_cat/indices?v2、要按文档数对所有索引进行降序排序 GET /_cat/indices?v&hindex,docs.count&sdocs.count:descv:参数用于显示列标题 h:参数用于指定要显示的列 s:参数用于指定按哪一列进行排序 desc&…

CAD随机多面体_圆柱试件3D插件

插件介绍 CAD随机多面体_圆柱试件3D插件可用于在AutoCAD软件内生成随机三维多面体及外侧圆柱体试件。插件可确保多面体之间不发生干涉,且多面体与外侧圆柱体试件之间保持适配关系,确保生成的模型导入有限元软件后几何合理有效。本插件主要可应用于三维混…

讲概念谈愿景AI Agent名不副实?看实在智能RPA Agent智能体如何落地!

OpenAI在首届开发者大会上推出了GPTs和Assitant API,不仅改写了AI Agent的构建范式,也把AI智能体的应用推向一个新高潮。GPTs和GPT商店,使得用户无需编码通过自然语言就能创建并拥有多个专属私人助理,且可以如在苹果应用商店一样在…

开发教育APP的意义

开发教育APP的意义有以下几点: 促进教育资源发挥效果:通过教育APP软件开发,可以让现代教育资源有效合理的进行利用,并且能够更进一步的提升发挥功能,促进教育资源全面发挥其具体作用和效果,从而提升教育行…

3.3.1详解linux内核链表list_head及其接口应用

文章目录 1 list定义2 list接口2.1 list初始化方法1:定义并初始化链表方法2:先定义再初始化链表2.2 list_add2.3 list_del2.4 list_replace2.5 list_move2.6 list_splice3 list遍历3.1 list_entry3.2 list_first_entry3.3 list_last_entry3.4 list_first_entry_or_null3.5 li…

Y-MODEM协议定制上位机

最近在使用N32G031和STM32F10X系列单片机进行IAP,使用的是Ymodem协议。单片机上的软件已经完成了,一般是使用secureCRT这样的工具作为上位机来进行测试,后来想做一个定制化的简单的上位机。在网上找了下资料,以下这篇文章写的使用…

浅谈安科瑞无线测温设备在挪威某项目的应用

摘要:安科瑞无线温度设备装置通过无线温度收发器和各无线温度传感器直接进行温度值的传输,并采用液晶显示各无线温度传感器所测温度。 Absrtact:Acre wireless temperature device directly transmits the temperature value through the wireless temp…

基于51单片机倾角MPU6050老人跌倒远程GSM短信报警器+源程序

一、系统方案 1、本设计采用这51单片机作为主控器。 2、MPU6050角度值送到液晶1602显示。 3、红外传感器检测心率。 4、跌倒远程GSM报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 void LCD_Init() //初始化液晶时间显示 { write_com…

yarn:无法加载文件 C:\Users\***\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本

原因:PowerShell 脚本的执行有着严格的安全策略限制! 解决方案:管理员身份启动Windows PowerShell 在命令行中输入set-ExecutionPolicy RemoteSigned 再使用yarn就可以了

SQL常见函数整理 _ LAG() 向上偏移

1. 用法 窗口函数,用于访问窗口中当前行之前的行的数据。该函数可以根据需要计算当前行之前的值,使我们能够轻松地比较不同行之间的差异和变化。 2. 基本语法 LAG(column, offset, default_value) OVER (ORDER BY column)column:代表在返回…