0


【Linux初阶】进程的相关概念 | 进程管理 & 查看进程 & 获取进程标识符 & fork进程创建

🌟hello,各位读者大大们你们好呀🌟

🍭🍭系列专栏:【Linux初阶】

✒️✒️本篇内容:进程的概念,进程管理初识(描述、管理进程),查看进程的基础方法,获取进程标识符(pid、ppid),fork进程创建(分流应用)

🚢🚢作者简介:计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-


一、什么是进程

进程的概念,有很多种不同的说法,我们看的最多的说法之一就是:一个运行起来的(加载到内存) 的程序,被称为进程。进程和程序相比,具有动态属性。

实际上,进程 = 内核数据结构(task_struct)+ 进程对应的磁盘代码


二、进程的管理

首先,我们要清楚一个前提——程序是一个文件,它存储在磁盘中。其次,我们要知道,要执行一个程序需要把程序加载到内存中。

接下来我们还需要了解一些相关的基础知识,来将进程的知识串联起来。

1.描述进程-PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block,中文名为程序控制块),Linux操作系统下的PCB是: struct task_struct
  • PCB对象是操作系统创建的

我们可以把PCB理解为一种struct结构体或类,专门用于存储加载到内存的各个程序的属性,比如程序的状态、运行的优先级等。

2.程序控制块(PCB)的管理

通过上面的知识,我们知道了内存中有从磁盘加载进来的程序块,每个程序块有对应的PCB,那么问题来了,计算机是如何对加载到内存中的程序进行管理的呢?我们通过下面的图示来理解

  • “管理”的执行本质:先描述,再组织;
  • 描述:PCB(struct task_struct),对程序信息进行了描述;
  • 组织:操作系统通过特定的数据结构,将不同的PCB(程序控制块)及其对应的程序组织(加载到内存的程序块)联系起来,最终实现对程序的管理。

进程 = 内核数据结构(PCB)+ 进程对应的磁盘代码。操作系统可以通过PCB找到对应的磁盘代码,因此,只要我们实现了对PCB的管理,也就相当于实现了进程的管理

进程组织:所有运行在系统里的进程都以task_struct链表的形式存在内核里。我们可以在内核源代码里找到它。

内存中PCB和程序块的组织形式如下图所示


三、查看进程

在Linux中查看进程的操作,实际上和我们再window上查看任务管理器是差不多的。

ps axj | head -1 && ps axj | grep ‘myproc’  或
ps axj | head -1 && ps axj | grep 4974(进程id)
  • ps axj - 查看系统所有进程;
  • head -1(数字1) - 打印标题;
  • grep ‘myproc’ - 对除文件myproc外进行行过滤。

进程在被调度运行的时候,进程就具有动态属性


四、通过系统调用获取进程标示符

1.进程和父进程

  • 进程id(PID)
  • 父进程id(PPID)

gerpid() - 获取当前进程的id(PID)

getppid() - 获取当前进程的父进程的id(PPID)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
     printf("pid: %d\n", getpid());
     printf("ppid: %d\n", getppid());
     return 0;
}

2.清除进程

kill -9 4974(进程id)    #kill -9 表示强制终止退出

五、进程创建 - fork

1.一般进程创建

实际上,我们运行的一个可执行程序,就是一个进程

命令行上启动的进程,在无特殊情况下,它的父进程都是bash。(bash为进程名,它是一个命令行解释器)

通常进程运行都是在子进程下运行,子进程和父进程相互独立但是又数据共享。目的是保护计算机安全(防止进程对系统进行危险操作)。

当程序单线程运行时,进程在子进程下运行。多次运行同一运行程序,子进程id改变,父进程id不变,说明每次运行该程序的子进程变了,但是每个子进程对应的父进程不变。

2.通过系统调用创建进程-fork初识

  • 运行 man fork 认识fork(除了起始页,还可通过底部命令行指令:/return val查看返回值);
  • fork有两个返回值(如果成功,子进程的pid返回父进程,0返回给子进程;如果失败,返回-1);
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)。

接下来我们看下面这段代码

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    //创建子进程 -- fork是一个函数 -- 函数执行前:只有一个父进程 -- 函数执行后:父进程+子进程
     fork();
     printf("我是一个进程,pid:%d, ppid: %d\n", getpid(), getppid());

     sleep(2);
     return 0;
}

3. fork的分流应用

通过文档我们了解到,fork 之后通常要用 if 进行分流【通过返回值不同实现分流】

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
     pid_t id = fork();
     if(id < 0)
    {
         perror("fork");
         return 1;
     }
     else if(id == 0)
     { 
        //child
        printf("I am child : %d!, id: %d\n", getpid(), id);
     }
     else
     { 
        //father
        printf("I am father : %d!, id: %d\n", getpid(), id);
     }

     sleep(1);
     return 0;
 }

结果是,父进程和子进程将会同时运行,因此我们可以得出结论

  • fork() 之后,会有父进程+子进程两个进程执行后续代码(拥有多个线程,多个执行流,这就是我们所说的多线程)
  • fork后续的代码,被父子进程共享(注意:共享不代表需要一个进程执行所有代码)
  • 通过返回值不同,可以让父子进程各自执行后续共享代码的一部分

** 通过对进程和合理化利用,就可以多进程/多线程运行程序,实现并发式编程!!!**


🌹🌹 Linux进程的相关概念大概就讲到这里啦,博主后续会继续更新更多Linux操作系统的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/Captain_ldx/article/details/127932653
版权归原作者 Captain-Lin 所有, 如有侵权,请联系我们删除。

“【Linux初阶】进程的相关概念 | 进程管理 & 查看进程 & 获取进程标识符 & fork进程创建”的评论:

还没有评论