当前位置: 首页 > news >正文

[Linux]进程 / PID

一、认识进程 --- PCB

写一个死循环程序执行起来,观察进程

ps ajx        显示所有进程

用分号可以在命令行的一行中执行多条指令,也可以用 && :

ps ajx | head -1 && ps ajx | grep proc

终止掉进程后再查看:

所以 ./proc 就是死循环程序运行的进程

grep --color=auto proc 之所以一直都在,是因为命令行指令执行时也是一个进程

ps ajx | grep proc 执行时,grep 指令也变成了一个进程,查询结果自然就会包含在内

可以用 grep 的 -v 选项反向搜索来不显示这个进程:

进程可以分为两种:一是执行完就退出的,例如指令,二是用户不关就不退的,被称为常驻进程,例如杀毒软件。

二、进程属性 --- task_struct 内容分类

1. PID

PID 是进程的标示符,用于唯一标识一个进程。

可以用 getpid() 来获取进程的 PID:(需要 sys/types.h 头文件)

2.kill

kill 是一条进程相关的指令,有许多选项:

通过 -9 或 -SIGKILL 可以关闭一个进程:

kill -9 <PID>

3.  /proc

Linux 中一切皆文件,所以进程的属性也以文件的形式可供用户查看

这里以数字命名的每个目录都代表着一个进程,里面的文件都是这个进程相关的属性

其中:

(1)exe

exe 是一个链接文件,标识了这个进程来源于哪个可执行程序

如果我们删掉 proc 文件,就会变成:

注意此时进程之所以还在进行,还有这个进程的目录,是因为我们的删除操作删除掉的是磁盘中的 proc 文件,而进程是内存级的,只要不停止运行就会一直在。

(2)cwd

current work directory “当前工作目录”的缩写

进程刚刚创建时,会用自己的 cwd 属性记录下程序所在的目录作为默认的“当前路径”

如果我们在程序中用 fopen 打开一个新 log.txt 文件,运行后就会在当前路径下创建出一个 log.txt 文件。这个“当前路径”,就来自于进程的 cwd 属性。

而且这个文件被新建时,创建的路径使用的是绝对路径,是用进程的 cwd 和文件名拼接成的:/home/mmr/linux-c/par02/log.txt

想要改变进程的 cwd,可以用 chdir()

就可以把进程的 cwd 更改为根目录,log.txt 也就可以新建在根目录下了(注意普通用户没有根目录的写权限,所以普通用户会创建失败)

(3)/proc是内存级文件

/proc 并不存储在硬盘当中,关机时整个文件被释放掉,不会存储。

4.PPID

在 Linux 系统中,系统启动之后,新创建的任何进程,都是由自己的父进程创建的。

PPID 就是父进程的 PID 。

可以用 getppid() 来获取进程的 ppid

可以看到 ppid 一直是相同的,我们查看一下:

可以看到这个进程是 bash,叫做命令行解释器,是 Linux 系统的shell 外壳

命令行中,执行指令、执行程序,本质都是 bash 的进程,创建的子进程,由子进程来执行代码

用户每一次登录,系统都会为用户创建一个 bash 进程,这里 bash 前有一个 "-",代表当前这个用户是使用命令行终端进行登录的。

三、使用系统调用,创建进程 --- fork

我们运行一下:

可以看到 child proc 打印了两遍。

这是因为 fork 创建出子进程后,原先的进程和子进程都要运行。原先的进程的父进程是 bash,子进程的父进程是原先的进程。

这两个进程先后连续创建的,所以 pid 也是连续的。

由 fork 的返回值可以知道,如果子进程创建成功,那么在原先的进程中,获得的返回值是子进程的 pid,而子进程中获得的 fork 返回值是 0

fork 创建的子进程,与其父进程共享同一份代码,但是数据是各自私有一份的,互不干扰。

父进程的代码,是由硬盘加载进内存后运行的,而子进程的代码,是直接共享自父进程的,而非从硬盘中加载得来。

所以说,进程具有很强的独立性。

多个进程之间,运行时,是互不影响的。

四、创建多个进程

1. C++

Linux 中 C++ 可以使用 .cpp .cc .cxx 作为后缀

使用 g++ -o <程序名> <源文件名> 生成可执行程序

如果使用了C++11中的语法:

2.创建多个进程

为什么这里子进程的 PPID 是 1 ?

因为我截这个图时父进程已经执行完毕挂掉了,此时子进程的 PPID 就不会是原先的父进程,会被 init 进程,托管给 1 号进程。

五、再理解创建子进程

1. fork 函数为什么有两个返回值

在 fork 函数体内部,先是父进程在走,在走的时候,子进程被创建出来,因为父子进程是共享同一份代码的,所以这时候就是父子进程一起在走 fork 函数。

当 fork 函数运行到最后的 return 语句时,父子进程各自执行一次 return,父进程返回父进程的值,子进程返回子进程的值。又因为父子进程的数据是各自私有一份的,所以即使返回值不同也互不干预,不会有任何后果。

因此虽然一个函数有两个返回值,但其实并不冲突。

2. fork之后,父子谁先运行

fork之后,父子进程谁先运行是不确定的,是由OS的调度器自主决定的。

http://www.xdnf.cn/news/1157995.html

相关文章:

  • [硬件电路-57]:根据电子元器件的受控程度,可以把电子元器件分为:不受控、半受控、完全受控三种大类
  • 非线性优化框架CasADi工具箱求解最优控制问题OCP
  • 什么是卡贴???
  • 零基础学习性能测试第一章:核心性能指标-并发量
  • 简洁高效的C++终端日志工具类
  • 2.组合式API知识点(1)
  • Dev-C++——winAPI贪吃蛇小游戏
  • Softhub软件下载站实战开发(十九):软件信息展示
  • 让不符合要求的任何电脑升级Windows11
  • 2025.7.20总结-实战演讲
  • 2025年03月20日中软(外包中控)
  • 30天打牢数模基础-卷积神经网络讲解
  • 《P3398 仓鼠找 sugar》
  • 基于深度学习的目标检测:从基础到实践
  • JavaScript 语言基础详解
  • 050_Set接口(HashSet / TreeSet / LinkedHashSet)
  • leetcode75【经典动态规划】之:最长公共子序列
  • imx6ull-系统移植篇11——U-Boot 移植(下)
  • 【Java源码阅读系列57】深度解读Java MethodHandle 类源码
  • 神经网络:池化层
  • jQuery多库共存
  • SQL189 牛客直播各科目同时在线人数
  • c/c++-memory-management
  • 【PTA数据结构 | C语言版】是不是堆
  • SpringBoot集成Skywalking链路跟踪
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 59(题目+回答)
  • 奥比中光双目摄像头实现物品抓取的机器人系统
  • 【Lua】多脚本引用
  • 数据结构 | 栈:构建高效数据处理的基石
  • Docker Compose