【Linux】进程的概念及操作进程

这篇具有很好参考价值的文章主要介绍了【Linux】进程的概念及操作进程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.什么是进程

背景:

我们通过冯诺依曼体系结构知道,程序需要运行,需要将其从磁盘中传入内存,在传入CPU,由CPU将其运行起来。

了解了这个背景,我们就能对进程得出下面的理解:

  • 进程 就是被加载到内存中的程序,或者被运行起来的程序就叫做进程

这也是很多教材上的说法,但它并不完全正确,甚至有些片面。

linux中进程基本操作,Linux,linux,服务器,运维

如上图,我们的计算机在运行后不论是我们自己打开的软件还是后台应用的程序,数量是很多的,如果这些程序就这样赤裸裸的交由操作系统来管理,会增加操作系统的负担,所以操作系统需要对每一个程序做整理,将其打包成一个对象,更抽象的讲,将其变成一个变量,操作系统只对这些变量进行管理,就会变得容易。

比如说,在学校中,每个学生都有自己的信息,如姓名、年龄、性别、各科成绩等等,这里的学生就是操作系统中的程序,想要对其进行管理,我们可以将学生的属性,如姓名、年龄等放入结构体中,在通过结构体创建对应的对象,管理这些对象即可,这样我们也就得出了进程的概念。

我们编写的程序通过编译、链接后生成一个可执行程序,该程序本质是一个文件,放在磁盘。在Windows中双击运行,在Linux中使用./运行,使其加载到内存。

在进程加载进内存后,操作系统要对其进行管理,也就是对程序的数据进行管理,从这些程序中抽象出所有的属性来构建一个结构体,然后将每一个进程都创建成一个结构体对象,最后再将所有的结构体对象使用某一种 高效的数据结构(在Linux中使用双链表 组织起来;

而想要获取每个进程中对应的代码时,根据结构体对象调用在内存中的对应的代码即可;

以此将所有的应用程序都已进程的方式运行,而每个进程都有自己独立的地址空间,使进程之间的地址相互隔离。CPU由操作系统同一进行分配,每个进程根据进程优先级的高低都会有机会得到CPU。

所以我们说,进程只是正在运行或将要运行的程序是不正确的,它的理解应当如下:

进程 = 内核关于进程的相关数据结构 + 进程对应内存上的代码和数据

其中,在操作系统中,用来描述和组织进程数据结构(抽象的可以看作结构体),被称为 进程控制块-PCB

2.描述进程 - PCB

从上面的知识中我们知道,单一的进程是由一个特定的结构体来描述出的,该结构体(数据结构)就是进程控制块,可以理解为进程属性的集合。

课本上将进程控制块称之为PCB(process control block),而不同的操作系统,PCB的名称不同,在Linux操作系统下的PCB是:task_struct

linux中进程基本操作,Linux,linux,服务器,运维

也就是说,每一个进程被加载到内存后,Linux操作系统都会对其创建task_struct对象,并将其与加载到内存的代码和数据产生关联,然后将所有的task_struct使用指针连接成一个双链表(此时该进程即为操作系统内被管理的进程),这样对进程的管理就是对链表的增删查改。(此为简易路线,剩余内容之后会讲)

PCB是用来描述进程的,在C++中我们使用类来描述一个事务,在C语言中我们使用结构体描述,而Linux是用C语言编写的,所以Linux当作描述进程的进程控制块就是结构体task_struct实现的。

  • task_struct是Linux内核的一种数据结构,被装再到内存(RAM)里,并且包含进程的信息。

了解了这些再来看一下在Linux中,task_struct包含的程序的各种属性内容,如下:

task_struct内容分类

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

抽象出来,可以用如下结构体来表示(以LInux为例)

struct task_struct{
    //进程的所有属性
    ....
    //进程对应的代码和数据的地址
    ....
    //下一个进程的地址
    struct task_struct* next;
}

关于进程的进程控制块PCB的task_struct结构体的具体描述可以参考这篇博客Linux中进程控制块PCB-------task_struct结构体结构

了解了这些,我们也就能更具体的感受进程的概念:

进程 = 内核关于进程的相关数据结构 + 进程对应内存上的代码和数据

总结:

  1. PCB是什么

    它就是一个struct结构体,这个结构体中包含着进程大部分的属性

  2. 为什么进程管理中要使用PCB?

    为了管理进程

3.进程的具体操作

知道了进程是什么,我们接下来就来看一下,在LInux下进程的具体操作。

3.1进程的属性与文件属性的关系

我们知道在磁盘中的文件 = 内容 + 属性。

那一个文件,在磁盘当中向内存加载,加载的是这个文件的内容还是属性呢?

答:内容

我们知道,每一个进程都有自己的属性集合叫PCB,那在磁盘中文件的属性和进程的属性有关系吗?

答:有关系,但是关系不大

比如说,在磁盘中,文件的属性一般包含着文件的权限、拥有者、所属组、什么时间创建修改和文件名是什么等等,这些判断用户是否有权限去操作文件和文件的一些基本信息,

而PCB结构体是一种内核数据结构,是由操作系统去创建动态维护的,和磁盘里的属性没有关系,它是重起炉灶,另搭台。就是说,进程里的属性是由操作系统根据获取的代码和数据自己去创建和维护的,和磁盘中的文件属性不同。

例如,进程的pid(process id,进程的id号),这个是文件没有的,而如果操作系统想要知道某个进程对应的文件名或文件的体积大小,它也是可以知道的,所以我们说它们有关系,但关系不大。

3.2查看进程

准备工作

  • 使用到vim、gcc、makefile,若是不熟悉,点击名称查看对应博客即可

我们在Linux中新建文件myprocess.c,编写如下代码

linux中进程基本操作,Linux,linux,服务器,运维

代码功能:我们知道当程序是以进程的模式在硬件中运行,在执行该程序后,陷入死循环,一直输出“hello process”,此时该程序对应的进程一定是存在的我们可以查看到。

所以我们可以得出如下结论:

结论:

  1. 在Windows系统中,通过双击或打开一个程序,程序就会以进程的方式运行。
  2. 在Linux系统中,执行可执行程序(./)后即为将程序变为进程的形式

下图为makefile文件代码:

linux中进程基本操作,Linux,linux,服务器,运维

上图表示,我们编写代码的myprocess.c文件生成的对应可执行文件名为MyProcess,下面会直接使用MyProcess可执行文件执行运行该程序

小技巧

因为只有程序运行,才能保证进程的存在,所以我们要在程序运行的情况下,观察对应进程信息,这时我们就需要使用多个页面配合的方式,我使用的是Xshell,如果大家和我使用的相同可以使用如下方法创建多页面。

  1. 右击当前会话框,找到复制会话

    linux中进程基本操作,Linux,linux,服务器,运维

  2. 复制出的会话与当前会话相同,处在同一文件,共用同一操作系统,一边的发生改变影响另一边

  3. 将复制好的进程拖至合适位置

    linux中进程基本操作,Linux,linux,服务器,运维

    • 复制会话,即为创建了一个新的bash进程,并且与原来的bash进程共用同一操作系统(后面会讲)
  4. 可使用该方法产生复制多个会话,一次运行多个程序,在查看进程

使用指令查找对应进程:

使用ps axj | head -1 && ps axj | grep 可执行文件名 | grep -v grep指令查找。

注意: 按具体需求使用该指令

linux中进程基本操作,Linux,linux,服务器,运维

解释:

指令:ps axj为查看当前执行的所有进程,

linux中进程基本操作,Linux,linux,服务器,运维

|:管道符,表示将前面执行的结果传到后面,执行后面的指令

指令:head -1取所有ps axj所有显示的第一行,也就是上面动图,最后使用白色部分选择的那行,给出每列名称,该指令具体内容查看该篇博客–常见指令

linux中进程基本操作,Linux,linux,服务器,运维

主要包含以下这几个名称:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND

这里介绍两个本文要用的,剩余的不做研究

  • PID:process ID ,进程的编号
  • PPID:父进程编号,即对应PID的父进程编号

&&:逻辑或,将两端指令的结果结合,输出到屏幕

指令:grep 可执行文件名 ,grep指令用于查找对应字符串,并输出字符串所在行,该指令具体内容,可查看该篇博客–常见指令

linux中进程基本操作,Linux,linux,服务器,运维

在上面的一张动图中,最终显示的结果如下

linux中进程基本操作,Linux,linux,服务器,运维

其中打印出的第二行是我们不需要的,可以使用最后一个指令使其不在打印

指令:grep -v grep,-v选项,表示不显示后面字符串(grep)所在行,具体内容,可查看该篇博客–常见指令

linux中进程基本操作,Linux,linux,服务器,运维

在文件中查看进程

/proc文件中查看(该方式比较冷门)

linux中进程基本操作,Linux,linux,服务器,运维

  • 数字对应的是对应进程的PID

举例:

我们先执行MyProcess文件,在使用上面的指令查找对应的进程,找到该进程的PID,根据PID在/proc中查看对应文件,如下:

linux中进程基本操作,Linux,linux,服务器,运维

具体如下(上面得进程不小心关闭了,重新打开了一个)

linux中进程基本操作,Linux,linux,服务器,运维

当我们查看该PID对应文件的具体信息,会看到如下情况:

linux中进程基本操作,Linux,linux,服务器,运维

表明该进程对应的程序的位置。

3.3关闭进程

ctrl+c

如下图,在当我们打开一个程序,并处于运行状态,我们可以使用热键ctrl + c结束该程序(结束该进程)

linux中进程基本操作,Linux,linux,服务器,运维

kill

我们也可以使用kill指令加-9选项后根进程PID结束目标进程,如下

kill -9 PID

linux中进程基本操作,Linux,linux,服务器,运维

3.4进程的一些特性

  1. 一个程序可以同时形成多个进程

    如下,我们对同一可执行文件执行两次,并查看进程

    linux中进程基本操作,Linux,linux,服务器,运维

  2. 随着进程创建的先后顺序不同,它的PID是变化的

    如下,我们打开关闭同一可执行文件,并查看对应进程PID的变化

    linux中进程基本操作,Linux,linux,服务器,运维

    如上图红色的框,表示每次运行该程序后,进程PID的变化,它是变化的,因为每次都需要重新将程序已进程得形式执行,不可能每次都使用相同得PID

  3. 一个程序它创建多次,虽然每次PID不同,但PPID(父进程)相同

    如上图,虽然每次进程的PID不同,但它们的父进程PPID是相同的,再Linux中该父进程为bash

  4. Linux中进程的父进程都是bash(有特殊情况,但毕竟是特殊情况)

    每一次我们开机,都会启动操作系统,那就需要命令行解释器来帮我们做解释命令,所以,bash命令行解释器也是一个进程,它有独立的PID。命令行启动后的所有程序,最后都会变成进程,而该进程对应的父进程就是bash。

    在该篇博客shell及其运行原理中提到过,shell为了保护自己,创建子进程来执行用户的指令。

    如下,我们在/proc文件中根据上图父进程的PID查看对应的信息,是否为bash

    linux中进程基本操作,Linux,linux,服务器,运维

    注意: 我们的指令(如:ls、touch等),是由C语言编写,./后也会形成进程。

  5. 一个进程结束后,它对应的进程PID文件也会被删除无法打开

    1. 我们在进程结束后,尝试打开对应进程PID文件

      linux中进程基本操作,Linux,linux,服务器,运维

      如上图,打不开文件,并且在/proc文件中找不到对应的文件

    2. 先打开进程PID文件,后结束进程,观察结束后该文件的变化

      linux中进程基本操作,Linux,linux,服务器,运维

  6. 我们知道bash也是进程,它是所有进程的父进程,当我们关闭该进程后,相对应的对话就无法使用,需重新创建,如下,我们使用kill指令关闭该进程(不同的系统下展现情况不同但意义相同)

    linux中进程基本操作,Linux,linux,服务器,运维

    上图我们创建了两个会话,虽然共用同一Linux操作系统,但对应得bash进程不同,我们查看的是右边会话对应得进程,所以它的父进程即为右边得bash,关闭后不会影响左边得会话。

3.5通过系统调用获取进程标识符

系统调用: 计算机是由用户层、操作系统、驱动、硬件等等组成,它们每一层使用接口与相邻层连接,而操作系统给出的供上层开发使用的接口统称为系统调用。(具体看该篇博客–操作系统)

当我们想在程序运行的时候显示它对应的进程PID和PPID,就需要使用系统调用。

我们使用系统调用接口getpid()getppid()来获取进程PID和PPID,这里我们可以通过man手册来查看这两个函数(按q退出)

man getpid

linux中进程基本操作,Linux,linux,服务器,运维

注意: 函数的返回值pid_t,将其当作int即可,在打印时,使用%d

我们在将myprocess.c文件中的代码做如下修改

linux中进程基本操作,Linux,linux,服务器,运维

运行该程序后,查看对应的PID和PPID值是否正确

linux中进程基本操作,Linux,linux,服务器,运维

3.6通过系统调用创建子进程

通过上面的学习我们知道,Linux操作系统通过父进程bash来创建子进程,那父进程是如何来创建子进程的?如何在代码层面直接创建新的子进程呢?这就要学习第三个系统调用接口fork().

可通过man查看fork的信息

man fork

linux中进程基本操作,Linux,linux,服务器,运维

下面让我们使用fork()看一下结果

首先,我们先将myprocess.c的程序做如下修改:

linux中进程基本操作,Linux,linux,服务器,运维

运行后的结果如下:

linux中进程基本操作,Linux,linux,服务器,运维

如上图运行结果,形成两个进程,父进程的PID为10130,子进程的PID为10131(23286为该会话的bash进程PID)

最开始打印父进程的字符串"AAA",fork后打印了父进程的字符串“BBB”,最后打印子进程的字符串“BBB”。

linux中进程基本操作,Linux,linux,服务器,运维

这是因为在fork后执行流会变成两个执行流,变为两个进程,这两个进程共享fork后的代码,而且并不是必须要先运行父进程后运行子进程,这个根据服务器的不同,结果不同。

整个调用链为:当我们运行该程序时,产生了子进程,而该程序内通过fork又创建了它自己的子进程。

总结: 对于父子进程,子进程是再父进程的基础上创建。

那么问题就来了,操作系统如何知道那个是父进程,那个是子进程的?

答:通过fork的返回值。

让我们在来使用man指令查看fork,并找到它关于返回值的内容,如下:

linux中进程基本操作,Linux,linux,服务器,运维

若进程创建成功,将子进程的PID返回给父进程,将0返回给子进程,若失败将-1返回给父进程,没有子进程创建,显示errno

注意:返回值类型为pid_t

我们通过下面修改的代码和修改后的运行结果理解上面的内容

linux中进程基本操作,Linux,linux,服务器,运维
linux中进程基本操作,Linux,linux,服务器,运维

如上图,fork给父进程返回的是子进程的PID17881,给子进程返回的是0,以此来区分父子进程。

想必这里大家就会有疑问,为什么一个变量会接收到两个返回值?为什么同一个地址却有不同的值?第一个问题我们下面会讲到,第二个设计到进程地址空间,本文为进程的概念,第二个问题在之后的博客会讲到。

了解了这些知识和现象,我们在来看一下一般我们使用fork的方式,将代码修改如下:

linux中进程基本操作,Linux,linux,服务器,运维 运行的结果如下:

linux中进程基本操作,Linux,linux,服务器,运维

还是一个变量,有两个值,导致该程序即执行了if又执行了else if。这也是fork如何两个返回值的问题?

接下来我们按步骤解答这个问题:

  1. fork做了什么?

    答:创建了子进程。

    我们知道一个进程 = 内核关于进程的相关数据结构 + 进程对应的磁盘代码和数据

    像上面这段程序,运行后先创建了一个进程它有自己对应的代码和数据,在fork后,它创建了自己的子进程,而子进程对应的仍然是父进程的代码和数据,

    linux中进程基本操作,Linux,linux,服务器,运维

  2. fork创建子进程后,父子进程是否影响着彼此?

    这里先要说一个概念:进程在运行的时候,是具有独立性的!

    比如说,我们在Windows系统下,打开QQ、微信、爱奇艺等待软件,在关闭QQ对其他的软件是没有影响的。

    而上面的程序是父子进程,运行的时候也是一样的,我们运行上面的程序,然后关闭父进程,查看子进程是否可以运行

    linux中进程基本操作,Linux,linux,服务器,运维

    如上图,父进程关闭后,子进程还可以正常运行,其中子进程的PPID变为1,子进程变为孤儿进程(孤儿进程此处作为了解,需在使用kill关闭子进程)

  3. fork如何看待代码和数据?

    首先,我们编写的代码在运行后不会被改变,例如,某行使用的是if,运行后被改为while,这是不会的。

    其次,运行程序后,在修改数据时,是将数据拷贝到另一个地方,在另一个地方对数据进行修改。

    总结:

    代码:代码是只读的,不会被改变

    数据:当一个执行流尝试修改数据的时候,操作系统(OS)会自动给我们当前进程除法写时拷贝

    所以在fork后形成两个进程共用同一代码和数据,代码时只读的无法进行修改,而数据以写实拷贝的方式两个进程各自私有一份,并且两进程 不互相干扰。(具体内容有关进程地址空间)

  4. fork如何理解两个返回值问题?

    首先,我们要明白,fork是一个系统调用接口,也就是一个函数,而一个函数在最后执行return前,它主要的功能已经执行完毕。其中,调用fork的是父进程,父进程一定执行了一遍fork并且return返回了值。

    在来看fork,它的功能就是创建子进程PCB,使其跑起来,最后return返回值。

    既然fork已经执行到return,说明它的主要功能已经执行完毕,也就是此时子进程已经创建,而子进程创建后也会执行代码,也就是说,fork执行到return后,父进程和子进程都会执行一次,导致返回了两个值。

    这两个值被接收时又发生了写时拷贝,存入了不同的空间,虽然看起来存入同一变量,同一空间。文章来源地址https://www.toymoban.com/news/detail-778713.html

到了这里,关于【Linux】进程的概念及操作进程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring系列(八) --- 详述 SpringAOP--面向切面编程的相关概念及基本操作

      AOP 其实就是针对程序中的某一个类或者某一个功能做统一的处理, 如针对登录功能在前后端之间可以做一些验证操作, 验证用户名或者密码是否正确. 切面: AOP 主要是针对的某一个功能进行的操作或者定义, 而这个功能就称之为是一个切面, 如用户登录功能, 这就是一个切面

    2023年04月09日
    浏览(40)
  • 【玩转Linux操作】crond的基本操作

    🎊专栏【玩转Linux操作】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【Counting Stars 】 欢迎并且感谢大家指出小吉的问题🥰 crond 是 Linux 系统中的一个守护进程(daemon),用于管理和执行定时任务。它负责在预定的时间间隔内运行用户定义的命令、脚本或

    2024年02月12日
    浏览(60)
  • Linux基本指令与操作

    1.不加选项: 列出 当前目录下 所有子目录和文件(不包括以.开头的隐藏文件) 2.加选项: ① -a :列出当前目录下所有子目录和文件,包括以.开头的隐藏文件 ② -l :列出当前目录下所有子目录和文件及其详细信息,不包括隐藏文件 ③-1:一行只输出一个文件 ④-i:显示文件的

    2024年01月17日
    浏览(49)
  • Linux之基本指令操作

    whoami:查看当前账号是谁  who:查看当前我的系统当中有哪些用户,当前有哪些人登录了我的机器 pwd:查看我当前所处的目录,就好比Windows下的路径 ls:查看当前目录下的文件信息(不包括隐藏文件) ls -l:显示当前目录下文件的属性列表(不包括隐藏文件),也可以用l

    2024年02月05日
    浏览(38)
  • 【Linux】Linux开发工具 - vim的基本操作

    vi/vim 的区别简单点来说,它们都是多模式编辑器,不同的是 vim 是 vi 的升级版本,它不仅兼容 vi 的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window 、 mac os 、windows 本文我们讲解 vim 的三种模式 ( 其实有好多模

    2024年01月22日
    浏览(48)
  • Linux学习笔记——基本操作命令

      Linux 操作系统的 Shell 作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言系统。   Shell 是用户和 Linux 内核之间的接口程序,如果把 Linux 内核想象成一个球体的中心,Shell 就是围绕内核的外层。当从 Shell 或其他程序向

    2024年03月12日
    浏览(70)
  • 【Linux】Mysql的基本操作

    目录 一、查看数据库 二、切换数据库 三、查看数据库中的表 四、表的增删改查;  五、字段的修改与添加 六、算术运算符 七、 聚合函数在表查询中的使用  count()  max()  min()  avg()  sum() 八、条件查询  使用in查询 使用BETWEEN AND查询 使用空值查询 使用LIKE关键

    2024年03月09日
    浏览(54)
  • Linux基本指令和操作(2)

    目录 一. 适配符 * 二. man指令 -- 查看手册  三. echo指令 -- 输出字符串到文件 四. cp指令 -- 复制 五. mv指令 -- 重命名或移动文件(剪切) 六. which指令 -- 查看指令所在的路径 七. alis指令 -- 指令重命名 八. cat指令 -- 输出文件内容 九. more指令 -- 查看文件内容 十. les

    2024年02月06日
    浏览(57)
  • Linux中docker的基本操作

    是一个开源的应用 容器引擎 ,基于go语言开发并遵循了apache2.0协议 是在Linux容器里运行应用的开源工具 是一种轻量级的“虚拟机” docker的容器技术可以在一台虚拟机上轻松为任何应用创建一个轻量级的、可移植的、自给自足的容器 docker的logo设计为蓝色的鲸鱼,拖着许多集

    2024年02月08日
    浏览(54)
  • 【Mysql】万字长文带你快速掌握数据库基础概念及SQL基本操作

    为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。 (博客的参考源码可以在我主页的资源里找到,如果在学习的

    2024年02月15日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包