【Linux】进程

----------------| 本文目录 |----------------

  • 1. 进程
    • 1.1 基本概念
    • 1.2 描述进程 - PCB
      • 1.2.1 task_struct - PCB的一种
      • 1.2.2 task_struct 内容分类
    • 1.3 组织进程
    • 1.4 查看进程
    • 1.5 通过系统调用获取进程标示符
    • 1.6 通过系统调用创建进程 - fork初识
  • 2. 进程状态
    • 2.1 看看Linux内核源代码怎么说
    • 2.2 进程状态查看
    • 2.3 Z(zombie) - 僵尸进程
    • 2.4 僵尸进程危害
    • 2.5 进程状态总结
    • 2.6 孤儿进程
  • 3. 进程优先级
    • 3.1 基本概念
    • 3.2 查看系统进程
      • 3.2.1 PRI and NI
      • 3.2.2 PRI vs NI
    • 3.3 查看进程优先级的命令
      • 3.3.1 用 top 命令更改已存在进程的 nice
    • 3.4 其他概念

在这里插入图片描述

1. 进程

1.1 基本概念

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

1.2 描述进程 - PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为 PCB(process control block),Linux 操作系统下的 PCB 是:task_struct

1.2.1 task_struct - PCB的一种

  • 在 Linux 中描述进程的结构体叫做 task_struct。
  • task_struct 是 Linux 内核的一种数据结构,它会被装载到 RAM(内存)里并且包含着进程的信息。

1.2.2 task_struct 内容分类

  • 标示符:描述本进程的唯一标示符,用来区别其他进程。
  • 状态:任务状态,退出代码,退出信号等。
  • 优先级:相对于其他进程的优先级。
  • 程序计数器:程序中即将被执行的下一条指令的地址。
  • 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
  • 上下文数据:进程执行时处理器的寄存器中的数据。
  • I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记帐号等。
  • 其他信息…

1.3 组织进程

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

1.4 查看进程

进程的信息可以通过 /proc 系统文件夹查看。

  • 如:要获取 PID 为 1 的进程信息,你需要查看 /proc/1 这个文件夹。

在这里插入图片描述

  • 大多数进程信息同样可以使用 top 和 ps 这些用户级工具来获取。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
	while (1)
	{
		sleep(1);
	}
	return 0;
}

在这里插入图片描述

1.5 通过系统调用获取进程标示符

  • 进程 id(PID)
  • 父进程 id(PPID)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    printf("pid: %d\n", getpid());
    printf("ppid: %d\n", getppid());
    return 0;
}

在这里插入图片描述

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

  • 运行 man fork 认识 fork
  • fork 有两个返回值
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int ret = fork();
    printf("hello proc: %d!, ret: %d\n", getpid(), ret);
    sleep(1);
    return 0;
}

在这里插入图片描述

  • fork 之后通常要用 if 进行分流
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int ret = fork();
    if (ret < 0)
    {
        perror("fork");
        return 1;
    }
    else if (ret == 0)
    {
        // child                                                                       
        printf("I am child: %d!, ret: %d\n", getpid(), ret);
    }
    else
    {
        // father
        printf("I am father: %d!, ret: %d\n", getpid(), ret);
    }
    sleep(1);
    return 0;
}

在这里插入图片描述

2. 进程状态

2.1 看看Linux内核源代码怎么说

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在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):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

2.2 进程状态查看

ps aux / ps axj 命令

在这里插入图片描述

2.3 Z(zombie) - 僵尸进程

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

创建一个维持30秒的僵尸进程例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return 1;
    }
    else if (id > 0)
    {
        // parent
        printf("parent[%d] is sleeping...\n", getpid());
        sleep(30);                                                      
    }
    else
    {
        // child
        printf("child[%d] is begin Z...\n", getpid());
        sleep(5);
        exit(EXIT_SUCCESS);
    }
    return 0;
}

编译并在另一个终端下启动监控

在这里插入图片描述

开始测试

在这里插入图片描述

看到结果

在这里插入图片描述

2.4 僵尸进程危害

  • 进程的退出状态必须被维持下去,因为他要告诉关心他的进程(父进程):你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于
    Z 状态?是的!
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在 task_struct(PCB)中,换句话说,Z 状态一直不退出,PCB 一直都要维护?是的!
  • 那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想 C 中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 内存泄漏?是的!

2.5 进程状态总结

  • 至此,值得关注的进程状态全部讲解完成,下面来认识另一种进程。

2.6 孤儿进程

  • 如果父进程提前退出,子进程后退出,进入 Z 状态后,该如何处理呢?
  • 父进程先退出,子进程就称之为“孤儿进程”。
  • 孤儿进程被 1 号 init 进程领养,当然要由 init 进程回收。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return 1;
    }  
    else if (id == 0)
    {  
        // child
        printf("I am child, pid: %d\n", getpid());
        sleep(10);                                             
    }
    else
    {  
        // parent
        printf("I am parent, pid: %d\n", getpid());
        sleep(3);
        exit(0);
    }
    return 0;
}

在这里插入图片描述

3. 进程优先级

3.1 基本概念

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

3.2 查看系统进程

在 Linux 或者 Unix 系统中,用 ps -l 命令则会类似输出以下几个内容:

在这里插入图片描述

我们很容易注意到其中的几个重要信息,如下:

  • UID:代表执行者的身份
  • PID:代表这个进程的代号
  • PPID:代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI:代表这个进程可被执行的优先级,其值越小越早被执行
  • NI:代表这个进程的 nice 值

3.2.1 PRI and NI

  • PRI 也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被 CPU 执行的先后顺序,此值越小进程的优先级别越高。
  • 那 NI 呢?就是我们所要说的 nice 值了,其表示进程可被执行的优先级的修正数值。
  • PRI 值越小越快被执行,那么加入 nice 值后,将会使得 PRI 变为:PRI(new) = PRI(old) + nice。
  • 这样,当 nice 值为负的时候,该程序会将优先级值变小,即:其优先级会变高,会更快的被执行。
  • 所以,调整进程优先级,在 Linux 下,就是调整进程 nice 值。
  • nice 其取值范围为: -20 ~ 19,一共 40 个级别。

3.2.2 PRI vs NI

  • 需要强调的一点是:进程的 nice 值不是进程的优先级,他们不是一个概念,但是进程 nice 值会影响到进程的优先级变化。
  • 可以理解 nice 值是进程优先级的修正数据。

3.3 查看进程优先级的命令

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

  1. 使用 top 命令

在这里插入图片描述

  1. 进入 top 后按 “r”

在这里插入图片描述

  1. 输入进程 PID

在这里插入图片描述

  1. 输入 nice 值

在这里插入图片描述

3.4 其他概念

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

END

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

美创科技第59号安全实验室最新力作!《内网渗透实战攻略》出版发行

总结先进攻防实战经验&#xff0c;基于创新入侵生命周期模型&#xff0c;为提升渗透实战能力提供系统操作教程&#xff01;近期&#xff0c;美创科技创始人&CEO柳遵梁&#xff0c;美创第59号安全实验室&#xff08;王月兵、覃锦端、毛菲、刘聪等&#xff09;撰写的新书《内…

时空序列问题的本质和底层逻辑

本质&#xff1a;Still need to polish this. 底层逻辑&#xff1a;Still need to polish this.See you pretty soon. Reference 【时空序列预测】什么是时空序列问题&#xff1f;这类问题主要应用了哪些模型&#xff1f;主要应用在哪些领域&#xff1f;_mb62b92582e5a0a的技…

办公场景日益多样化 企业如何保持安全?

当前&#xff0c;企业的办公场景日益多样化。远程办公、移动办公、云办公、分支机构等&#xff0c;这些新的办公场景也带来了新的网络安全挑战。以下将介绍一些办公场景带来的安全威胁。 1、远程办公&#xff1a;员工可以在任何地方工作&#xff0c;但同时也带来了网络安全的隐…

支付宝电脑端支付代码

在学习某些项目需要用到支付功能,如支付宝支付。 详细配置 演示沙箱环境下支付,沙箱环境和正式支付只不过一些参数不同 像AppId PrivateKey AlipayPublicKey gatewayUrl 这些参数会有不同。 代码配置 @Component @Data public class payConfig {private String PrivateKey…

springboot配置多数据源

在开发过程中&#xff0c;为了满足需求&#xff0c;会从第三方获取需要的数据&#xff0c;这个时候&#xff0c;除了使用原始的jdbc方式读取数据外&#xff0c;还可以配置多数据源来获取我们想要的数据。 第一步&#xff1a;pom.xml添加依赖 <dependency><groupId>…

JPackage指令将可执行Jar包打包成EXE运行程序

jpackage是jdk14正式加入的一个用于独立打包的工具。 官网简介翻译&#xff1a; jpackage工具将以Java应用程序和Java运行时映像作为输入&#xff0c;并生成一个包含所有必要依赖项的Java应用程序映像。它可以生成特定于平台格式的本机软件包&#xff0c;例如Windows上的exe或…

KVM系统虚拟化性能测试过程总结

buildroot编译 为啥要用buildroot 支持很多&#xff1a;交叉编译工具链、根文件系统生成、内核映像编译和引导加载程序编译。使用简单&#xff1a;使用类似内核的menuconfig、gconfig和xconfig配置界面&#xff0c;使用buildroot构建基本系统很容易。支持很多的包&#xff1a…

1.10 Unity中的数据存储 XML

一、XML 1.介绍 XML是一个文档后缀名是*.xmlXML是一个特殊格式的文档XML是可扩展的标记性语言XML是Extentsible Markup Language的缩 写XML是由万维网联盟(W3C)创建的标记语言&#xff0c;用于定义编码人类和机器可以读取的文档的语法。它通过使用定义文档结构的标签以及如何…

基于ubuntu2204使用kubeadm部署k8s集群

部署k8s集群 基础环境配置安装container安装runc安装CNI插件部署1.24版本k8s集群&#xff08;flannel&#xff09;安装crictl使用kubeadm部署集群节点加入集群部署flannel网络配置dashboard 本集群基于ubuntu2204系统使用kubeadm工具部署1.24版本k8s&#xff0c;容器运行时使用…

AIGC视频生成:Pika1.0快速入门详解

Pika1.0快速入门详解 一、简介二、登录三、参数设置1、改变画面大小&#xff08;Aspect ratio&#xff09;2、改变帧数大小&#xff08;Frames per second&#xff09;3、镜头平移&#xff08;Camera control&#xff09;4、画面运动控制&#xff08;Strength of motion&#x…

[Linux进程(一)] 什么是进程?PCB的底层是什么?以及进程标识符pid与ppid

文章目录 1、前言2、描述进程 — PCB(os怎么管理进程呢)3、查看进程3.1 方法一3.2 方法二 4、系统调用获取进程标示符(PID)4.1 获取进程的ID4.2 获取进程的父进程ID 5、系统调用创建子进程-fork 1、前言 大家经常都在讲进程&#xff0c;而它到底是什么呢&#xff1f; 这里给大…

UE5 UE4 修复GPU驱动程序崩溃

原贴链接&#xff1a;https://mp.weixin.qq.com/s/e5l9XtfwEFWgwhHi1b2idg UE5 UE4在处理含有大量图形的项目时&#xff0c;你有可能会遇到GPU崩溃 可以通过修改注册表&#xff0c;修复崩溃。 GPU崩溃情况概述 UE5 UE4在处理含有大量图形的项目时&#xff0c;你有可能会遇到G…

二线厂商-线上测评-大数据开发

曾经投递过一些中级岗位&#xff0c;在面试之前&#xff0c;会通过邮件的方式把性格测试的题目发给你让你做一下。 一般分为单选题&#xff0c;多选题&#xff0c;性格测试题&#xff0c;认知理解题等等。 大概做了一个小时吧。 单选题&#xff1a; 感觉就是类似于以前高中时候…

AI芯片:神经网络研发加速器、神经网络压缩简化、通用芯片 CPU 加速、专用芯片 GPU 加速

AI芯片&#xff1a; 神经网络研发加速器、神经网络压缩简化、通用芯片 CPU 加速、专用芯片 GPU 加速 神经网络研发加速器神经网络编译器神经网络编译器 神经网络加速与压缩&#xff08;算法层面&#xff09;知识蒸馏低秩分解轻量化网络剪枝量化 通用芯片 CPU 加速x86 加速arm 加…

OceanBase原生分布式数据库

1.历史背景 在Java Web项目中&#xff0c;常常使用免费开源的MySQL数据库存储业务数据&#xff0c;按业界经验MySQL单库超过多大数据体量&#xff0c;或单表超过几百万条数据后就会出现查询变慢的情况&#xff0c;单实例数据库只能扩展物理资源(CPU、内存)&#xff0c;来提升查…

ASP.NET Core高级之认证与授权(二)--JWT认证前后端完整实现

阅读本文你的收获 了解JWT身份认证的流程了解基于JWT身份认证和Session身份认证的区别学习如何在ASP.NET Core WebAPI项目中封装JWT认证功能 在上文ASP.NET Core高级之认证与授权(一)–JWT入门-颁发、验证令牌中演示了JWT认证的一个入门案例&#xff0c;本文是一个基于JWT认证…

docker 安装redis (亲测有效)

目录 1 安装 1 安装 1 将redis 的 tar 包 上传到服务器 上传之后tar 包&#xff0c;将他变成镜像 输入docker images,发现目前是没有镜像的&#xff0c;现在将tar 包变成镜像 docker load -i redis.tar以上就将tar 包变成镜像了 现在在宿主机找一个地方&#xff0c;存放数据…

跟我学java|Stream流式编程——并行流

什么是并行流 并行流是 Java 8 Stream API 中的一个特性。它可以将一个流的操作在多个线程上并行执行&#xff0c;以提高处理大量数据时的性能。 在传统的顺序流中&#xff0c;所有的操作都是在单个线程上按照顺序执行的。而并行流则会将流的元素分成多个小块&#xff0c;并在多…

DHSP和DNS

一、服务程序 1.1DHCP定义 DHCP&#xff08;动态主机配置协议&#xff09;是一个局域网的网络协议。指的是由服务器控制一段IP地址范围&#xff0c;客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下&#xff0c;DHCP作为Windows Server的一个服务组…

java基础之Java8新特性-方法引入

目录 1.简介 2.方法引入 方法引入遵循规范 方法引入种类 1.静态方法引入 2.对象方法引入 3.实例方法引入 4.构造函数引入 1.简介 方法引用是 Java 8 中引入的另一个重要特性&#xff0c;它提供了一种简洁的语法来直接引用现有方法或构造函数。方法引用可以看作是 Lambd…