初识进程

文章目录

  • 一、进程的概念
    • 1. 进程是什么及进程的管理
    • 2. Linux 下的 pcb
    • 3. 系统调用接口 getpid 和 getppid
    • 4. 系统调用接口 fork

一、进程的概念

1. 进程是什么及进程的管理

在 Linux下 ./binaryfile 运行一个程序或者在 Windows下双击运行一个程序时,程序就变成了一个进程

根据冯诺依曼体系结构,程序运行起来后,程序的代码和数据就会被操作系统加载到内存,但一个程序仅仅被加载到内存,并不代表该程序就是进程

将这里的内存比作学校程序比作人进程比作学校的学生,如果一个人处在学校中,并不能说明这个人就是学校的人,如:学校的保安,食堂阿姨等这些并不是学生,只有那些被学校管理起来的,并且信息在学校的学生档案中的人才能被称作学生,所以只有程序被操作系统管理起来,并且程序的代码和数据的相关信息被操作系统记录了,这个程序才被称做进程

在学校中,当学生很多时,我们需要对学生进行管理,在操作系统中,当很多程序运行起来时,加载到内存中的代码便会很多,操作系统便需要对这些代码和数据进行管理

根据我们对管理进行的建模,可以知道操作系统对加载到内存中代码和数据的管理方式:先描述,在组织

  • 先描述:为了管理程序运行后加载到内存中的代码和数据,操作系统采用了一个结构体对象 pcb,用来描述加载到内存中的代码和数据的相关属性,其中 pcb 中有一个内存指针,用来指向内存中的代码和数据
    在国内的教材中 pcb(process control block) 统一称作进程,在国外有的叫做任务,Linux 下的 pcb 称做 task_struck
    进程管理
    进程 = 内核中关于程序的相关结构体 + 程序的代码和数据

  • 在组织:每一个加载到内存中的代码和数据操作系统都会为其创建一个 pcb 对象,因此我们可以在 pcb 对象中在加上 pcb 结构体指针,构成数据结构中的链表
    Linux 下采用双链表的形式组织

当操作系统想新增一个进程时(启动一个程序),只需要创建一个 pcb,然后录入该程序的属性到 pcb 中,然后在链表中插入该 pcb

当操作系统想杀掉一个进程时(结束程序的运行),只需遍历链表,找到该进程的 pcb,然后通过内存指针释放 pcb 指向的内存中的代码和数据,在再链表中释放该 pcb 结点即可

当操作系统想查看一个进程的运行状态时(查看程序运行是否正常),只需要遍历链表,找到该进程的 pcb,然后查看状态信息即可

当操作系统想找到一个优先级别较高的进程执行时(让 CPU 运行指定程序),只需要遍历链表,找到该进程的 pcb,然后通过内存指针找到 pcb 指向的代码和数据,让 CPU 执行即可

通过先描述,再组织的方式,操作系统对进程的管理被完全的转换成了对 pcb 结构体组成的链表数据结构的增删查改

运行的可执行程序都要被操作系统转换为进程来调度以便完成特定的任务,因此当我们运行一个程序时,就称作 创建了一个进程

仅个人当前理解:软件其实就是一个在磁盘上的二进制文件,当软件运行起来后,便需要加载到内存,所以操作系统对进程的管理,便是对软件资源的管理

进程 = 内核中关于进程的相关数据结构 + 进程的代码和数据

2. Linux 下的 pcb

为了操作系统管理进程,需要描述出进程的共同属性,从而产生了结构体 pcb

task_struct 的字段

  • 标识符:描述本进程的唯一标识符,用来区别进程
  • 状态:任务状态,退出代码,退出信号等
  • 优先级:相对于其他进程的优先级
  • 程序计数器:程序中即将被执行的下一条指令的地址
  • 内存指针:包括程序diamante和进程的相关数据结构的指针,还有和其他进程共享的内存块的指针

pcb 和可执行程序的文件属性关系不大

3. 系统调用接口 getpid 和 getppid

如何证明程序运行起来,便成为了一个进程?

当我们创建一个进程时,操作系统就会在 /proc 目录下创建一个该进程 pid 为名的目录,该目录下存在该进程的属性(文件路径等),当进程终止时,/proc 目录中也会删除该进程 pid 为名的目录

预备知识1:
ps ajx:查看系统中所有的进程
ls /proc:查看系统中的所有进程,其中目录名为数字的表示进程的标识符 pid

[starrycat@iZ2vcer6gtjgqa43cdpeeaZ code]$ ps ajx
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     1     1     1 ?           -1 Ss       0   3:57 /usr/lib/systemd/systemd --system --deserialize 17
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     3     0     0 ?           -1 S        0   0:08 [ksoftirqd/0]
    2     5     0     0 ?           -1 S<       0   0:00 [kworker/0:0H]
    2     7     0     0 ?           -1 S        0   0:00 [migration/0]
...
[starrycat@iZ2vcer6gtjgqa43cdpeeaZ code]$ ls /proc
1     14     21134  25405  28     350  47   539   6770  854        crypto       interrupts  kpagecount  mtrr          softirqs       uptime
10    1523   21252  25512  280    36   49   557   6771  9          devices      iomem       kpageflags  net           stat           version
101   15631  21262  26     29     365  5    587   7     acpi       diskstats    ioports     loadavg     pagetypeinfo  swaps          vmallocinfo
1019  16     22     27     296    37   50   598   787   buddyinfo  dma          irq         locks       partitions    sys            vmstat
...

预备知识2:
pid_t getpid(void):返回调用该函数的进程标识符 pid,需要包含头文件 <sys/types.h> 和 <unistd.h>
pid_t:有符号整形的 typedef

如果想了解更多关于 getpid 函数的内容,通过 man 2 getpid 即可查看

接下来通过代码证明程序运行起来,便成为了一个进程

在 process.c 中写好如下代码:

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

int main()
{
    while(1)
    {
        printf("我是一个进程了,我的 pid 是:%d\n", getpid());
        sleep(1);
    }

    return 0;
}

证明1:
打开新的窗口,通过命令查看发现,运行的程序 process 可以查到他的进程标识符 pid

其中 ps ajx | head -1 表示获取进程的第一行属性字段(便于观看)
&& 表示当前一条指令执行成功后执行后一条指令
ps ajx | grep process | grep -v grep 表示筛选出 process 的进程,并且去除掉 grep 这个进程
在这里插入图片描述

过程2:
用 ctrl + c 终止程序后,便查找不到该进程了

在这里插入图片描述

终上所述,程序运行起来后就变成了进程


在进程中存在着父子进程的概念

pid_t getppid(void):返回调用该函数的进程的父进程标识符 pid,需要包含头文件 <sys/types.h> 和 <unistd.h>
pid_t:有符号整形的 typedef

在 process.c 中写好如下代码:

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

int main()
{
    while(1)
    {
        printf("我是一个进程了,我的 pid 是:%d,我的 ppid 是:%d\n", getpid(), getppid());
        sleep(1);
    }

    return 0;

不断的执行 process 会发现子进程的进程标识符一直在增加,但是父进程的进程标识符 6771 一直不变,通过 ps 命令后可以发现 6771 这个进程标识符就是命令行解释器 bash,即命令行执行的程序都是通过创建子进程的方式去执行的,是为了避免执行的程序挂了,导致影响 bash 自己

命令行解释器 bash 其实就是在 /bin/bash 的一个二进制可执行程序,因此 bash 也是一个进程
在这里插入图片描述

命令行启动的所有程序,都是 bash 创建的子进程,为了防止子进程挂了,导致影响自己

4. 系统调用接口 fork

命令行是如何创建子进程的呢?

pid_t fork(void):如果创建子进程成功,则给调用该函数的父进程返回子进程的 pid,给子进程返回 0,如果失败则返回 -1,需要包含头文件 <sys/types.h> 和 <unistd.h>

  • 在代码中执行到 fork 语句后,执行流变成了两个执行流
  • fork 之后的代码,父子进程都会执行,因此我们可以用 if 语句来让执行流分流,以便父子进程执行不同的代码块

在 process.c 中写好如下代码:

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

int main()
{
    pid_t ret = fork();
    if (ret == 0)
    {
        // 执行子进程
        while (1)
        {
            printf("我是子进程,我的 pid 是:%d,我的 ppid 是:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else if (ret > 0)
    {
        // 执行父进程 
        while (1)
        {
            printf("我是父进程,我的 pid 是:%d,我的 ppid 是:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else 
    {}

    return 0;
}
  • fork 创建子进程成功之后,父进程和子进程谁先被 CPU 调度运行是由操作系统决定的

可以通过 fork 系统调用来创建子进程

fork 创建子进程的过程:操作系统为了可以管理子进程,会根据父进程的 pcb 创建子进程的 pcb,并且子进程的 pcb 会和父进程的 pcb 指向同一块代码和数据

在这里插入图片描述

虽然父进程创建子进程后,子进程指向父进程的代码和数据,但是不同的进程在运行时是独立的,父子进程在运行时也是独立的

kill -9 pid 功能:杀掉进程

再次运行 process 之后,在另一个窗口中输入 kill -9 父进程 pid,此时子进程任然可以正常运行
在这里插入图片描述

父子进程是如何做到独立的呢?

  • 在代码层面:可执行程序的代码都是二进制机器指令了,是只读的,不可能被修改,因此父子进程可以一起读代码,只需要记住自己进程执行代码的位置即可
  • 在数据层面:Linux 操作系统采用写时拷贝的方式来保证数据的独立性,即:当某一个进程想要修改数据时,操作系统会自己拷贝一份数据到别的位置然后进行修改

为什么一个函数会有两个返回值?
因为一个函数在执行 return 之前,函数的主题功能已经完成了,对于 fork 函数,在 return 之前已经创建好子进程了,此时便有父子进程两个执行流,于是父子进程都会执行 return 语句,也就产生了两个返回值的现象

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

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

相关文章

【百面成神】spring基础12问,你能坚持到第几问

前 言 &#x1f349; 作者简介&#xff1a;半旧518&#xff0c;长跑型选手&#xff0c;立志坚持写10年博客&#xff0c;专注于java后端 ☕专栏简介&#xff1a;java面试宝典&#xff0c;特点&#xff1a;全、精、深、简&#xff0c;力求每个核心知识点1分钟回答好。 &#x1f3…

RK3588平台开发系列讲解(视频篇)RTP H264 码流打包详解

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、单 NALU 封包方式二、组合封包方式三、分片封包方式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 H264 码流是放在 RTP 的有效载荷部分的。因此有效载荷前面的 RTP 头部跟码流本身是没有关系的,所以我…

Python|蓝桥杯进阶第六卷——搜索

欢迎交流学习~~ 专栏&#xff1a; 蓝桥杯Python组刷题日寄 蓝桥杯进阶系列&#xff1a; &#x1f3c6; Python | 蓝桥杯进阶第一卷——字符串 &#x1f50e; Python | 蓝桥杯进阶第二卷——贪心 &#x1f49d; Python | 蓝桥杯进阶第三卷——动态规划 ✈️ Python | 蓝桥杯进阶…

mysql数据库介绍

&#x1f49c;今天对mysql的一些基础概念进行讲诶横扫&#xff0c;如概念、特点、优势、发展历史等等。对之前内容感兴趣的同学可以参考&#x1f447;&#xff1a; 链接: mysql学习之数据系统概述 &#x1f3be;让我们开始今日份的学习吧&#xff01; 目录1. mysql的基本概念…

十七、网上商城项目(5)

本章概要 购物车 购物车状态管理配置购物车组件 结算页面用户管理 用户状态管理配置用户注册组件用户登录组件 17.8 购物车 在一个电商网站中&#xff0c;购物车在很多页面都需要用到&#xff0c;因此非常适合放在 Vuex 的 store 中进行集中管理。在本项目中&#xff0c;采…

【北大青鸟天府校区的Java专业怎么样?】

北大青鸟天府校区是北大青鸟总部在西南投资兴办的重点校区&#xff0c;拥有极为强大的外部教育资源和就业资源&#xff0c;使咱们的学员能够享受更好、更完善的教学资源。超过23年的办学经验&#xff0c;培养了超过10000位学员&#xff0c;保障就业&#xff0c;学员就业率达到9…

[入门必看]数据结构2.3:线性表的链式表示

[入门必看]数据结构2.3&#xff1a;线性表的链式表示第二章 线性表2.3 线性表的链式表示知识总览2.3.1 单链表的定义2.3.2_1 单链表的插入删除2.3.2_2 单链表的查找2.3.2_3 单链表的建立2.3.3 双链表2.3.4 循环链表2.3.5 静态链表2.3.6 顺序表和链表的比较2.3.1 单链表的定义单…

JUC高级四:Java内存模型之JMM

JUC高级四:Java内存模型之JMM 1. 计算机硬件存储体系(JMM为什么诞生) 因为有这么多级的缓存(cpu和物理主内存的速度不一致的)&#xff0c;CPU的运行并不是直接操作内存而是先把内存里边的数据读到缓存&#xff0c;而内存的读和写操作的时候就会造成不一致的问题 在我们cpu寄存…

WebRTC开源库内部调用abort函数引发程序发生闪退问题的排查

目录 1、初始问题描述 2、使用Process Explorer工具查看到处理音视频业务的rtcmpdll.dll模块没有加载起来 3、使用Dependency Walker工具查看到rtcmpdll.dll依赖的库有问题 4、更新库之后Debug程序启动时就发生异常&#xff0c;程序闪退 5、VS调试时看不到有效的函数调用堆…

十大Python可视化工具,太强了

今天介绍Python当中十大可视化工具&#xff0c;每一个都独具特色&#xff0c;惊艳一方。 Matplotlib Matplotlib 是 Python 的一个绘图库&#xff0c;可以绘制出高质量的折线图、散点图、柱状图、条形图等等。它也是许多其他可视化库的基础。 import matplotlib.pyplot as p…

OpenCV入门(二十)快速学会OpenCV 19 对象测量

OpenCV入门&#xff08;二十&#xff09;快速学会OpenCV 19 对象测量1.对象测量2.多边形拟合3.计算对象中心作者&#xff1a;Xiou 1.对象测量 opencv 中对象测量包括&#xff1a; 如面积&#xff0c;周长&#xff0c;质心&#xff0c;边界框等。 弧长与面积测量&#xff1b; …

《LKD3粗读笔记》(4)进程调度

1、多任务 什么是多任务操作系统&#xff1f; 能同时并发地交互执行多个进程。注意是并发而不是并行。特别地&#xff0c;在多处理机机器上可以实现真正意义上的并行&#xff0c;因为它长了多个脑子多任务操作系统有哪些分类&#xff1f; 非抢占式多任务&#xff08;cooperati…

【云原生】Kubernetes(k8s)部署 MySQL+Dubbo+Nacos服务

一、说明二、部署 MySQL三、部署 Nacos四、部署 Dubbo 服务4.1. 创建镜像仓库的密钥4.2. 部署 provider 服务4.3. 部署 consumer 服务五、测试一、说明 本文介绍基于 Kubernetes(k8s) 环境集成阿里云 私有镜像仓库 来部署一套 Dubbo Nacos 的微服务系统&#xff0c;并使用 Ku…

7个最好的PDF编辑器,帮你像编辑Word一样编辑PDF

PDF 是具有数字思维的组织的重要交流工具。提供高效的工作流程和更好的安全性&#xff0c;可以创建重要文档并与客户、同事和员工共享。文档的布局已锁定&#xff0c;因此无论在什么设备上查看&#xff0c;格式都保持不变。这是让每个人保持一致的好方法——尤其是那些使用Micr…

C++中的引用

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【C】 接下来就要开始进行C的学习路线了&#xff0c;听说这块的内容稍微难一些&#xff0c;不过我相信只要自己好好学习&#xff0c;态度…

java与Spring的循环依赖

java与Spring的循环依赖一、循环依赖是什么有什么危害二、循环依赖在Spring中的体现和类型三、Spirng如何解决循环依赖四、总结一、循环依赖是什么有什么危害 什么是循环依赖 java中循环依赖用一张图来说就是下图&#xff1a;在对象的创建过程中多个对象形成了依赖闭环&#xf…

初识linux之管道

一、进程间通信的概念大家都知道&#xff0c;进程是具有独立性的&#xff0c;因为一个程序运行起来生成进程时&#xff0c;也会生成它的进程结构体&#xff0c;即PCB&#xff0c;然后然后通过进程结构体中的结构体指针找到它的虚拟地址空间&#xff0c;然后再通过它的页表映射到…

C语言——字符函数和字符串函数【详解】(一)

文章目录函数介绍1.strlen2.strcpy3. strcat4. strcmp5. strncpy6. strncat7. strncmp8. strstr函数介绍 求字符串长度 strlen 长度不受限制的字符串函数&#xff08;使用时不安全&#xff09; strcpy strcat strcmp 长度受限制的字符串函数介绍&#xff08;与长度不受限制函数…

【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(9)

目录 写在前面&#xff1a; 题目&#xff1a;P1025 [NOIP2001 提高组] 数的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 解题思路&#xff1a; 代…

【数据结构】哈希表

目录 1、哈希表 1.1 哈希表的简介 1.2 降低哈希冲突率 1.3 解决哈希冲突 1.3.1 闭散列 1.3.2 开散列&#xff08;哈希桶&#xff09; 1、哈希表 1.1 哈希表的简介 假设我们目前有一组数据&#xff0c;我们要从这组数据中找到指定的 key 值&#xff0c;那么咱们目…