Linux进程(万字解析)

news2024/11/15 10:25:20

进程

  • 一.冯诺依曼体系结构
  • 二.操作系统
    • 1.管理的概念
    • 2.系统调用和库函数概念
  • 三.进程
    • 1.先描述
    • 2.再组织
  • 四.Linux里的PCB
    • 1.概念
    • 2.理解当前路径
    • 3.PID
      • 1.kill指令
      • 2.获取自己的PID
    • 4.初识fork函数
  • 五.进程状态
    • 1.一般意义上的
      • 1.运行
      • 2.阻塞
      • 3.挂起
    • 2.Linux内核里的状态
      • 1.运行态
      • 2.阻塞态
      • 3.暂停态
      • 4.僵尸状态
      • 5.孤儿进程
  • 六.进程优先级
    • 1.概念
    • 2.查看进程优先级
    • 3.top调整优先级

一.冯诺依曼体系结构

我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。

在这里插入图片描述

截至目前,我们所认识的计算机,都是有一个个的硬件组件组成:

1.输入单元:包括键盘, 鼠标,扫描仪, 写板等 。
2.中央处理器(CPU):含有运算器和控制器等 。
3.输出单元:显示器,打印机等。

关于冯诺依曼,必须强调几点:
1.这里的存储器指的是内存。
2.不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)。
3.外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
4. 一句话,所有设备都只能直接和内存打交道。

二.操作系统

在这里插入图片描述

1.管理的概念

在这里插入图片描述

在这里插入图片描述

总结:操作系统通过驱动程序来获取数据进而实现对软硬件的管理。

但如果操作系统管理所有数据的话,很显然数据量太大了,但由于所有的硬件都有公共属性,所以可以将它们组合成对象,最终操作系统就可以从对数据的管理变成对数据结构的管理了。我们把这种方式称为先描述再组织。

结论:在操作系统中,管理任何对象,都可以转化成对某种数据结构的增删查改。

操作系统就是一款搞管理的软件。

2.系统调用和库函数概念

根据上文可以知道显示器是硬件,那么我们平常写c语言里的printf将数据打印到显示器上是怎么实现的呢?毫无疑问是必须通过操作系统的。库函数与系统调用一定是上下层的关系。

在这里插入图片描述

三.进程

简单理解:一个已经加载到内存里的程序叫做进程(任务)。进程=PCB+自己的代码和数据。

1.先描述

一个操作系统可以,不仅仅只能运行一个进程,可以同时运行多个进程。就意味着操作系统必须将进程管理起来,那么它是如何管理的呢?

核心思路先描述再组织。任何一个进程,在加载到内存成为真正的进程的时候,操作系统都要先形成描述进程(属性)的结构体对象–PCB(进程控制块)。本质上PCB就是进程属性的集合。而操作系统是用c语言写的,所以PCB是用struct封装的。

在这里插入图片描述

在加载进程时,不仅要把你自己的代码和数据加载到内存里,还要把PCB也加载进去。而这两者相结合才能成为一个进程。操作系统对进程进行管理就可以直接管理PCB。

2.再组织

对多个进程进行管理

在这里插入图片描述

PCB是一个struct对象,里面可能存放着进程编号,进程状态,优先级,其他PCB指针等属性,而操作系统对多进程管理就可以通过PCB指针,形成链式结构,像管理链表一样进行增删查改,这就是再组织。

四.Linux里的PCB

1.概念

Linux下的PCB是task_struct。task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

在这里插入图片描述

task_struct内容分类

在这里插入图片描述

2.理解当前路径

接下来简单写一个程序

在这里插入图片描述

接着在运行后新开一个标签页来查看进程(ps:如果下面进程PID有变化是正常现象,因为每启动一次程序,PID大概率会改变)

在这里插入图片描述

可以使用ps指令或者查看proc目录来查看进程。

在这里插入图片描述

在这里插入图片描述

这里面的蓝色字体全部都是目录,每一个数字就是当前进程的PID。可以看到myprocess的PID是26117,接着进入这个进程。

进入进程

在这里插入图片描述

而圈着的就是当前路径。一般我们创建一个文件只写文件名,它会默认将文件放在当前路径下。因为进程的PCB里包含了当前路径的信息,而在打开或者创建文件时,默认会将当前路径拼接在文件前面。

3.PID

上文提到PID是进程的唯一标识符,那么PID有什么作用呢?

1.kill指令

可以使用kill-9将指定进程强行停止。

在这里插入图片描述

2.获取自己的PID

PID存放于task_struct里,而task_struct是Linux里的一种数据结构,而操作系统并不信任用户,不能跳过操作系统直接访问task_struct,必须通过系统调用接口。而这个调用接口是getpid。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

PPID是父进程

在这里插入图片描述
在这里插入图片描述

当运行一个进程时,bash会将该进程变成自己的子进程,但即使子进程终止也不会影响bash进程。

4.初识fork函数

在这里插入图片描述

测试

在这里插入图片描述

在这里插入图片描述

我们可以发现fork之后的代码被执行了两次。我们再次阅读手册,可以看到fork的返回值是paid类型,它的作用是创建一个新的进程。如果调用成功,它返回的一个子进程的PID给父进程返回0给子进程。那么为什么它有俩个返回值呢?接着改进代码再测试。

在这里插入图片描述

在这里插入图片描述

结果是不断打印父进程和子进程,说明再同一份代码里,id>0和id=0是同时成立的,也说明有两个死循环在同时运行。简单理解,在执行了fork指令后,该进程产生了一个分支,父进程是它自己,子进程是分支。

在这里插入图片描述

分析

在这里插入图片描述

第一个问题。返回不同的返回值是为了进行区分,让不同的执行流执行不同的代码块。一般而言,fork之后的代码父子共享(参考上文被执行了两次的代码)。一个父进程可以有多个子进程,为了能够识别子进程,所以给父进程返回子进程的PID用来标识子进程的唯一性。而一个子进程只能有一个父进程,故不需要进行标识。

第三个问题。fork创建了一个子进程,而进程=内核数据结构+代码和数据。所以首先要创建自己的task_struct,而它的创建是以父进程作为模板,再对部分属性进行修改。子进程创建时没有代码和数据,只能访问父进程的代码和数据,这就是为什么fork之后父子进程代码共享。而为什么要创建子进程呢?是为了让父子进程执行不同的代码块从而进行协同,所以在fork函数设计上具有了不同的返回值。

第二个问题。首先fork是一个系统调用函数,在执行它时会进入到操作系统内创建子进程。而在创建子进程时,会进行创建子进程PID,填充子进程内容等操作,将这一系列操作完成后会进行返回。关键是在进行返回时子进程已经创建完毕而代码又是父子共享,所以会有两次返回。

在这里插入图片描述

第四个问题。一个概念,在任何平台进程在运行时具有独立性。而又由于数据能够被修改(代码不能修改),所以不能让两个进程共享同一份数据。但由于子进程没有任何数据,所以它有需要将父进程数据进行拷贝。但子进程并不一定会使用父进程里的数据,如果全部拷贝势必会造成资源浪费,所以操作系统做了一些修改。在子进程刚创建时代码和数据都是共享,当子进程需要修改数据时,操作系统额外开辟一块空间,在新空间里写入,这种技术被称为父子进程间在数据层面上的写时拷贝。所以在进行return写入的时候,子进程进行了写时拷贝,这样就保证了返回值不同。

总结

fork创建了一个子进程,而子进程在创建之初与父进程共享代码和数据。由于父和子是两个进程会执行两次return,在两次返回时对PID发生写时拷贝,让父子进程的PID变成不同的值,所以后续我们就可以通过对不同的PID进行分流,让它们执行不同的代码块。

回到前文的bash进程,bash是通过fork函数创建子进程来运行。

五.进程状态

1.一般意义上的

在这里插入图片描述
在这里插入图片描述

以下主要介绍运行,阻塞,挂起三个状态。

1.运行

Linux内部可以同时有多个进程,每个进程通过双链表进行链接,这样链接起来的队列叫做运行队列。所以只要我们能够找到头节点,就能够调用所有进程。那么毫无疑问每个cpu里需要有一个头节点,它会维护一个runqueue(运行队列)的结构体,队列里包含了很多属性,最重要的就是head和tail。这样如果我们需要运行一个进程,直接将它拿到头部就可以了。

而多个进程毫无疑问会强占CPU资源,这时就会有一个调度器(一种函数)得到所有进程的参数之后就可以更好的进行资源分配了。

运行态

凡是处于运行队列里的进程都被称作运行态(R态)。

在这里插入图片描述

一个进程只要放到CPU上去那是否意味着必须跑完才会被CPU放下呢?

当然不是。每个进程里都有一个叫做时间片的概念。比如时间片是10ms,那么该进程最多在CPU里运行10ms,然后放到队列尾部。最终呈现的效果就是,在一个时间段里,每一个进程都会被调用。对于这种情况,又被叫做并发执行。在这段时间里必然存在着大量将进程拿去和放下的操作,这种情况叫做进程切换。

2.阻塞

每个CPU都连接着各种各样的外设,不论是什么硬件,操作系统都会先描述再组织。

在这里插入图片描述

接下来有一个进程要从键盘里读取数据,当前该进程等待键盘输入数据,但我却一直不按下键盘。那么这个进程就绝对不能放到运行队列里,因为想要访问的软硬件资源没有就绪。这个进程就会被链接到键盘资源里,如果又有一个进程需要从键盘读取资源,那么这个进程又会链接到上个进程后面。这个链接起来的队列就是waitqueue(等待队列)。如果键盘输入了数据,那么该进程就会自动进入运行队列了。

在这里插入图片描述
阻塞态

总结:把这种等待某种特定设备的进程称为该进程的阻塞状态。每一个设备都有等待队列。

3.挂起

阻塞挂起态

如果操作系统内存资源严重不足了,那么它会保证正常运行的情况下,省出内存资源。而阻塞队列在等待过程中里面是没有数据的,那么此时操作系统就有可能将等待的进程的代码交还到外设里,只保留PCD,这个过程就叫做内存数据的换出;而当该进程的资源就绪后,CPU又会将代码拷到运行队列里,这个该过程叫做换入。而在这个过程里,代码和数据并没有在内存中,这个状态就叫做挂起状态。

2.Linux内核里的状态

在这里插入图片描述

一个进程的状态与它的代码和数据无关。

Linux内核代码定义的状态

在这里插入图片描述

1.运行态

R态就是运行态,一个例子

在这里插入图片描述

在这里插入图片描述

有个很奇怪的现象,明明程序在运行,但它显示的却不是R态而生S态。接下来把打印都注释掉。

在这里插入图片描述

在这里插入图片描述

这时这个进程就变成R态了,是怎么回事呢?这是因为CPU的速度很快,所以我们在进行printf打印的时候,CPU大部分时间都是在等待外设资源,所以我们看到的是等待态。这里的R+代表的是当前进程在前台运行。

2.阻塞态

S和D态都是阻塞态
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

S态被称为浅度睡眠,可以被直接唤醒。D态在Linux里被称为深度睡眠,处于不可被唤醒状态,它也不可被操作系统所响应。

3.暂停态

T和t状态就是暂停态

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

可以使用Kill-19暂停进程,kill-18重新运行。之前的kill-9是强制结束进程。

在这里插入图片描述

4.僵尸状态

Z状态

1.僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

exit

在这里插入图片描述

这个函数的作用就是让一个正常运行的进程直接终止,具体参数现在知识储备不足,之后会更新。

一个例子

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在第5秒的时候,有一个进程从S态变到了Z态。并且可以看到后面有个defunct(失效的)单词。对于这种已经失效但在等待父进程回收的状态就叫做僵尸状态。

进程一般退出的时候,如果父进程没有主动回收子进程信息,那么子进程会一直让自己处于Z状态,进程的相关资源尤其是task_struct不能被释放。这样就会造成内存泄漏问题。

在这里插入图片描述

5.孤儿进程

这次让父进程先退出看看会发生什么

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们发现过了一会,父进程消失了,子进程还在。并且该子进程的PPID还变成了1。这里的1是什么呢?

在这里插入图片描述

其实就是systemd,也就是操作系统本身。所以可以得出,如果父进程先退出,那么子进程的父进程会被改为1号进程(操作系统)。对于这种进程我们称为孤儿进程,该进程被操作系统领养。

为什么要被领养呢?因为孤儿进程也需要被释放。

六.进程优先级

1.概念

是什么

优先级与权限的区别。权限决定的是能不能,而优先级是谁先谁后的问题。

为什么

因为资源是有限的,进程是有多个的,注定了进程之间有竞争—竞争性。
操作系统必须保证大家进行良性竞争,就必须确认优先级。如果进程长时间得不到CPU资源,该进程代码长时间无法执行–进程的饥饿问题

基本概念

1.cpu资源分配的先后顺序,就是指进程的优先权(priority)。
2.优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能(谨慎)。
3.还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整 体性能。

2.查看进程优先级

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

优先级可以调整。那么我们是否可以任意更改nice值,大大的提高优先级呢?技术上是可以实现的,但Linux的调度器设计者并不想让用户过多的参与优先级的调整,所以nice值只能在【-20,19】之间。优先级默认是从80开始。

在这里插入图片描述

3.top调整优先级

在这里插入图片描述

在这里插入图片描述
进入root用户,再输入top

在这里插入图片描述

按r,输入要调整进程的PID

在这里插入图片描述

输入调整的值

在这里插入图片描述

更改成功

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

2023软考下半年考试和报名时间汇总(附详细报名流程)

2023年上半年软考结束了,相信有不少准备报考下半年软考的考生正摩拳擦掌,期待在11月的考试中大显身手。2023下半年软考什么时候报名呢?一起来看看吧~ 根据中国计算机技术职业资格网发布的关于《2023年度计算机技术与软件专业技术资格&#x…

ERROR: transport error 202: gethostbyname: unknown host报错解决方案

Java 9 syntax for remote debugger: -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005Java 8 不适用 *:port,应该使用: -agentlib:jdwptransportdt_socket,servery,suspendn,address5005参考 https://stackoverflow.com/questions/50344957/ja…

预测性维护:融合新兴技术6大发展趋势

随着技术的不断进步,预测性维护在工业领域呈现出新的发展趋势。这些趋势旨在通过更有效地分析数据和利用先进的技术手段来提高设备的维护效率和性能。以下是笔者认为可能的预测性维护的六大新兴趋势,抛砖引玉,供交流探讨: 一、数据…

清风数学建模——层次分析法

层次分析法 文章目录 层次分析法评价类问题可以用打分来解决1.通过查阅资料选定指标2.画出权重表格并填写2.1.判断矩阵一致矩阵2.3一致性检验的步骤先算一致性指标CI根据表格查找n对应的RI(平均随机一致性指标),表格一般会在题目中给出计算一…

现场服务管理系统有哪些?5个现场服务管理软件对比

现场售后服务管理软件的使用者通常是机械设备、家电、仪表仪器、医疗器械等厂商的工程师和客服调度人员。现场售后服务管理软件可将服务过程标准化,包括工单派发、服务过程步骤、配件订购出货和付款、客户评价都有系统支持,有的现场售后服务软件还支持数…

有理逼近 C++详解

有理逼近 C详解 有理逼近问题描述输入输出格式输入格式输出格式 输入输出样例输入样例输出样例: 解法代码代码解法变量解析算法 注:本文支持互3~ 有理逼近 问题描述 输入输出格式 输入格式 输入文件的第一行为 P 、 N P、N P、N,其中 P …

MongoDB文档--架构体系

阿丹: 在开始学习先了解以及目标知识的架构体系。就能事半功倍。 架构体系 MongoDB的架构体系由以下几部分组成: 存储结构:MongoDB采用文档型存储结构,一个数据库包含多个集合,一个集合包含多个文档。存储形式&#…

ReID网络:MGN网络(2) - 模型定义

1. 概述 MGN网络使用ResNet50((Before res_conv4_2) )作为Backbone进行特征的析取。为了实现多粒度(Multiple Granularities),MGN从ResNet50的网络的尾部开始,将后续网络划分为3个分支,对应三个不同的粒度。 2. ResNet ResNet 网络是在 20…

【SQL应知应会】表分区(三)• Oracle版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 分区表 • Oracle版 前言一、分区表1.什么是表分区…

CountdownLatch(门闩)

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。 CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实…

前端视频播放技术概览

转眼间,2023 年已进入下半场,在这样一个时间节点下,长视频平台如爱奇艺、优酷、腾讯视频等,以及短视频平台如抖音、快手等,对大家来说早已是司空见惯的事物。然而,在我们追剧、刷弹幕的时候,很少…

超越AI的未来:ChatGPT菜鸟级使用流程

文章目录 1. ChatGPT简介2. 准备工作3. 安装OpenAI Python库4. 创建ChatGPT会话5. 发起对话请求6. 处理ChatGPT响应7. 示例应用8. 结语 引言: 随着人工智能技术的不断发展,自然语言处理(NLP)领域的一个重要突破是开放式AI语言模型。OpenAI的ChatGPT&…

系统架构设计师-软件架构设计(6)

目录 一、物联网分层架构 二、大数据分层架构 三、基于服务的架构(SOA) 1、SOA的特征 2、服务构件与传统构件的区别 四、Web Service(WEB服务) 1、Web Services 和 SOA的关系 五、REST(表述性状态转移) 六、ESB(…

linux系统编程重点复习--进程之间通信

目录 复习目标 2 进程间通信相关概念 2.1 什么是进程间通信 2.2 进程间通信的方式 3 管道-pipe 3.1管道的概念 3.2管道的原理 3.3管道的局限性 3.4创建管道-pipe函数 3.5父子进程使用管道通信 3.6 管道练习 3.7 管道的读写行为 3.8 如何设置管道为非阻塞 3.9 如何…

Maven设置阿里云路径(防止加载过慢)

<?xml version="1.0" encoding="UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regardin…

git | git使用心得记录

公司里项目最近使用Git进行协作开发&#xff0c;总结一下使用心得 一、第一次用git&#xff0c;完全同步最新代码checkout 按照以下步骤操作 1、git init 2、git remote add origin 远程仓库的地址https://gitlab.xxxx.com.cn/xx/xx/xxx/Android/baseline/x.x.x.git(远程仓库…

剑指offer48.最长不含重复字符的子字符串

我一开始的想法是创建一个大小为26的int数组&#xff0c;下标为0对应的是‘a&#xff0c;25对应的是’z&#xff0c;然后一开始都赋为-1&#xff0c;用一个for循环从头遍历这个字符串&#xff0c;通过char c s.charAt(i)获得字符&#xff0c;然后c-97&#xff0c;就是它对应的…

《向量数据库指南》——向量数据库向专业化和智能化的发展趋势

随着数据的规模不断扩大和信息技术的发展,向量数据库在各个行业中扮演着越来越重要的角色。未来,随着技术的不断进步和市场需求的不断增长,向量数据库的应用将更加广泛和深入,同时也会出现更加专业化和智能化的趋势。 一、向量数据库的专业化发展 随着各个行业数据量的不…

【雕爷学编程】Arduino动手做(178)---超迷你哦,用徽商香烟盒做个智能小车2

早上去打羽毛球&#xff0c;路上捡到一个香烟盒子&#xff0c;于是就想尝试一下&#xff0c;捣鼓捣鼓。 经测试&#xff0c;控制器与电机使用同一组电源会互相干扰&#xff0c;故只好再加一组电池 商徽烟盒小车内部结构总算整好了&#xff0c;够迷你吧 小车轮子准备用矿泉水瓶盖…

【ChatGPT辅助学Rust | 基础系列 | Cargo工具】Cargo介绍及使用

文章目录 前言一&#xff0c;Cargo介绍1&#xff0c;Cargo安装2&#xff0c;创建Rust项目2&#xff0c;编译项目&#xff1a;3&#xff0c;运行项目&#xff1a;4&#xff0c;测试项目&#xff1a;5&#xff0c;更新项目的依赖&#xff1a;6&#xff0c;生成项目的文档&#xf…