【Linux--进程】

目录

  • 一、基本概念
    • 1.1描述进程-PCB
    • 1.2task_struct中内容分类
  • 二、了解进程
    • 2.1查看进程
    • 2.2通过系统调用获取进程标识符
  • 三、fork创建进程
    • 3.1fork()函数
    • 3.2写时拷贝
  • 四、进程的状态
    • 4.1操作系统学科里的进程状态(运行、阻塞、挂起)
    • 4.具体的Linux状态是如何维护的
  • 五、进程的优先级
  • 六、环境变量
    • 6.1 环境变量的基本概念
    • 6.2和环境变量相关命令
    • 6.3获取环境变量的方式
  • 七、进程地址空间
    • 7.1程序地址空间
    • 7.2写时拷贝

一、基本概念

  • 课本概念:程序的一个执行实例,正在执行的程序等
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体。

1.1描述进程-PCB

操作系统是一个软硬件资源管理的软件,那么相比进程也要被操作系统(OS)管理。
那么操作系统是如何对进程进行管理的呢?答案肯定是:先描述,在组织,对一个进程我们首先要用计算机语言对其进行描述,再利用相关的数据结构将其组织管理起来。
在操作系统的书籍上称描述进程的结构体为pcb,在linux操作系统下这个结构体叫做task_struct,这是在操作系统内核中创建的一种数据结构。但是一台计算机上会同时有多个进程(你可以打开你的任务管理器,看到许多进程正在跑着),操作系统是如何将这么多进程组织起来的呢?
是将各个进程的pcb(process control block)利用链表这种数据结构对其组织起来。
在这里插入图片描述

1.2task_struct中内容分类

操作系统内核中创建pcb来完成对进程的管理,那么这个结构体里究竟都有什么内容呢?

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 这里的标示符指的是PID
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据。
  • I/ O状态信息: 包括显示的I/O请求,分配给进程的I/ O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息
//截取源码部分
struct task_struct {volatile long state;//状态	/* -1 unrunnable, 0 runnable, >0 stopped */void *stack;//栈atomic_t usage;unsigned int flags;	/* per process flags, defined below */unsigned int ptrace;int lock_depth;		/* BKL lock depth *//* task state */int exit_state;int exit_code, exit_signal;int pdeath_signal;  /*  The signal sent when the parent dies  *//* ??? */unsigned int personality;unsigned did_exec:1;unsigned in_execve:1;	/* Tell the LSMs that the process is doing an* execve */unsigned in_iowait:1;/* Revert to default priority/policy when forking */unsigned sched_reset_on_fork:1;pid_t pid;//标识符pid_t tgid;//...
};

二、了解进程

2.1查看进程

先看看猪跑的样子(嘿嘿)。
进程的信息可以通过 /proc 系统文件夹查看
在这里插入图片描述
大多数的进程同样可以通过top、ps这样的工具来查看
在这里插入图片描述
自己创建一个进程
普通的代码:
在这里插入图片描述
在这里插入图片描述

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

  • 进程id(PID)
  • 父进程id(PPID)
    在这里插入图片描述
    在这里插入图片描述
    这里可以看到test的pid是13414而它的ppid为9927,它的父进程是什么呢?
    其实可以查看下。
    ps -axj | head -1 && ps -axj | grep bash | grep -v grep
    在这里插入图片描述
    结论:我们自己写的程序是通过bash来创建子进程执行的,所以使用命令行bash启动的程序,其父进程都是bash。

三、fork创建进程

3.1fork()函数

fork 函数的作用是创建一个子进程,函数声明如下:
在这里插入图片描述
这里提一下返回值,父进程创建成功会返回子进程的PID,创建失败返回 -1,创建出子进程以后,子进程也会执行fork,但是子进程不会继续创建新的进程,因此返回值是0。这是我们辨别父子进程的关键依据。

  • 子进程运行 fork()函数 返回0
  • 父进程运行 fork()函数 返回子进程的PID
    fork()函数调用后的变化:
    fork之后,执行流会变成两个执行流
    fork执行之后父子进程,父子进程谁先执行是随机的由调度器决定先调度谁
    fork之后,fork之后的代码共享,通常我们采用if else 语句来进行分流,父子进程执行不同的代码
    不同进程之间是相互独立的,父子进程也是如此,这是如何实现的呢?
    对于代码:代码是只读的,父子进程公用一份代码谁读谁的代码互不影响。
    对于数据:当有一个执行流想要修改数据的时候会发生写时拷贝(下面的进程地址空间会提到),来保证进程的独立性。
    使用fork( )创建子进程的例子:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    打印的顺序不一定是先打印父进程,然后打印子进程,顺序是随机的,子进程被创建以后,会立马加入到运行队列中,谁先运行完,就先打印
    问题:为什么要给子进程返回0给父进程返回子进程的pid?
    答案:返回不同的返回值,是为了区分让不同的执行流执行不同的代码块!一般而言fork之后的代码父子共享。一个父进程可以有多个子进程,而一个子进程可以有多个父进程,给父进程返回子进程的pid可以用来标识子进程的唯一性其目的也是为了区分子进程。

3.2写时拷贝

写时拷贝现象:
先看以下代码与执行结果。
在这里插入图片描述
我们发现,两次打印的值居然不一样,不是说父子进程共享一份数据和代码吗??
答案是发生了写时拷贝!!
写时拷贝原理:
在这里插入图片描述
在这里插入图片描述

四、进程的状态

4.1操作系统学科里的进程状态(运行、阻塞、挂起)

运行状态:
在这里插入图片描述
阻塞状态:
当一个进程的资源没有就绪时,系统会把这个进程放入等待队列中,当这个资源就绪时,就会把进程从等待队列放入运行队列中。
挂起状态:
假设操作系统的内存严重不足时,将等待队列中进程的代码和数据“换出”时,这个进程的状态为挂起状态。

4.具体的Linux状态是如何维护的

下面的状态在kernel源代码里定义:

/** The task state array is a strange "bitmap" of* reasons to sleep. Thus "running" is zero, and* you can test for combinations of others with* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
}; 
  • R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的
    进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送 SIGCONT
    信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)
没有读取到子进程退出的返回代码时就会产生僵死(尸)进程僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
僵尸进程的危害:
进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎
么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话
说,Z状态一直不退出,PCB一直都要维护?是的!
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构
对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空
间!
孤儿进程:
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号init进程领养,当然要有init进程回收喽

五、进程的优先级

问题1:什么是优先级
进程的优先级代表了对于资源的访问,谁先访问,谁后访问。
问题2:为什么要有进程优先级
因为资源是有限的,进程是多个的,注定了进程之间的竞争关系!操作系统必须保证进程的良性竞争,确认优先级。
问题3:怎么修改优先级
在这里插入图片描述

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
    Linux不想过多的让用户参与优先级的调整,在我们对应的范围内进行优先级调整,nice:[-20,19]
    PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。
    用top命令更改已存在进程的nice:
  • top
  • 进入top后按“r”–>输入进程PID–>输入nice值

六、环境变量

6.1 环境变量的基本概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但
    是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

6.2和环境变量相关命令

  1. echo: 显示某个环境变量值
  2. export: 设置一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量和环境变量

6.3获取环境变量的方式

1.命令行第三个参数

#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{int i = 0;for(; env[i]; i++){printf("%s\n", env[i]);}return 0;
}

2.通过第三方变量environ获取

#include <stdio.h>
int main(int argc, char *argv[])
{extern char **environ;int i = 0;for(; environ[i]; i++){printf("%s\n", environ[i]);}return 0;
}

总结:
环境变量是系统提供的一组name=value形式的变量,不同的环境变量有不同的用户,通常具有全局属性,可以被子进程继承。
我们所运行的进程都是子进程,bash在启动时会从操作系统的配置文件中读取环境变量的信息,子进程会继承父进程交给他的环境变量。

七、进程地址空间

7.1程序地址空间

在这里插入图片描述
验证的代码及结果:
在这里插入图片描述

7.2写时拷贝

在这里插入图片描述
在这里插入图片描述
所谓的地址空间是什么?
本质上是一个描述进程可视范围的大小,地址空间内一定要存在各种区域的划分,对线性地址进行start、end即可。
地址空间本质是内核的一个数据结构对象,类似PCB一样,地址空间也是要被操作系统管理的:先描述、在组织
在这里插入图片描述
为什么要有进程地址空间:
1.让进程以统一的视角看待内存。
2.增加进程虚拟空间可以让我们访问内存的时候,增加一个转换的过程,在这个转换的过程中,可以对我们的寻址请求进行在审查,一旦有异常访问,直接拦截,该请求不会到达物理内存,保护物理内存。
3.因为有地址空间和页表的存在,将进程管理模块和呢村管理模块进行解耦合!

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

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

相关文章

xampp环境安装

XAMPP是完全免费且易于安装的Apache发行版&#xff0c;其中包含Apache、MariaDB、PHP和Perl。 类似XAMPP的服务器套件还有很多&#xff0c;我用过的还有UPUPW&#xff0c;它们都极大的简化了开发环境的配置。 下载链接Download XAMPP 我选的最新的 一路next就安装好了。 访问…

百度曾出价 8500 万挖“AI 教父”被拒;GPT-3.5 图灵测试中败给上世纪 AI丨 RTE 开发者日报 Vol.99

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

创建 Python Docker 镜像的完整指南

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python和Docker是两个极其流行的技术&#xff0c;结合它们可以创建强大的应用程序。Docker允许将应用程序及其依赖项打包到一个独立的容器中&#xff0c;而Python则提供了丰富的库和工具来开发应用程序。本文将提…

2023年12月5日作业:多态

题目&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;class Animals { private:string name; public:Animals(){}Animals(string name):name(name){}virtual void perform() 0;void show(){cout << "这个动物是" << name…

使用肘部法则选择KMeans聚类中的k值

在这篇文章中&#xff0c;我们将讨论如何选择最好的k&#xff08;聚类数&#xff09;的k-Means聚类算法。 肘部法则简介 任何无监督算法的基本步骤是确定数据可以被聚类到的聚类的最佳数量。因为我们在无监督学习中没有任何预定义数量的聚类。我们倾向于使用一些可以帮助我们…

通过断点调试解决node 运行js程序直接退出(没有任何报错提示)的问题

现象&#xff1a; node运行程序直接退出&#xff0c;但是从echo $?的返回值可以知道&#xff1a; 一定出现了错误&#xff0c;但是没有显示出来 解决办法&#xff1a; 1. 使用node --inspect-brk 启动程序 然后在浏览器访问chrome://inspect 然后点击inspect 进行单步调试 …

Java中的File详细说明

File的概述--> File常见的构造方法--> 代码示范---> /*public File(String pathname) 根据文件路径创建文件对象根据字符串表示的路径&#xff0c;创建File对象*/String str "E:\\java_code\\a.txt";File f1 new File(str);System.out.println(f1);//结果…

000FreeCAD源码学习--MainGui.cpp

目录 1 MainGui.cpp源代码 2 int main()函数分析 3 编译运行截图 FreeCADMain项目下的MainGui.cpp 1 MainGui.cpp源代码 int main( int argc, char ** argv ) { #if defined (FC_OS_LINUX) || defined(FC_OS_BSD)setlocale(LC_ALL, ""); // use native environm…

使用pyscenedetect进行视频场景切割

1. 简介 在视频剪辑有转场一词&#xff1a;一个视频场景转换到另一个视频场景&#xff0c;场景与场景之间的过渡或转换&#xff0c;就叫做转场。 本篇介绍一个强大的开源工具PySceneDetect&#xff0c;它是一款基于opencv的视频场景切换检测和分析工具&#xff0c;项目地址: h…

龙迅#LT8311X3 USB中继器应用描述!

1. 概述 LT8311X3是一款USB 2.0高速信号中继器&#xff0c;用于补偿ISI引起的高速信号衰减。通过外部下拉电阻器选择的编程补偿增益有助于提高 USB 2.0 高速信号质量并通过 CTS 测试。 2. 特点 • 兼容 USB 2.0、OTG 2.0 和 BC 1.2• 支持 HS、FS、LS 信令 • 自动检测和补偿 U…

界面控件DevExpress WPF导航组件,助力升级应用程序用户体验!(上)

DevExpress WPF的Side Navigation&#xff08;侧边导航&#xff09;、TreeView、导航面板组件能帮助开发者在WPF项目中添加Windows样式的资源管理器栏或Outlook NavBar&#xff08;导航栏&#xff09;&#xff0c;DevExpress WPF NavBar和Accordion控件包含了许多开发人员友好的…

Python OS模块常用方法整理

os模块包含了普遍的操作系统和文件目录方法 引入类库 首先需要引入类库 import os 常用方法 OS模块方法 获取操作系统类型 nt->window:Microsoft Windows NT posix->Linux/Mac OS: Portable Operating System Interface of UNIX&#xff08;可移植操作系统接口&…

深入理解Java核心技术:Java工程师的实用干货笔记

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在Java工程师的职业生涯中&#xff0c;深入理解…

K8S部署nginx并且使用NFS存储数据

安装NFS 在master安装NFS systemctl start nfs-server修改配置 /etc/exports /data *(rw,no_root_squash,no_all_squash,sync)目录为 /data 允许所有地址访问 验证下 [rootmaster nginx]# showmount -e 192.168.57.61 Export list for 192.168.57.61: /data *共享可以正常…

基于 springboot + vue 健身房管理系统 毕业设计-附源码

qq&#xff08;2829419543&#xff09;获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;springboot 前端&#xff1a;采用vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xf…

使用 husky 和 lint-staged 配置代码检查工作流

提交代码前做代码检查 如果我们不做代码检查&#xff0c;有时候有代码错误&#xff0c;我们不能及时发现&#xff0c;只有打开代码块才知道&#xff0c;这样在提交仓库时也会忽略&#xff0c;很危险。 1、初始化 git仓库&#xff0c;执行 git init 即可 2、初始化 husky 工具配…

12月5日作业

以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一位讲解员&…

面向注解编程—Spring 注解看这一篇就够了(2)

面向注解编程—Spring注解大全&#xff08;AOP篇&#xff09; AOP英文全称&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;其实说白 了&#xff0c;面向切面编程就是面向特定方法编程。 AOP的作用&#xff1a;在程序…

排序的概念及其运用

1.排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序…

⭐ Unity里 用Shader 去做实时动态绿幕抠图

1.先看一下效果 a.这是背景图片 b.抠完图之后(这里用的是扣去白色的) 2.shader代码如下 Shader "UniversalChromaKey" {Properties{_MainTex("Base (RGB)", 2D) "white" {}_Sens("Sensibilidad", Range(0,.9)) .3_Cutoff("R…