云计算百科
云计算领域专业知识百科平台

【Linux系统】进程的生命旅程:从创建到独立的演绎

文章目录

  • 一. 进程概念
  • 二. 查看进程的方法
    • 2.1 getpid() && getppid() 函数
    • 2.2 ps && grep 指令
    • 2.3 /proc 目录
  • 三. 创建进程
    • 3.1 fork() 函数
    • 3.2 关于fork的问题

一. 进程概念

进程(Process)是计算机中正在执行的程序的一个实例。它是操作系统资源分配和调度的基本单位,是操作系统管理计算机硬件和软件资源时的核心概念之一。

程序与进程的区别:

  • 程序:是一组静态的指令集合(二进制文件),它是一个静态的实体,不会占用计算机的系统资源。

  • 进程:是程序的执行实例,它是动态的,并且在执行过程中会占用系统资源(如CPU时间、内存等)。

内存在同一时间会有成百上千的被加载进来的程序,操作系统是需要对其进行管理的。

操作系统会给每个代码和数据块建立一个struct结构体(进程控制块),结构体存的是对代码和数据块的信息,也有相应的指针指向对应的代码和数据。许多这样的结构体组成双链表,也就是进程列表。

进程控制块PCB→Process Control Block

Linux系统中PCB是task_struct

在这里插入图片描述 PCB相关内容:https://www.cnblogs.com/tongyan2/p/5544887.html

总结:进程 = PCB(task_struct) + 对应的代码和数据

进程信息被放在进程控制块中,可以理解为进程属性的集合。操作系统要对进程进行管理,其实就是对描述进程的task_struct形成的数据结构进行增删查改。

注:我们在Linux执行的指令、工具、程序,运行起来都是进程


二. 查看进程的方法

2.1 getpid() && getppid() 函数

getpid()//获取进程pid
getppid()//获取父进程pid

  • pid 就是进程的标识符(编号);
  • 这两个函数都是系统调用

我们可以使用 man 2 getpid 来查看相关信息。 在这里插入图片描述

其返回值就是一个整型变量,成功调用返回一个大于0的整数,失败就返回-1。


2.2 ps && grep 指令

ps axj | head -1 ; ps axj | grep mypro//查看mypro进程相关信息

在这里插入图片描述 由于grep本来也是个进程,查找mypro进程,grep进程就会带上mypro的关键字,那么查出来的进程也会有grep进程,要屏蔽的话就使用grep -v反向匹配

ps axj | head -1 ; ps axj | grep mypro | grep -v grep


2.3 /proc 目录

ls /proc

ls /proc 以文件的方式查看进程,proc目录记录进程信息,每个数字目录代表一个正在运行的进程,进程结束后,对应的目录文件就会删除。

我们先运行一个pid为70816的进程。

在这里插入图片描述 再使用ls /proc查看进程信息,可以看到有70816的文件夹。 在这里插入图片描述 让我们直接查看70816的文件夹。

在这里插入图片描述 在这里插入图片描述

  • exe 代表我们的可执行文件,如果将其删除不会对正在运行的进程造成影响,因为删除的是磁盘上的程序,可执行文件已经被加载在内存里了。

  • cmd (current work directory)是进程所在的当前文件路径,我们的程序在创建文件时默认是在当前路径下创建的,而当前路径就是通过cmd获取的。

  • 改变文件路径

    我们可以使用chdir改变当前进程的文件路径,以下为相关信息。

    在这里插入图片描述 结束进程:ctrl+c 或 kill -9 pid


    父进程pid不变现象:

    多次启动进程时,会发现其父进程的pid不变,这是因为该父进程其实就是bash进程,我们执行的程序或者指令大多都是bash的子进程。

    在这里插入图片描述 当子进程出问题,不会影响bash进行,因为进程具有独立性;当我们启动xshell时,系统自动生成bash进程。

    三. 创建进程

    3.1 fork() 函数

    创建进程需要使用系统调用fork函数。

    #include <unistd.h>
    pid_t fork();

    在这里插入图片描述

  • fork 系统调用,没有参数,有两个返回值

  • fork 在创建进程成功时,给父进程返回子进程的pid,给子进程返回0,失败时返回-1给父进程(没有子进程创建)。这样做的原因是因为父进程与子进程的关系是一对多的关系,将子进程的pid返回给父进程让其可以区分不同的子进程。

  • 父子进程代码共享,数据各自开辟空间,私有一份(写时拷贝)

  • 在这里插入图片描述 fork的使用示例:

    #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)
    {
    //子进程
    while(1)
    {
    sleep(1);
    printf("I am a child process, my pid: %d\\n", getpid());
    printf("\\n");
    }
    }
    else
    {
    //父进程
    while(1)
    {
    sleep(1);
    printf("I am a fathermak process, my pid: %d\\n", getpid());
    }
    }
    return 0;
    }

    在这里插入图片描述 从上面的现象我们可以看出,id == 0 和 id > 0 同时成立,这是因为当我们创建完子进程后,其实已经存在了两个进程,会共用fork之后的代码,对于父进程 id > 0,对于子进程 id == 0 ,在同一时间内两个进程执行相同代码的不同部分,就会产生上图的结果。

    3.2 关于fork的问题

  • 为什么fork会返回两个值?
  • 在fork函数内部,执行到最后的return语句时,子进程已经创建好了,两个进程就会同时执行return语句,fork就能返回两个值,我们以前认知的一个函数只能有一个返回值是在同一个进程的条件下才成立的。

    在这里插入图片描述

  • 为什么 id == 0 和 id > 0 同时成立?

    • 进程具有独立性。父子进程不同的PCB、代码虽然共享,但是只读的,不会影响独立性

    • 父进程和子进程共用代码和数据,当任意进程尝试修改数据,操作系统在数据被修改前拷贝一份,让目标进程修改这份数据的拷贝。通过这种写时拷贝技术让不同进程的数据独立,从而保证进程的独立性。


  • Have a good day😏

    See you next time, guys!😁✨🎞

    请添加图片描述

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【Linux系统】进程的生命旅程:从创建到独立的演绎
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!