首页 > 系统相关 >【Linux】进程的概念

【Linux】进程的概念

时间:2024-09-02 19:51:20浏览次数:13  
标签:grep 代码 pid 概念 Linux 进程 PCB 运行

【Linux】进程的概念

文章目录

基本概念

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

直接看上面的基本概念显得很抽象,那我们就先不管它。先来粗略地看看在windows系统下的进程:

在这里插入图片描述

通过任务管理器,我们可以看到一个个正在运行的程序,这就代表了一个个进程。 我们可以直观地感受到:在操作系统中,进程可以同时存在很多个

描述进程-PCB


既然操作系统中可以有很多进程,那操作系统就要将这些进程管理起来,操作系统是如何管理进程的呢?

先描述,再组织。想了解如何管理进程,我们就要先将它描述出来

我们先来写一个简单程序,然后将其编译为可执行程序myprocess

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

int main()  
{  
	while(1)  
	{
        sleep(1);
		printf("I am a process!\n");                                 
	}                
	return 0;           
}              

在这里插入图片描述

当我们的程序被CPU调度运行时,就是一个进程了

在这里插入图片描述

当程序没有运行时,它是存储在磁盘中的

在这里插入图片描述

根据冯诺依曼体系规定,我们要运行程序,必须将其加载到内存中,也就是要将程序对应的代码与数据拷贝到内存中

在这里插入图片描述

那么像上图这样的模型,将代码与数据加载到内存中就是一个进程了吗?

我们知道,内存中可以存在多个进程,哪个进程该调度,调度多长时间,下一个进程又是谁,这些问题似乎仅凭上图的模型无法解决,这里我们就要引入一个数据结构——PCB(Process Control Block)进程控制块

PCB中存放着进程的信息,可以理解为进程属性的集合

它的具体实现是怎么样的,我们现在先不去深究,只需了解以下即可

struct PCB
{
	// ...所有属性
	struct PCB* next // 指向下一个进程的PCB
	// 内存指针, 指向对应的代码与数据
}

每一个进程都必须对应一个PCB

在这里插入图片描述

这样我们就可以粗略的认识,进程 = PCB + 对应的代码与数据

有了PCB,操作系统对进程的管理,就变为了对PCB链表的增删查改,当然也不一定是链表,也可能是其他的数据结构

PCB是在操作系统学科里的一个统称,在Linux中,PCB具体叫法是struct task_struct,是一种内核数据结构

task_ struct内容分类

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

PCB的意义


通过以上,我们了解了什么是PCB,下面我们来看看它的意义或者作用

我们知道,操作系统也属于软件,在开机时就被加载到了内存中

在这里插入图片描述

而程序运行时,进程 = 内核task_struct结构体 + 程序的代码与数据,都会被加载到内存

在这里插入图片描述

操作系统对进程进行调度时,就是调度进程对应的task_struct,会有一个task_queue或者其他数据结构,让不同进程的task_struct进行排队

在这里插入图片描述

所以,调度运行进程,本质就是让进程控制块task_struct进行排队

有了PCB,操作系统就可以对进程进行管理

进程标识符


到这里,我们知道,运行一个可执行程序,就是让系统创建进程并运行。

无论是我们写的代码形成的可执行文件,还是系统的指令(lspwd等)操作,本质都是运行进程

当进程运行起来时,我们可以使用如下指令查看进程运行的情况

ps axj

ps是查看进程的指令,axj是选项,选项可以乱序

在这里插入图片描述

直接使用,显示出来的数据很乱,通常要配合管道grep来查看特定进程

ps axj | grep 进程名

下面运行之前的myprocess,然后使用ps指令查看此进程

在这里插入图片描述

可以看到,查到了我们想要的进程状态,但是我们并不知道这些数据代表什么,我们可以将ps axj的前一行取出来,对应了各个数据的名称

ps axj | head -1

而且下面还有一行grep进程,这是因为grep运行时也会创建进程,我们可以将这一行过滤掉,grep -v grep是反向过滤,将含grep的数据过滤掉

ps axj | grep myprocess | grep -v grep

同时运行上面两条指令,可以这样

ps axj | head -1 && ps axj | grep myprocess | grep -v grep

这时我们再来看进程运行情况

在这里插入图片描述

先来看PID这一项,为了区分不同进程,每个进程都有唯一标识符,就是PID

getpid

除了使用ps axj指令,还可以怎样查看进程对应的PID呢?——进程可以自己查看自己的PID

我们要明确一点,进程是运行起来的程序,程序是我们写的,我们代表了用户。而PID是操作系统内核的数据,用户是不可以直接访问操作系统内部的,但是操作系统为用户提供了系统调用。因此,我们可以在程序中使用系统调用来查看进程的PID

这个系统调用是getpid,头文件是<unistd.h><sys/types.h>,返回类型是pid_t无符号整型

下面我们直接使用

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

int main()
{
	pid_t pid = getpid();
	while(1)
	{
        sleep(1);
		printf("I am a process, pid:%d\n", pid);
	}
	return 0;
}

将编译后的程序运行起来:

在这里插入图片描述

通过getpid得到的pid和我们使用ps命令得到的pid是一致的

由于我们写的程序是个死循环,要想停止只能按CTRL+C,而这里有了进程的pid后,可以使用kill指令停止进程

kill -9 进程的pid

在这里插入图片描述

进程的创建


除了直接运行可执行程序,我们还可以在代码中创建进程

进程创建的代码方式

首先,我们要知道,一个进程是由其父进程创建的

使用系统调用getppid可以获得当前进程的父进程的pid,先来使用一下看看

在这里插入图片描述

运行程序:

在这里插入图片描述

确实获得了一个ppid,多运行几次程序

在这里插入图片描述

我们发现,pid每次都会改变,而它父进程对应的ppid是不变的。这很容易理解,我们每次运行一个程序,都是重新创建一个新的进程,pid肯定会不同,而它的父进程ppid不变,说明父进程一直在运行着

我们使用ps指令和查看一下父进程

在这里插入图片描述

可以看到,父进程是bash命令行解释器,说明我们运行的程序的进程是由父进程bash创建的子进程


知道了进程是由父进程创建后,我们该怎么在代码中创建进程呢?

用户不能直接访问操作系统内核,我们想在代码中创建一个进程,只能使用系统调用

pid_t fork()

先不谈它的返回值,直接使用来看看

在这里插入图片描述

这里先来暂时输出一个结论:fork之后,父子进程代码共享。即fork之后,会输出两条I am a process,一个是父进程输出的,另一个是子进程输出的

在这里插入图片描述

我们知道,父进程是myprocess,它的代码与数据来源于磁盘;它创建子进程,子进程的代码与数据来源于哪里?这里我们暂时理解为子进程继承了父进程的代码与数据

为什么要创建子进程


父进程与子进程运行不同的代码,可以提高工作效率

父子进程代码是共享的,如何运行不同的代码呢?这就要返回去看fork的返回值了

fork的返回值:

在这里插入图片描述

创建子进程成功,子进程的pid被返回给父进程,返回0给子进程;创建失败,返回-1给父进程

我们根据fork的返回值,来写一份代码:

在这里插入图片描述

运行结果:

在这里插入图片描述

可以看到因为fork的返回值不同,父子进程也执行了不同的代码

回头看代码有两个问题:

  1. 为什么fork函数可以返回同时两个值
  2. 为什么id可以同时等于0和子进程的pid

解答

  1. fork函数在执行的时候,子进程就创建了。在fork函数执行结束,返回值时,同时有父子两进程,同时有两个fork函数,所以可以返回两个值
  2. 进程具有独立性,父子进程的数据互不影响。可以非常粗略地认为,父进程和子进程有自己变量id,是各自私有的,只是都叫id而已。后面虚拟地址空间、写时拷贝会解开这个问题的答案

以文件的形式查看进程


每一个进程运行时,都会在/proc目录下生成对应的文件

在这里插入图片描述

写一个简单的程序,在proc中查看它的进程文件

在这里插入图片描述

运行起来:

在这里插入图片描述

可以看到,确实生成了对应进程的目录

看看里面的详细信息:

在这里插入图片描述

很明显地可以看到cwdexe

  • cwd(current work dir)代表了当前进程当前的工作路径
  • exe记录了进程对应的可执行程序的路径

结束,再见

标签:grep,代码,pid,概念,Linux,进程,PCB,运行
From: https://blog.csdn.net/2301_77578940/article/details/141828106

相关文章

  • Linux需要掌握哪些知识才能找工作?
    众所周知,Linux是一门非常值得学习的技术,从服务器到移动设备、从嵌入式系统到超级计算机,都离不开Linux的身影,而且掌握它之后不仅发展前景好,还可以获得一份收入不错的工作,但前提条件是掌握相关技能,那么Linux运维学到什么程度可以找工作?以下是具体内容介绍。简单来讲,Linux运......
  • Linux运维需要掌握哪些技能?
    想要成为一名合格且优秀的Linux运维工程师,其不仅需要掌握各种各样的技能,还需要具备良好的学习能力、沟通能力、表达能力等,这样才能更好地胜任岗位要求,那么Linux运维工程师需要掌握哪些技能?以下是具体内容介绍。Linux运维工程师需要掌握的技能有很多,其中包括Linux基础、系......
  • 【Linux】08.Linux 下的第一个小程序——进度条
    一、知识引入在写我们的进度条之前需要先引入一下小的知识点:换行与回车,认识缓冲区,认识格式化输出1.1换行与回车换行指的是跳转到下一行的同一个位置回车指的是跳转到本行开头的位置新起一行就是换行+回车但是日常生活中我们见到的换行一般都是使用Enter(回车键)进行......
  • 【Linux修行路】实现一个简单的日志代码
    目录⛳️推荐一、可变参数的使用二、Log2.1日志打印2.1.1时间获取2.1.2日志分块打印2.2打印模式选择2.3Log使用样例2.4Log完整源码⛳️推荐前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站【Linux修行路】动......
  • linux shell grep命令单字匹配
    grep.sh#!/bin/bashE_BADARGS=65if[-z"$1"];thenecho"Usage:`basename$0`pattern"exit$E_BADARGSfiechoforfilein*dooutput=$(sed-n/"$1"/p$file)if[!-z"$output"];thenecho-n"......
  • Linux目录结构基础和Linux核心命令
     前言 想要了解Linux系统,我们先从它的目录结构部分说起。一、Linux目录概述Linux的目录是什么,类似于windows中的文件夹,但是它是以根目录为起始向下延伸,它的表示形式为'/'。 1.1.Linux的核心目录(根下)   根下的核心目录说明/etc/系统服务的配置文件,主要存放一些......
  • linux定时重启jar包项目
    1、创建.sh文件touchgtws.sh//创建文件vitouchgtws.sh //编辑文件#!/bin/bash#停止现有程序pkill-fdp-upload.jar#等待三秒时间sleep3#重启项目包nohupjava-jardp-upload.jar>dp-upload.log&#输出提示信息echo"定时任务重启成功"exit注意......
  • 2.Linux编程-库
    命名(习惯):静态库:.lib/.a动态库.dll/.so静态库的命名一般分为三个部分:前缀:lib库名称:自定义即可,如test后缀:.a共享库的命名一般分为三个部分:前缀:lib库名称:自己定义即可,如test后缀:.so库制作完成后,如何给用户使用头文件—包含了库函数的声明库文件—包含了库函数的代......
  • 【树莓派开发】使用树莓派在Linux环境下编写C语言代码
    文章目录前言1.创建test.c文件2.编译运行该文件3.编译并链接两个源文件结语前言如何使用树莓派编译C语言代码呢?21年暑假的时候,学习编程的劲头高涨,然后冲动消费买了个树莓派4B……结果压根不会用,吃灰了半年不过现在已经学完了C语言,也接触了一丢丢Linux系统下的gcc指令,可以尝试用它......
  • linux PS1
    最近不小心动了环境变量的PS1老是感觉很奇怪然后研究了一下PS1可以支持以下这些选项:\d:显示曰期,格式为"星期月日"。\H:显示完整的主机名。如默认主机名"localhost.localdomain"。\h:显示简写的主机名。如默认主机名"localhost"。\t:显示24小时制时间,格式为"HH:MM:SS"。......