Linux--进程(进程概念、PCB、进程状态、孤儿进程、进程优先级、进程切换、进程调度)

一、进程概念和PCB

1.什么是进程?

进程是操作系统中的一个核心概念,指的是正在执行的程序实例。它不仅包含程序的代码,还涉及程序运行时的状态和资源。

程序与进程的区别:

  • 程序静态的指令集合;比如:通过语言编写的程序。

  • 进程:程序的一次动态执行,包括代码、数据和状态(将磁盘的代码加载到内存中,运行的程序称之为进程 )。

进程 = 内核数据结构(例如:PCB) + 程序的代码和数据

运行程序本质是系统启动一个进程:

  • 执行完就退出 -- 例如:ls,pwd等指令
  • 一直不退,直到用户退出 -- 常驻进程(例如:杀毒软件)

2.进程的描述方式--PCB

操作系统的管理核心方式为“先描述再组织”,对进程管理时,需要先对进程信息及属性进行描述。

  • PCB:进程控制块(process control block),是一种数据结构,用于存放进程信息,可以理解为进程属性的集合。
  • task_struct:PCB的一种,在Linux中描述进程的结构体叫做task_struct;是Linux内核的一种数据结构,它存在于RAM(内存)里并包含进程的信息(属于内存级的数据对象)。

task_struct的内容:

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

对进程进行组织:
所有运行在系统里的进程都以task_struct链表(双链表)的形式存在内核里,对进程的管理就变为了对链表的增删查改。

查看进程信息:
进程的信息可以通过 /proc 系统文件夹查看

 /proc 是 Linux 系统中一个特殊的虚拟文件系统,它提供了内核和进程信息的接口。/proc 目录中的文件和目录并不是真实的磁盘文件(并不是磁盘级的文件),而是由内核动态生成的,用于反映系统状态和进程信息。 进程的信息以文件的形式呈现,/proc目录内分别以每个进程的PID为名创建一个目录(实时创建:进程启动时,同时创建对应目录),一个目录代表一个进程,目录内存放着一个进程的信息;当进程结束时,对应的目录也会被自动删除掉了。
查看PID为1的进程信息:

ps命令可以查看进程的相关属性,ps的底层就是通过/proc进行文本分析来实现的
指令 选项 ps aux ps ajx
显示内容 显示所有用户的进程详细信息。 显示进程的作业信息(PGID、SID 等)。
常用场景 查看进程的资源使用情况(CPU、内存)。 查看进程的父子关系、进程组和会话信息。
输出字段 包含 USER%CPU%MEM 等。 包含 PPIDPGIDSID 等。

进程信息:

  • exe:启动该进程的程序在磁盘中的位置

    在该进程没有结束时在磁盘中删除掉该程序,进程任然能进行(因为程序会加载到内存中,磁盘删除暂时不影响)
  • cwd:cwd(current work dir:当前工作目录)-> 例如:fopen时没有该文件就会在当前工作路径下创建该文件;当运行程序启动一个进程时,该进程的cwd会记录在开始运行该程序时的磁盘位置作为当前工作路径;

    可以通过系统调用 int chdir(const char* path)  更改进程的当前工作路径
    //更改当前工作路径
    #include <iostream>
    #include <algorithm>
    #include <unistd.h>
    using namespace std;
    
    int main()
    {
      chdir("/");
      while(1)
      {
         cout << "PID:" << getpid() << endl;
         cout << "PPID:" << getppid() << endl << endl;
         sleep(1);
      }
    
      return 0;
    }
    

/proc和task_struct的关系:
task_struct 是 Linux 内核用于表示进程或线程的核心数据结构,存储进程各类关键信息。/proc 是虚拟文件系统,将 task_struct 中的信息以文件和目录形式映射到用户空间,每个进程对应 /proc 下以其 PID 命名的目录,目录里文件包含该进程 task_struct 部分信息。它为用户提供查看和监控进程状态的便捷方式,是内核与用户空间交互的桥梁,信息随 task_struct 动态更新。

二、task_struct -- 进程标识符PID和PPID

  • PID:描述本进程的唯一标示符,用来区别其他进程。
  • 系统对PID的维护:累加增长且连续,所以同一个程序在不同时间运行时进程PID不同
  • PPID:表示当前进程的父进程的PID。(在Linux系统中,启动之后,新创建的任何进程都是由自己的父进程创建的)

通过系统调用获取当前进程标识符:

  • 进程id(PID):getpid()
  • 父进程id(PPID):getppid()
  • 头文件:<unistd.h>
  • 返回值类型:pid_t(本质是整型类型的封装)
//循环打印当前进程的PID和PPID
#include <iostream>
#include <algorithm>
#include <unistd.h>
using namespace std;

int main()
{
  while(1)
  {
    pid_t pid = getpid();
    pid_t ppid = getppid();

    cout << "PID:" << getpid() << endl;
    cout << "PPID:" << getppid() << endl << endl;
    sleep(1);
  }

  return 0;
}

命令行中,执行命令/执行程序,本质是bash作为父进程,创建的子进程,由子进程执行程序(bash--命令行解释器shell的一种,每一次登录,都会创建一个bash进程)

三、通过系统调用fork()创建进程

  • 头文件:<unistd.h>
  • 原型:pid_t fork(void)
  • 返回值:当前进程作为父进程创建一个子进程,如果创建成功fork返回给父进程新创建子进程的PID,返回给子进程0;如果创建失败fork返回给父进程-1。所以根据父子进程的返回值不同可以进行分流,由返回值判断是父进程还是子进程并执行不同的操作。
  • 父子进程代码共享,数据各自开辟空间私有一份(采用写时拷贝);进程具有很强的独立性,多个进程之间,运行时互不影响,即便是父子进程,代码是只读的,数据是私有的。
#include <iostream>
#include <algorithm>
#include <unistd.h>
using namespace std;

int main()
{
  pid_t pid = fork();
  if(pid == 0) //子进程
  {
    while(1)
    {
        cout << "子进程PID:" << getpid() << ' ' << "PPID:" << getppid() << endl;
        sleep(1);
    }
  }
  else if(pid > 0) //父进程
  {
    while(1)
    {
        cout << "父进程PID:" << getpid() << ' ' << "PPID:" << getppi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

みずいろ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值