进程的概念

一.进程和程序的理解

首先抛出结论:进程是动态的,暂时存在于内存中,进程是程序的一次执行,而进程总是对应至少一个特定的程序。

程序是静态的,永久的存在于磁盘中

程序是什么呢?程序其实就是存放在我们磁盘上的可执行程序,它静态的,而且是永久存在的。

image-20240705150158608

进程就是磁盘上的程序,加载拷贝到内存上运行起来的,这就是进程。

image-20240705151023097

在windows上打开任务管理器,我们就可以看到操作系统中运行的所有的进程。

image-20240705150530296

这里存在着很多进程,这么多进程,操作系统要不要将这些进程给管理起来呢?答案是肯定的。那又要如何管理呢?这就引出了之前说的冯诺依曼体系结构中的,先描述,再组织

那要怎么将这些进程描述好,组织好呢?首先操作系统是C语言写的,C语言中描述一个物体的很多属性,都是通过结构体struct概括起来的。而描述进程的这个结构体的全部叫做:PCB。

二.进程的PCB

进程的PCB全称叫做进程控制块(process control block),PCB中部分内容如下:

struct xxxx
{
    //id(也就是pid)
    //代码数据地址
    //优先级
    //程序计数器(pc)
    //struct PCB*next
}

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

进程的运作:

在这里插入图片描述

所以说:进程=可执行程序+内核数据结构(PCB)。

在Linux中,进程的PCB具体是struct task_struct{}

其中可执行程序已经被描述成了PCB,然后操作系统需要将PCB给组织起来,使用链表进行链接,于是对于进程的管理就成了对链表的增删改查。

这里的链表又和之前学习的双向头尾链表有点不同。

struct task_struct//PCB
{
    //各种属性
    struct dlist list;
}
struct dlist//链表
{
    struct dlist*prev;
    struct dlist*next;
}

PCB中有一个结构体对象list,然后该结构体中有prev和next指针将操作系统中PCB给组织起来。

image-20240705162447957

这里不要认为进程的PCB只能存在链表中,操作系统中存在许多组织进程PCB的列表,像运行队列,阻塞队列等等。

后续细说。

三.task_struct中的pid和ppid

1.pid

task_struct中有很多属性,也就是很多字段,那它的核心字段有哪些呢?-贯彻整个的学习的过程。

这里我要说到一个核心字段pid(process id),也就是标识该进程的一个数字,表明它是独一无二的一个进程。

这里我们写一个小小的代码来看看进程的pid。

①test.c文件中,写一个死循环的程序。

#include<stdio.h>                                                                                #include<unistd.h>
int main()
{
     while(1)
     {
        printf("这是一个进程\n");
        sleep(1);
     }
 return 0;
 }

②makefile自动化构建代码。

mycode:test.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f mycode     

然后我们使用make创建出可执行程序,然后执行该可执行程序,于是该可执行程序就变成了进程。

image-20240705182716557

这里鼠标右键,点击复制SSH渠道,为了方便我们观察进程的运行和进程的pid的变化。

使用脚本查看该进程的pid:ps ajx | head -1 && ps ajx | grep mycode

image-20240705183213406

该进程我们写的死循环,它就在一直运行起来的,每次我们使用这个这个脚本查看进程,可以看出mycode进程的pid一直没变过,因为该进程一直在运行。而每次使用该脚本,我们都会使用grep这个程序,一瞬间,grep进程就运行起来并马上死亡,于是看到每次grep,它的pid都会发生变化。

在左边进程一直在运行,可以使用ctrl+c,终止该进程,再使用该脚本查看,就发现该进程pid就看不到了。

还可以使用这个命令来杀死进程:kill -9 进程的pid(无脑杀死进程,后续说的僵尸进程没有办法杀死)

image-20240705183936835

2.ppid

这里可以看到除了进程的pid之外,进程还有ppid,而且ppid的值一直没有变过。

解释:进程中除了自己的pid之外,还有父进程的pid,父进程的pid,在子进程来看就是自己的ppid。

那这个父进程到底是谁呢?父进程其实是bash,也就是我们的命令行解释器。

bash是一直不变的,我们在bash下创建的进程,都是bash的子进程。

马上我们使用函数getpid()和getpppid()就验证了。

四.系统调用接口getpid()和getppid()

上述中,我们使用脚本来查看一个进程的pid,每次都这样子来查看进程的pid就很麻烦,于是有两个系统调用接口就可以直接查看进程的pid和ppid,现在我们直接演示。

注意系统调用接口函数在man 2号手册里面查找,而各种库函数都是在man 3号手册中查找的。

image-20240705190657300

修改源代码:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
    while(1)
    {
        printf("这是一个进程,pid:%d,ppid:%d\n",getpid(),getppid());
        sleep(1);
    }                                                                                       return 0;
} 

image-20240705192328849

这里即验证成功,该进程的ppid和bash进程的pid是对应上的,故而说明,在bash下创建出来的进程都是bash的子进程。

五./proc/pid目录和PCB的关系

linux中有一个目录proc,它存放着所有的进程。

image-20240705200132515

其中proc/pid目录存放着具体某个进程的一些信息。目录的名称就是以该进程的pid命名的。

image-20240705200930739

当我们将进程启动起来,使用ls /proc/pid命令就可以查看该进程的一些信息。

其中cwd就是该进程的当前工作目录,而exe就是可执行程序,还有很多信息。


image-20240705201301015

当ctrl+c终止掉进程之后,再使用查看同样的目录,该目录就不存在了,由此可以看出,/proc目录结构是动态的


当进程运行起来的时候,我们使用命令make clean将可执行程序删除了(也就是在磁盘上删除了该可执行文件),但是进程此时并不受影响,因为进程已经在内存中运行起的。

然后使用命令查看该进程的信息,可以看到该进程是知道自己的可执行程序是被删除了的。

于是得出一个结论:进程是可以找到自己的可执行程序的,靠的就是cwd这个链接文件。

image-20240705201808927


在/proc/pid下我们可以看到具体某个进程的信息,那么它和进程的PCB的关系是什么呢?

/proc/pid 目录下的内容是操作系统向用户展示的关于进程的一部分信息,它与进程控制块(PCB)有一定的关联。

/proc/pid 中的信息可以被看作是从 PCB 中提取出来的、以可读形式呈现给用户的部分关键数据。这些数据反映了进程的某些状态和特征,是 PCB 中部分重要信息的外在表现。

③例如,/proc/pid/status 文件中的一些字段可能与 PCB 中记录的进程状态信息相对应;/proc/pid/maps 可能与 PCB 中关于进程内存布局的信息相关。

然而,/proc/pid 并不能涵盖 PCB 中的所有详细和底层的控制信息,只是提供了一个便于用户观察和了解进程基本情况的接口。

六.Linux中创建进程的两种方式

1.手动的创建进程

上述的所有过程我们都是手动的创建出进程。

除了手动的创建出进程,我们还可以使用代码来创建出进程。

2.使用代码进行创建

使用函数fork()来创建出子进程。(后续细说)

相关推荐

  1. 进程概念介绍

    2024-07-10 16:16:01       42 阅读
  2. Linux进程基本概念

    2024-07-10 16:16:01       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 16:16:01       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 16:16:01       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 16:16:01       57 阅读
  4. Python语言-面向对象

    2024-07-10 16:16:01       68 阅读

热门阅读

  1. liunx上修改Firefox版本号

    2024-07-10 16:16:01       20 阅读
  2. PS设计新手如何学习?沈阳PS设计线下培训

    2024-07-10 16:16:01       22 阅读
  3. 深度学习进阶

    2024-07-10 16:16:01       20 阅读
  4. 提示学习的本质是KNN

    2024-07-10 16:16:01       22 阅读
  5. Tomcat

    Tomcat

    2024-07-10 16:16:01      19 阅读
  6. pytorch 源码阅读(1)——torch.complie

    2024-07-10 16:16:01       20 阅读
  7. weapp.socket.io.js

    2024-07-10 16:16:01       15 阅读
  8. 内网和外网的区别及应用

    2024-07-10 16:16:01       24 阅读
  9. Symfony Monorepo:一站式开发的艺术与实践

    2024-07-10 16:16:01       23 阅读
  10. Docker 深度分析与选型指南

    2024-07-10 16:16:01       28 阅读
  11. 深度学习 - 模型剪枝技术详解

    2024-07-10 16:16:01       22 阅读
  12. 基于单片机的火灾自动报警器研究

    2024-07-10 16:16:01       24 阅读
  13. linux从入门到精通

    2024-07-10 16:16:01       21 阅读