【Linux探索学习】进程的概念及详细解释和一些简单的相关操作

目录

一.什么是进程?

1.1查看进程

1.2进程的cwd与exe

二.认识fork-系统调用创建进程

[什么是 fork()?](#什么是 fork()?)

[fork() 的返回值](#fork() 的返回值)

[独立的实现机制:写时复制(Copy-on-Write, COW)](#独立的实现机制:写时复制(Copy-on-Write, COW))


一.什么是进程?

从用户的视角来看,进程是一个程序的运行实例;从操作系统的视角来看,进程是一个拥有资源分配能力的实体。

进程 = 内核数据结构对象(PCB) + 自己的代码和数据

在Linux中进程可以看做是PCB(task struct)和自己的代码和数据 组成的。PCB中包含该进程的所有属性,与代码以及数据共同组成进程,PCB中存在指向其他进程的指针,通过指针的指向,进程通过双向链表 的数据结构来进行链接,而进程的管理就是对链表的增删查改。并且每个进程都有独立的地址空间,以避免相互干扰。

PCB主要内容(PCB 被实现为一个名为task_struct的结构体)

  • 标识符:如进程 ID (PID),用于唯一标识进程。
  • 状态:包括进程当前的运行状态(运行、就绪、阻塞等)。
  • 优先级:用于调度时比较不同进程的重要性。(CPU计算的优先级)
  • 程序计数器:存储下一条将要执行的指令地址。
  • 内存指针:指向进程的代码段、数据段以及共享内存块。
  • 上下文数据:包括处理器寄存器中的数据。
  • I/O 状态信息:描述进程使用的文件和 I/O 设备。
  • 记账信息:记录进程使用的资源总量和时间。

所有进程的 PCB 以链表形式组织。通过 task_struct 中的 nextprev 指针,形成一个双向链表,对进程进行遍历和管理。

1.1查看进程

我们可以通过查看/proc/文件,来查看我们目前正在执行的全部进程

上面蓝色的数字就是进程的PID,每个进程都会有一个对应的PID,PID就是我们上面所说的进程ID,也叫做进程标识符,我们可以通过这些进程标识符来查看每个进程具体的信息,比如查看1号进程

除了上面的这个方法外,我们还可以通过ps axj这个指令,不仅可以看到所有的进程,还可以看到它们的进程的属性信息

我们可以只打印出一行来看一下进程属性的内容(利用管道 | 和打印行数head)

这里要注意的点就是PPID指的是父进程标识符,PID知道是当前进程标识符、

我们可以查看下我们自己创建的这个进程的相关信息(注意只有当我们的程序在跑着的时候它才叫进程,所以我们可以将我们的程序写成一个死循环,然后让它执行起来)

复制代码
ps axj | head -1 && ps axj | grep mytest

1.2进程的cwdexe

cwd是一个符号链接,指向进程的当前工作目录。当前工作目录是指进程在执行过程中,其相对路径的基准目录。就好比你在终端中切换到某个目录,然后运行一个程序,这个被切换到的目录就是程序的当前工作目录。

例如,假设你在/home/user/projects目录下启动了一个名为my_app的程序,那么/proc/[PID]/cwd就会指向/home/user/projects目录。

exe是一个符号链接,指向启动该进程的可执行文件的路径。这个可执行文件是进程运行的主体,包含了程序的机器代码和资源。

例如,如果你使用命令/usr/bin/my_app启动了一个程序,那么/proc/[PID]/exe就会指向/usr/bin/my_app。

二.认识fork-系统调用创建进程

  • 回值为pid_t类型
  • 包含在头文件<unistd.h>

可以通过以下代码获取进程的 PID 和其父进程的 PPID:

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    printf("pid: %d\n", getpid());
    printf("ppid: %d\n", getppid());
    return 0;
}

fork() 是 Linux 中用于创建新进程的函数,我们先来看下面的一个小程序:

cpp 复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 int main()
  5    {
  6 
  7 |      printf("我是父进程!!,我的pid:%d\n",getpid());
  8 |      fork();
  9 |      printf("我是子进程!!,我的pid:%d\n",getpid());
 10        return 0;
 11    }

可以看出,在fork();执行后出现了两个进程,其中一个进程的pid是fork前的进程的pid,一个是新进程的pid。

cpp 复制代码
1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4  int main()
  5 {
  6 pid_t id = fork(); // 父子进程的独立过程是在调用 fork() 函数时完成,之后父子进程独立
  7 
  8 if(id < 0)
  9 {
 10 |   perror("fork");
 11 |   return 1;
 12 }|  
 13 else if(id == 0)
 14 {
 15 |   // child 
 16 |   
 17 |   
 18 |   
 19 |    printf("我是一个子进程!我的pid:%d,我的父进程id:%d\n",getpid(), getppid());
 20 |   
 21 }
 22 else
 23 {
 24 |   // father
 25 |  
 26 |   
 27 |   
 28 |     printf("我是父进程!我的pid:%d,我的父进程id:%d\n",getpid(), getppid());
 29 |   
 30 }
 31                                                                                                                                                                                                                                  
 32 printf("返回结束\n");
 33 
 34 return 0;
 35 }
~        

子进程和父进程的执行流从 fork() 的返回值处分叉:

父进程 继续运行时,fork() 返回子进程的 PID。子进程 继续运行时,fork() 返回 0。

什么是 fork()

fork()是用于创建进程的系统调用。

它会从当前运行的进程(称为父进程)中复制出一个几乎完全相同的新进程(称为子进程)。

父子进程几乎完全独立,但共享相同的代码段

父子进程拥有不同的内存空间,彼此之间不影响。

fork() 的返回值
  1. 在父进程中fork() 返回子进程的 PID(进程 ID),这是一个正整数(> 0)。
  2. 在子进程中fork() 返回 0
  3. 创建子进程失败返回-1。
独立的实现机制:写时复制(Copy-on-Write, COW)

现代操作系统使用了一种优化机制,叫做 写时复制(COW),以减少不必要的资源浪费:

  • **fork()** 刚返回时,父子进程共享相同的物理内存页(只读),因此复制过程很快。
  • 当父进程或子进程试图修改内存时
    • 操作系统会为需要修改的部分分配新的物理内存。
    • 修改后的内存空间对父子进程来说是独立的。

因此,只有在需要时,内存的独立性才真正实现,也就是需要对对内存中数据进行修改的时候,但逻辑上,父子进程从 fork() 返回后就已经被视为完全独立了。

相关推荐
风兮雨露1 小时前
VMware虚拟机(安装/绿色版)
学习
charlie1145141912 小时前
嵌入式Linux驱动开发——新 API 字符设备驱动完整教程 - 从设备结构体到应用测试
linux·运维·驱动开发
飞Link2 小时前
2000 亿砸向算力:字节跳动 AI 基建跨越,后端与运维的“万亿 Token”生死战
运维·人工智能
消失的旧时光-19432 小时前
C语言对象模型系列(四)《Linux 内核里的 container_of 到底是什么黑魔法?》—— 一篇讲透 Linux 内核的“对象模型”核心技巧
linux·c语言·算法
zl_dfq2 小时前
python学习8 之 【集合、datetime模块、字典】
学习
SWAGGY..3 小时前
Linux系统编程:(二)基础指令详解
linux·运维·服务器
kdxiaojie3 小时前
U-Boot分析【学习笔记】(3)
linux·笔记·学习
烛衔溟3 小时前
TypeScript 接口继承与混合类型
linux·ubuntu·typescript
MediaTea3 小时前
Scikit-learn:从数据到结构——无监督学习的最小闭环
人工智能·学习·算法·机器学习·scikit-learn
张文君4 小时前
上古世纪服务端编译安装AAEmu docker编译安装
运维·docker·容器