<Linux>进程

news2024/11/22 16:09:20

进程

文章目录

  • 进程
    • PCB
    • pid与ppid
    • fork系统调用
    • 进程状态
    • 孤儿进程
    • 状态优先级
    • 环境变量
    • 进程地址空间
    • 虚拟地址

最直观的表示:启动一个软件,本质就是启动一个进程

PCB

PCB是Process Control Block的简称,是用来描述进程状态信息的数据结构。

进程运行时,是会在内存中存放该进程的代码+数据

因此:进程=代码和数据+PCB

这里的PCB结构是一种泛化的概念,在Linux下,PCB的实例化就是task_struct

pid与ppid

就像人有名字一样,进程也有自己的名字,进程的名字就是pid,ppid就是该进程的父进程的pid

fork系统调用

fork是创建进程的系统调用,给父进程返回子进程pid,给子进程返回0

#include<stdio.h>
#include<sys/types.h>

int main()
{
    pid_t id =fork();

    if(0!=id)
    {
        printf("我是父进程,pid:%d 我的子进程pid:%d\n",getpid(),id);
        //getpid()返回pid
    }
    else if(0==id)
    {

        printf("我是子进程,pid:%d 我的父进程pid:%d\n",getpid(),getppid());
        //getppid()返回父进程pid
    }
    return 0;
}

运行结果如下
在这里插入图片描述

注意

  • fork之后会有两个不同的执行流,至于父进程对于执行流先运行还是子进程对于执行流先运行不一定,这由操作系统的调度器决定
  • fork之后代码由父子进程共享

fork之后子进程会拷贝父进程的代码与数据给自己,操作系统会给子进程创建对应的PCB。

进程状态

  • 运行态,这里的运行态不单单指在cpu上运行才叫做运行态,在运行队列中排队等待调度器调度时也叫做运行态
  • 阻塞,阻塞态可以简单地理解为进程等待某种资源的释放或某种事件的发生,进程在这种状态下暂时停止执行,直到所需的资源可用或所等待的事件发生为止。
  • 挂起,内存不足时,操作系统会适当置换进程的代码与数据到磁盘,这种状态就叫做挂起状态。

Linux下的进程状态

  • R:就是上面运行态

验证R状态

#include <stdio.h>

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

运行起来之后写一段shell脚本来检测进程运行状态

while :;do  ps axj | head -1 && ps axj | grep test | grep -v grep ; sleep 1 ;echo "------------------"; done

在这里插入图片描述

R后面的‘+’表示这是一个前台进程

  • S:对于上面阻塞态,可被操作系统唤醒,可中断睡眠

验证S状态

#include <stdio.h>

int main()
{
    int a;
    scanf("%d", &a);
    return 0;
}

运行起来之后,系统会等着你输入,这时候不要输入,去查看进程状态

在这里插入图片描述

  • D:深度睡眠,不可被中断,不可被被动唤醒

不做验证

  • T:暂停状态

在用一些调试工具调试时可以验证,这里不做验证

  • Z:僵尸状态,进程已经退出,但是还不允许操作系统释放,处于被检测的状态。维持该状态是为了父进程/操作系统来回收

验证Z状态

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

可以看到,前面三秒都是S装态,这里S状态是因为sleep了一秒钟,第四秒开始子进程变成僵尸状态,等待着父进程或者操作系统来回收,也就是对应的Z状态

在这里插入图片描述

子进程的进程名后面出现了‘defunct’,即为失效的,即僵尸状态

在这里插入图片描述

打印输出也只剩父进程

如何解决僵尸进程?在我的另一篇博客:中有详细解读,感兴趣的朋友可以自行阅读。

  • X:终止状态

孤儿进程

父进程先退出,子进程就被称为孤儿进程,此时该进程就会被init进程(pid为1)领养,由init回收

验证孤儿进程

// 验证孤儿进程
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

int main()
{
    pid_t id = fork();
    if (0 == id)
    {
        while (1)
        {
            printf("我是子进程,pid:%d,ppid:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else
    {
        int cnt = 3;
        while (cnt--)
        {
            printf("我是父进程,pid:%d,ppid:%d\n", getpid(), getppid());
            sleep(1);
        }
        exit(0);
    }
    return 0;
}

在这里插入图片描述

可以看到,前三秒父进程和子进程同时在跑,但是3秒后父进程退出,子进程被1号进程领养

状态优先级

进程优先级即cpu资源分配的先后顺序

查看进程优先级命令

ps -l

在这里插入图片描述

  • PRI

代表进程优先级,数值越小,优先级越高

  • NI

nice值,用来更改进程优先级,取值范围[-20,19]

PRI=PRI+NI

所以想要修改进程优先级,就要通过修改nice值来进而修改进程优先级

修改进程优先级命令

top

输入‘r’后输入进程pid,随后修改nice值即可

环境变量

先来看现象

我们写一个打印的程序

#include <stdio.h>
int main()
{
    printf("hello linux\n");
    return 0;
}

在这里插入图片描述

使用系统自带的命令时,不用带路径,直接可以运行,但是我们自己写的程序如果不带路径就会报错。

这就和环境变量有关

查看环境变量

echo $PATH

在这里插入图片描述

这里维护了大量的路径,路径之间用冒号’:‘隔开,我们使用的诸如’ls’,'pwd’的系统命令就在这些路径当中,我们可以查看一下ls所处的路径

which ls

在这里插入图片描述

所以我们运行自己的程序时,shell会在这些路径中去查找’myproc’,没有找到就会显示’command not found’

如果不想带路径运行自己的程序,可以将可执行程序所在的路径导入到系统环境变量中,即可像系统指令一样执行自己写的程序。

export PATH=$PATH:程序所在路径

在这里插入图片描述

导入之后再查看系统环境变量,这时程序即可直接运行,不用带路径

但是,这种方式只在本次对话当中有用,下次连接系统时不会存在这个路径,如果需要永久保存,需要修改环境变量配置文件。

但是呢,环境变量不止PATH,还有HOME

echo $HOME

在这里插入图片描述

SHELL环境变量

echo $SHELL

在这里插入图片描述

显示所有环境变量

env
  • 子进程的环境变量继承自父进程,往上层去找最终就是bash的环境变量
  • 环境变量具有全局属性,体现在可以被子进程继承

进程地址空间

在c/c++程序员眼中,程序地址空间如下

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
int uninit_global;
int init_global = 10;

int main(int argc, char *argv[], char *env[])
{
    const char *str = "read only";

    int *heap1 = (int *)malloc(sizeof(int));
    int *heap2 = (int *)malloc(sizeof(int));

    printf("code address:%p\n", main);
    printf("read only address:%p\n", str);
    printf("init_global address:%p\n", &init_global);
    printf("uninit_global address:%p\n", &uninit_global);
    printf("head address:%p\n", heap1);
    printf("head address:%p\n", heap2);

    printf("stack address:%p\n", &heap1);
    printf("stack address:%p\n", &heap2);

    int i = 0;
    for (i = 0; i < argc; i++)
    {
        printf("argv[%d] address:%p\n", i, &argv[i]);
    }
    for (i = 0; env[i]; i++)
    {
        printf("env[%d]:%p\n", i, env[i]);
    }

    return 0;
}

输入命令运行结果如下

在这里插入图片描述

虚拟地址

为什么叫虚拟地址空间?难道上面我们讲的进程地址空间都是虚拟的?假的? 没错!!就是假的!!

如果直接让用户对真实的 物理空间进行读写访问,其实是非常危险的动作,因此,操作系统不会让你直接访问真实的物理地址。

操作系统表面上告诉进程,计算机的地址空间全是你的,但是其实不然。

先来一段代码

#include <stdio.h>
#include <sys/types.h>

int global = 10;

int main()
{
    pid_t id = fork();
    if (0 == id)
    {
        printf("global_val:%d---%p\n", global, &global);
    }
    else
    {
        global = 5;
        printf("global_val:%d---%p\n", global, &global);
    }
    return 0;
}

运行结果如下

在这里插入图片描述

出现了非常神奇的现象?同一个地址为什么对应的值不同???

我们知道,父进程在创建子进程之后会给子进程拷贝一份父进程的代码与数据,也会给子进程创建对应的程序地址空间,而这个程序地址空间就属于虚拟地址,需要页表哈希索引来找到对应的真实的物理地址,子进程拷贝的虚拟地址与父进程对应的虚拟地址一样,所以出现了地址一样,值却不一样的现象。解析图如下

在这里插入图片描述

上述程序因为拷贝了父进程的代码与数据,拷贝的地址属于虚拟地址,经过页表置换后才能找到真正的物理地址。

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

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

相关文章

了解并解决 Flutter 中的灰屏问题

生产中的 flutter 应用程序中的灰屏是一种通用占位符&#xff0c;当框架遇到问题无法渲染预期用户界面时就会显示。是的&#xff0c;所以基本上是出现问题时的后备指示器。 有趣的是&#xff0c;这只出现在发布模式下。在任何其他模式下运行都会显示红色错误屏幕&#xff0c;并…

课设--学生成绩管理系统(二)

欢迎来到 Papicatch的博客 目录 &#x1f40b;引言 &#x1f988;编写目的 &#x1f988;项目说明 &#x1f40b;产品介绍 &#x1f988;产品概要说明 &#x1f988;产品用户定位 &#x1f988;产品中的角色 &#x1f40b; 产品总体业务流程图 &#x1f40b; 产品功…

【PL理论】(25) C- 语言:表达式求值的推理规则 | 执行语句的推理规则 | 语句执行的推理规则

&#x1f4ad; 写在前面&#xff1a;本章我们将继续更新我们的 "C-" 语言&#xff0c;更新表达式求值的推理规则、执行语句的推理规则以及语句执行的推理规则。 目录 0x00 C- 语言更新&#xff1a;表达式求值的推理规则 0x01 C- 语言更新&#xff1a;执行语句的推…

观察者模式(大话设计模式)C/C++版本

观察者模式 扩展&#xff1a;观察者模式——委托 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15905936.html #include <iostream> #include <list> #include <memory> #include <string> using namespace std;// Observer类 抽象观…

港科夜闻 | 香港科大与香港科大(广州)合推红鸟跨校园学习计划,共享教学资源,促进港穗学生交流学习...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与香港科大(广州)合推“红鸟跨校园学习计划”&#xff0c;共享教学资源&#xff0c;促进港穗学生交流学习。香港科大与香港科大(广州)6月14日共同宣布推出“红鸟跨校园学习计划”&#xff0c;以进一步加强两校学…

5.拼数 - 蓝桥杯

基础知识要求&#xff1a; Java&#xff1a;for循环、if判断、Scanner类、数组、字符串 Python&#xff1a; for循环、if判断、列表、字符串、input() 题目&#xff1a; 思路解析&#xff1a; 读取输入&#xff1a; 首先读取要排序的字符串数量。然后读取相应数量的字符串&am…

【Redis】String的常用命令及图解String使用场景

本文将详细介绍 Redis String 类型的常见命令及其使用场景&#xff0c;包括缓存、计数器、共享会话、手机验证码、分布式锁等场景&#xff0c;并且配图和伪代码进一步方便理解和使用。 命令执行效果时间复杂度set key value [key value…]设置key的值是valueO(k),k是键个数get…

使用消息队列(MQ)实现MySQL持久化存储与MySQL server has gone away问题解决

在现代应用程序开发中&#xff0c;消息队列&#xff08;MQ&#xff09;扮演着重要的角色。它们可以帮助我们解决异步通信和解耦系统组件之间的依赖关系。而其中一个常见的需求是将消息队列中的数据持久化到数据库中&#xff0c;以确保数据的安全性和可靠性。在本文中&#xff0…

gbase8s数据库阻塞检查点和非阻塞检查点的执行机制

1. 检查点的描述 为了便于数据库系统的复原和逻辑恢复&#xff0c;数据库服务器生成的一致性标志点&#xff0c;称为检查点&#xff0c;其是建立在数据库系统的已知和一致状态时日志中的某个时间点检查点的目的在于定期将逻辑日志中的重新启动点向前移动 如果存在检查点&#…

【Quartus 13.0】NIOS II 部署UART 和 PWM

打算在 EP1C3T144I7 芯片上部署 nios ii 做 uart & pwm控制 这个芯片或许不够做 QT 部署 这个芯片好老啊&#xff0c;但是做控制足够了&#xff0c;我只是想装13写 leader给的接口代码是用VHDL写的&#xff0c;我不会 当然verilog我也不太会 就这样&#xff0c;随便写吧 co…

[大模型]XVERSE-7B-chat Transformers 推理

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

【ARMv8/ARMv9 硬件加速系列 3.2 -- SVE 读写内存指令 st1b | st1w | st1w | st1d 使用介绍】

文章目录 SVE Load 和 Store 指令使用介绍LD1 加载指令ST1 存储指令PFR 预取指令参考示例LD1 加载示例ST1 存储示例 代码实例 SVE Load 和 Store 指令使用介绍 ARMv9架构中的SVE&#xff08;Scalable Vector Extension&#xff09;指令集为向量计算提供了强大支持&#xff0c;…

fs.1.10 ON rockeylinux8 dockerfile模式

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 rockeylinux8 docker上编译安装fs.1.10的流程记录&#xff0c;本文使用dockerfile模式。 环境 docker engine&#xff1a;Version 24.0.6 rockylinux docker&#xff1a;8 freeswitch&#xff1a;v1.10.7 dockerfi…

CleanMyMacX4.15.4如何优化苹果电脑系统缓存,告别MacBook卡顿,提升mac电脑性能

你是否曾为苹果电脑存储空间不够而烦恼&#xff1f;是否曾因系统运行缓慢而苦恼&#xff1f;别担心&#xff0c;今天我要给大家种草一个神器——CleanMyMac&#xff01;这款软件可以帮助你轻松解决苹果电脑的种种问题&#xff0c;让你的电脑焕然一新&#xff01; 让我来给大家介…

显著提高iOS应用中Web页面的加载速度 - 提前下载页面的关键资源(如JavaScript、CSS和图像)

手动下载并缓存资源是一种有效的方式&#xff0c;可以确保在需要时资源已经在本地存储&#xff0c;这样可以显著提高加载速度。 缓存整个 web 页面的所有资源文件 具体实现步骤 下载和缓存资源&#xff1a;包括 HTML 文件、CSS、JavaScript 和图像。在应用启动时预加载资源。…

CSS从入门到精通——动画:CSS3动画执行次数和逆向播放

目录 任务描述 相关知识 动画执行次数 动画反向播放 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现loading效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画执行次数&#xff0c;2.动画反向播放。 需要实现的效…

CSS从入门到精通——动画:CSS3动画延迟和完成后状态的保持

目录 任务描述 相关知识 动画状态 动画完成时的状态 动画延迟 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现小车等待红绿灯的效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画状态&#xff0c;2.动画完成时的状…

mac下Xcode在iphone真机上测试运行iOS软件

最近一个需求需要在iPhone真机上测试一个视频直播的项目。 需要解决如何将项目 app 安装到真机上 在进行真机调试。 安装Xcode 直接在App Store上搜索Xcode安装即可。 关键是要安装Simulator。项目需要安装iOS17.5但是由于安装包太大&#xff0c;并且网络不稳定的原因。在Xco…

关于yolov5训练的那些事儿

1.YOLOv5 的模型系列包括从最小到最大的多种模型&#xff1a;YOLOv5n&#xff08;Nano&#xff09;&#xff0c;YOLOv5s&#xff08;Small&#xff09;&#xff0c;YOLOv5m&#xff08;Medium&#xff09;&#xff0c;YOLOv5l&#xff08;Large&#xff09;&#xff0c;以及 YO…

【Linux硬盘读取】Windows下读取Linux系统的文件解决方案:Linux Reader4.5 By DiskInternals

前言 相信做机器视觉相关的很多人都会安装 Windows 和 Linux 双系统。在 Linux 下&#xff0c;我们可以很方便的访问Windows的磁盘&#xff0c;反过来却不行。但是这又是必须的。通过亲身体验&#xff0c;向大家推荐这么一个工具&#xff0c;可以让 Windows 方便的访问 Ext 2/3…