Linux进程的概念

news2024/11/16 19:58:32

一:冯诺依曼体系结构

什么叫做体系结构???

计算机组成 / 芯片架构

e3037d0705b94f6ca943bfcf4786afe8.png

输入单元:键盘、话筒、摄像头、usb、鼠标、磁盘(ROM)/ssd、网卡、显卡

存储器:内存(RAM)

中央处理器(CPU):寄存器、各种级别的缓存(cache)

输出单元:显示器、喇叭、打印机、磁盘、网卡、显卡

计算机里面的几乎所有的设备,都有数据存储的能力!!!

CPU这个设备,他的数据处理速度是非常快的,然后是内存,然后是各种外设(磁盘)。


程序在运行之前,必须先加载到内存?为什莫?

程序 = 代码 + 数据

最终都要CPU来执行处理,CPU需要先读取到这些代码和数据,而CPU只和内存有“数据(二进制层面)”层面的交互,但是形成的 exe,本质就是一个文件,只能在磁盘(外设)中保存。所以必须要在程序运行之前先加载到内存中。


二:操作系统

1.什么是操作系统?

操作系统(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。
操作系统是用户和计算机的接口,同时也是计算机硬件和其他软件的接口。操作系统的功能包括管理计算机系统的硬件、软件及数据资源,控制程序运行,改善人机界面,为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,提供了各种形式的用户界面,使用户有一个好的工作环境,为其它软件的开发提供必要的服务和相应的接口。

操作系统是一款软件,进行软硬件资源管理的软件。


2.为什么要有操作系统?

操作系统将软硬件资源管理好(手段),

给用户提供良好的(稳定,高效,安全)使用环境(目的)。 


如何管理呢???

什么是真正的管理者?(做决策/做执行)做决策,如何做正确的决策 ---> 根据完善的数据

示例:在学校中,管理者是校长,但与学生接触最多的是辅导员。

校长(做决策)   辅导员(做执行)   学生(被管理)

校长为了更方便的管理学生,可以制作一个execl表格,将学生的各项信息填入表格中,当数据发生变动时,在表格中进行修改,但这种方法很不方便 ---> 创建结构体,存放学生的各项信息,并将其各个节点连接起来组成链表,校长就可以直接对链表进行增删查改,不需要每天盯着表格操作。 管理的本质不是管人,而是管理数据。上述的描述,本质上就是一个建模的过程。

先描述,再组织 任何管理工作都可以经过这六个字进行计算机建模!!!

下图是,操作系统对软硬件:

036e5df9de244af09af656dc5ab4d160.jpeg 操作系统并不直接和硬件打交道,那么如何将其管理好?是通过(硬件相对的)数据管理的,通过驱动程序拿到数据。

操作系统管理:核心是:进程管理、内存管理、文件/IO管理、驱动管理。

3.系统调用和库函数的概念

系统调用:操作系统不相信任何用户,但又不得不向我们提供服务,在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口

库函数:系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。

三:进程

 1.基本概念

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。

进程 = 可执行程序 + 内核数据结构(PCB)

2.描述进程

<1>: 如何描述进程---PCB

进程信息被放在一个叫做进程控制的块的数据结构中,可以理解为进程属性的集合。

这个数据结构叫做PCB --- Linux操作系统下的PCB是 task_struct。

<2>:task_struct 内容分类

标示符: 描述本进程的唯一标示符,用来区别其他进程。

b9001b4f89c0450c82af05bf22a4b270.png

状态: 任务状态,退出代码,退出信号等。

5a50e37bc99b4c12bf3f4f26ef3f4c68.png

优先级: 相对于其他进程的优先级。

程序计数器: 程序中即将被执行的下一条指令的地址。

内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。

I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

其他信息

<3>:组织进程

 可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里。 

3.通过系统调用获取进程标识符

进程 id (PID)

父进程 id (PPID)

4a212d1cbb294c909e3505a2d94c947d.png

 示例:

#include<stdio.h>
#include<unistd.h>                                                                                                                                                     
int main()
{
    printf("pid: %d\n",getpid());
     printf("ppid: %d\n",getppid());
    return 0;
}

 运行结果为:

c80ab3740fee4f178ce22ac3289a8cb6.png

 在命令行中,父进程一般为命令行解释器(bash)。

90d533f090b347f2a8b9461374f71fd7.png

4.通过系统调用创建进程 --- fork 初识


fork 函数:

f845d05108504cdc999511dbc9dc0d8b.png

返回值:有两个返回值,一个返回父进程的子进程的 id,还有一个是子进程的 id (子进程 id 返回0说明,子进程创建成功,反之不成功)。 


示例:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    printf("pid:%d ,ppid: %d\n",getpid(),getppid());
    int ret = fork();
    printf("pid: %d ,ppid: %d ,ret: %d\n",getpid(),getppid(),ret);
    sleep(1);
    return 0;
}

代码运行结果为:

0a1be191c2134b038f1bdeb2747ace5b.png

我们发现,一个 printf( ) 函数打印了两次,而且两次打印的 ret  值不同,为什么会出现  这种现象?

只有父进程执行 fork 之前的代码,fork 之后,父子进程都要执行后续的代码,即 printf 函数既要被父进程执行一次,又要被子进程执行一次,所以在此处,会出现打印两次的情况。


<1>:为什么 fork 之后会有两个返回值?

在 fork()函数体内,函数返回 id 前已经完成了子进程的创建,既然完成了子进程的创建,那么子进程就也会去到运行队列中,等待CPU调度,父子进程共享代码,数据各自开空间。由于返回值id是数据,所以虽然id的变量名相同,但是内存地址不同,所以返回的id是不同的。

<2>:fork 两个返回值,为什么给父进程返回子进程的 pid ,给子进程返回0?

父进程返回子进程 id , 父进程可以直接找到子进程,子进程返回 0 表示创建进程成功。  

<3>:fork 之后,父子进程的运行顺序是什么样的?

创建完成子进程,只是一个开始,创建完成子进程之后,系统的其他进程,父进程和子进程,接下来都要被调度执行,当父子进程的PCB都被创建并在队列中排队的时候,哪一个进程的PCB先被选择调度,那个进程就先运行!即父子进程运行的顺序是不确定的,它由操作系统自主决定,由各自的PCB中的调度信息(时间片、优先级等)+ 调度器的算法共同决定。


fork() 之后一般要 if 分流:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        //子进程
        printf("我是子进程,pid:%d ,ppid: %d\n",getpid(),getppid());

    }
    else
    {
        printf("我是父进程,pid:%d ,ppid: %d\n",getpid(),getppid());
    }
    sleep(1);
    return 0;
}

代码运行结果为:

b3f10c9136214d53a9281726f7f8d5bb.png

四:进程状态


  • 运行状态(R) 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • 睡眠状态(S)意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠。
  • 磁盘休眠状态(D) 有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • 停止状态(T)可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • 死亡状态(X)这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

1.进程状态的查看

查看进程状态的命令:

ps aux / ps axj

运行结果为: 

 

2.僵尸进程


概念:进程退出了,但是还没有被父进程/操作系统(OS)读取,操作系统(OS)必须维护这个退出进程的PCB结构,此时,该进程的状态为僵尸状态(Z)。等到父进程或者操作系统(OS)读取之后,PCB的状态先被改成死亡状态(X)状态,才会被释放。

如果一个僵尸进程的父进程没有回收该进程,那么该进程的PCB将一直存在,如果我们不及时回收,会存在内存泄露的风险。


示例:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        //子进程
        int i = 5;
        while(i)
        {
            printf("我是子进程,pid:%d ,ppid: %d ,i: %d\n",getpid(),getppid(),i);
            sleep(1);
            i--;
        }
    }
    else
    {
        while(1)
        {
            printf("我是父进程,pid:%d ,ppid: %d\n",getpid(),getppid());
            sleep(1);
        }    
    }
    return 0;
}

在此处我们使用以下内容检测进程的运行状态:

while :;do ps aux | grep mycode | grep -v grep;sleep 1;echo "---------------------";done

运行结果为:

3.孤儿进程


概念:子进程的父进程先退出,此时子进程就称为孤儿进程,孤儿进程要被1号init进程领养,由init进行回收。


示例:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        //子进程
        printf("我是子进程,pid:%d ,ppid: %d\n",getpid(),getppid());
        sleep(10);
    }
    else
    {
         printf("我是父进程,pid:%d ,ppid: %d\n",getpid(),getppid());
         sleep(3);
         exit(0);
    }
    return 0;
}

运行结果为:

4.进程优先级


基本概念:

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

查看系统进程:

top

 运行结果为:

通过上述图片,我们可以从中看到以下几个内容:

UID:代表执行者的身份

PID:代表这个进程的信号

PPID:代表这个进程是由那个进程发展衍生而来的,既父进程

PRI:代表这个进程可被执行的优先级,值越小越先被执行

NI:代表这个进程的 nice 值


Linux进程的优先级数值范围为 60-99 (40个)

Linux中默认进程的优先级为 80

Linux支持动态优先级调整,那么如何调整?

nice值:进程优先级的修正数据

pri(新) = pri(旧) + nice 且 pri(旧) =80

top 命令更改已存在进程的 nice:

进入top后按“r”–>输入进程PID–>输入 nice 值 

nice 调整的最小值为-20,nice 调整的最大值为19。

nice 值超出最大最小调整范围时,超过部分按最大/最小计算。

为什么要把优先级限定在一定的范围内???

操作系统(OS)调度的时候,较为均衡的让每一个进程都要得到调度,这样比较公平。

如果不加以限制,可能会导致优先级较低的进程,长时间得不到CPU资源 --- 进程饥饿。


5. 其他概念

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

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

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

相关文章

apache seatunnel支持hive jdbc

上传hive jdbc包HiveJDBC42.jar到seatunel lib安装目录 原因是cloudera 实现了add batch方法 创建seatunnel任务文件mysql2hivejdbc.conf env {execution.parallelism = 2job.mode = "BATCH"checkpoint.interval = 10000 } source {Jdbc {url = "jdbc:mysql:/…

Kafka设计原理详解

Kafka核心总控制器Controller 在Kafka集群中会有一个或者多个broker&#xff0c;其中有一个broker会被选举为控制器&#xff08;Kafka Controller&#xff09;&#xff0c;它负责管理整个集群中所有分区和副本的状态。 当某个分区的leader副本出现故障时&#xff0c;由控制器…

UEditor编辑器导入自定义html模板,jeesite框架报json.parse()错误

文章目录 前言一、错误描述1. 选择模板错误2. 填入模板数据错误二、解决方案1. 选择模板错误解决2.填入数据错误解决总结前言 实现效果如下图: 添加模板 选择模板 填入模板及对应数据 一、错误描述 1. 选择模板错误

Java修仙传之Flink篇

大道三千:最近我修Flink 目前个人理解&#xff1a; 处理有界&#xff0c;无界流的工具 FLINK&#xff1a; FLINK定义&#xff1a; Flink特点 Flink分层API 流的定义 有界数据流&#xff08;批处理&#xff09;&#xff1a; 有界流&#xff1a;数据结束了&#xff0c;程序也…

【图像分割】【深度学习】Windows10下PFNet官方代码Pytorch实现与源码讲解

【图像分割】【深度学习】Windows10下PFNet官方代码Pytorch实现与源码讲解 提示:最近开始在【图像分割】方面进行研究,记录相关知识点,分享学习中遇到的问题已经解决的方法。 文章目录 【图像分割】【深度学习】Windows10下PFNet官方代码Pytorch实现与源码讲解前言PFNet模型运行…

算法笔记【4】-冒泡排序法改进

一、冒泡排序缺点 冒泡排序是一种简单但效率较低的排序算法。冒泡排序通过比较相邻元素并交换位置来实现排序。具体而言&#xff0c;它从数组的第一个元素开始&#xff0c;依次比较相邻的两个元素&#xff0c;如果顺序错误则交换它们的位置&#xff0c;直到整个数组排好序为止…

RK3399平台开发系列讲解(基础篇)应用程序代码优化技巧

🚀返回专栏总目录 文章目录 一、利用高速缓存二、代码内联三、restrict 关键字四、消除不必要的内存引用沉淀、分享、成长,让自己和他人都能有所收获!😄 📢我主要会为你介绍四个优化 应用代码的技巧,它们分别是 利用高速缓存利用代码内联利用 restrict 关键字消除不必…

Java架构师软件可靠性构建

目录 1 导学2 软件可靠性基本概念3 软件可靠性建模4 软件可靠性管理5 软件可靠性设计6 软件可靠性测试与评价想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导学 2 软件可靠性基本概念 软件可靠性是软件产品在规定的条件下和规定的时间区间完成规定功能的能力。软件…

Java精品项目源码爱心捐赠平台网站(编号V65)

Java精品项目源码扶农助农平台建设系统(编号V64) 大家好&#xff0c;小辰今天给大家介绍一个爱心捐赠平台网站(编号V65)&#xff0c;演示视频公众号&#xff08;小辰哥的Java&#xff09;对号查询观看即可 文章目录 Java精品项目源码扶农助农平台建设系统(编号V64)难度指数&a…

修仙路上的基石 ->继承与实现

继承与实现的区别 不同点&#xff1a; 继承&#xff1a;不强制 子类重写父类方法 实现&#xff1a;强制 实现类重写接口的全部方法共同点&#xff1a; 都可以使用多态 继承&#xff1a;父类 父类对象 new 子类() 实现&#xff1a;接口 接口对象 实现类.调用方法(); 这里…

[尚硅谷React笔记]——第7章 redux

目录&#xff1a; redux简介redux工作流程求和案例_纯react版求和案例_redux精简版redux完整版异步action版对react-redux的理解连接容器组件与UI组件&#xff0c;react-redux基本使用优化1_简写mapDispatch优化2_Provider组件的使用优化3_整合UI组件与容器组件数据共享_编写P…

风云七剑攻略,最强阵容搭配

今天的风云七剑攻略最强阵容搭配给大家推荐以神仙斋减怒回血为主的阵容。 关注【娱乐天梯】&#xff0c;获取内部福利号 首先&#xff0c;这个角色在这个阵容当中&#xff0c;所有的角色当中&#xff0c;他的输出系数是最高的&#xff0c;已经达到了200%的层次&#xff0c;而且…

【NLP】什么是语义搜索以及如何实现 [Python、BERT、Elasticsearch]

语义搜索是一种先进的信息检索技术&#xff0c;旨在通过理解搜索查询和搜索内容的上下文和含义来提高搜索结果的准确性和相关性。与依赖于匹配特定单词或短语的传统基于关键字的搜索不同&#xff0c;语义搜索会考虑查询的意图、上下文和语义。 语义搜索在搜索结果的精度和相关…

Linux 文件系统之虚拟文件系统

文章目录 一、简介二、进程读写文件示例三、VFS高速缓存参考资料 一、简介 虚拟文件系统&#xff08;Virtual File System&#xff0c;简称 VFS&#xff09;是内核中的软件层&#xff0c;为用户空间程序提供文件系统接口。它还在内核中提供了一个抽象层&#xff0c;允许不同的…

SQL 通用数据类型

SQL 通用数据类型 数据类型定义了存储在列中的值的类型。 SQL 通用数据类型 数据库表中的每一列都需要有一个名称和数据类型。 SQL 开发人员必须在创建 SQL 表时决定表中的每个列将要存储的数据的类型。数据类型是一个标签&#xff0c;是便于 SQL 了解每个列期望存储什么类型的…

[GKCTF 2021]easycms 禅知cms

一道类似于渗透的题目 记录一下 首先扫描获取 登入界面 admin/12345登入 来到了后台 然后我们开始测试有无漏洞点 1.文件下载 设计 自定义 导出 然后进行抓包 解密后面的内容 发现是绝对路径了 所以这里我们要获取 flag 就/flag即可 L2ZsYWc /admin.php?mui&fdownlo…

linux的使用学习(1)

Linux 修改root密码 1.以 root 用户或具有 sudo 权限的登录到 Linux 系统。 2.打终端&#xff0c;并执行以下命令以更改 root 用户的密码&#xff1a; sudo passwd root 3.然后&#xff0c;系统会要求你输入新的 root 密码。请注意&#xff0c;在输入密码时&#xff0c;终端界…

图、深度优先(DFS)、广度优先(BFS)

图 基本介绍 表示方式 图的创建 from typing import Listclass Graph:vertex_list: List[str] [] # 存储顶点的数组edges: List[list] [] # 存储图中各条边的邻接矩阵num_edges: int 0 # 边的数总数def __init__(self, n: int):"""根据传入的顶点个数初始…

11、插件注入到vue实例中

新建插件 nuxt-demo2\plugins\vue-inject.js import Vue from "vue"Vue.prototype.$test function (str) {console.log(str) }配置插件 nuxt-demo2\nuxt.config.js export default {...// Plugins to run before rendering page: https://go.nuxtjs.dev/config-…

表格识别软件:科技革新引领行业先锋,颠覆性发展前景广阔

表格识别软件的兴起背景可以追溯到数字化和自动化处理的需求不断增加的时期。传统上&#xff0c;手动处理纸质表格是一项费时费力的工作&#xff0c;容易出现错误&#xff0c;效率低下。因此&#xff0c;开发出能够自动识别和提取表格数据的软件工具变得非常重要。 随着计算机…