目录

前言

Part1. 进程概念

Part2. 创建进程 fork()

Part3. 结语


前言

  在Linux的学习中认识进程是至关重要的一环,所以接下来来跟随小编的视角来认识一下进程的概念吧。


let's go!!!!!!!!


Part1. 进程概念

进程:正在运行的程序

磁盘上存放的是可执行程序,当程序被加载到内存之后,就变成进程。
操作系统中会同时运行大量进程操作系统维护一个结构体,存放进程全部信息:代码地址、数据地址、pid等。


PCB(task_struct):Linux下的进程控制块。
PCB + 代码和数据 = 进程


PCB(task_struct)是内核用来管理进程的结构体,PCB是对进程的描述,进程真正的代码、数据在内存当中。


task_struct核心属性

1. pid:进程id,区分不同进程

2. 进程状态

3. 优先级

4. 程序计数器

5. 内存指针


系统当中所有运行的程序,都是一个个进程。


相关系统调用与命令

1. getpid():头文件 <sys/types.h>,获取当前进程pid

2. ps axj查看系统全部进程


shell符号小知识

a && b:执行A成功之后,才执行B

a ; b:无论A执行成功失败,之后都执行B


# 过滤进程
ps axj | head -1
ps axj | grep 进程名


进程操作命令

1. ctrl + c:终止前台进程

2. kill -9 n:n为pid号,强制杀死对应进程


/proc 虚拟文件系统

/proc是内存当中的虚拟文件夹。

• ls /proc/n:n代表进程pid,查看该进程对应的文件表


• exe:符号链接,指向进程原始可执行程序。
即使磁盘原始程序被删除,进程依旧可以正常运行。因为程序数据已经加载到内存,删除的只是磁盘文件。


• cwd:符号链接,记录进程当前的绝对工作目录
相对路径,是相对于当前工作目录cwd;修改cwd,相对路径的查找逻辑会跟着改变


chdir("...")修改进程当前工作目录。头文件 <unistd.h>。

getppid()获取父进程pid
现象:子进程pid变化,父进程pid不变


shell命令行:bash是命令行解释器,我们在命令行执行的指令,绝大多数都会交给bash创建子进程去执行。


Part2. 创建进程

//头文件
#include <sys/types.h>
#include <unistd.h>
//基础示例
printf("父进程:%d\n", getpid());
fork();
printf("子进程:%d\n", getpid());
//fork之后,会存在两个进程,父子进程都会继续执行后续代码。
//子进程会拷贝父进程的代码和数据,拥有自己独立的页表。

fork返回值(核心考点)

返回0:代表当前是子进程

返回大于0返回值是子进程pid,代表当前是父进程

返回‑1fork创建进程失败


pid_t id = fork();
if(id == -1){
    // 出错处理
}else if(id == 0){
    // 子进程执行逻辑
}else{
    // 父进程执行逻辑
}

为什么fork会有两个不同返回值?

内核层面

1. fork内部申请PCB,拷贝父进程数据、代码;生成子进程PCB

2. 父子两个进程,都会执行return id;

3. 父进程拿到子进程pid;子进程拿到返回值0。
所以同一个id变量,父子进程看到的值不一样,因此可以使用if‑else区分父子进程。 


写时拷贝原理:

父子进程刚fork完成时,共享同一份数据。
当任意一个进程尝试修改数据,操作系统才会把对应内存拷贝一份,父子进程各自拥有独立副本。
不修改数据,则不会发生拷贝,节省内存开销。


Part3. 结语

  这篇文章我们认识并知道了如何创建进程,接下来,小编还会带来更多Linux相关的知识,敬请期待~

 最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!

 最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐