2024-09-18 实操层面理解进程

news2024/9/23 1:29:06

一、进程初探

# ps ajx | head -1
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
root@hcss-ecs:~# ps ajx | head -1; ps ajx | grep proc
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
  24696   24707   24707   24679 pts/2      24707 S+    1000   0:00 ./proc
  24756   24806   24805   24756 pts/3      24805 S+       0   0:00 grep --color=auto proc
root@hcss-ecs:~# ps ajx | head -1 && ps ajx | grep proc
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
  24696   24707   24707   24679 pts/2      24707 S+    1000   0:00 ./proc
  24756   24810   24809   24756 pts/3      24809 S+       0   0:00 grep --color=auto proc
root@hcss-ecs:~# ps ajx | head -1 && ps ajx | grep proc | grep -v grep
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
  24696   24813   24813   24679 pts/2      24813 S+    1000   0:00 ./proc

运行程序本质上是在操作系统中创建一个进程。

某些命令如 `ls` 和 `pwd` 完成操作后即终止其进程。

常驻进程(如后台服务)则持续运行,直至用户主动终止。

getpid() 是一个系统调用,用于获取当前进程的进程标识符(Process ID, PID)。

使用 kill -9 [pid] 可以立即终止指定的进程,其中 [pid] 是该进程的进程ID。此操作发送一个不可忽略的 SIGKILL 信号给目标进程,强制其立即停止运行。

二、理解 cwd

在当前项目中新建文件通常指的是在进程的当前工作目录(Current Working Directory, CWD)中创建文件。

chdir() 是一个系统调用,用于改变当前进程的工作目录。调用 chdir() 函数时需要传递一个新的目录路径作为参数,如果调用成功,则该进程后续执行的涉及文件操作的行为(如打开文件、创建文件等)都会基于这个新设置的工作目录进行。chdir() 对于需要临时改变目录进行特定操作的应用程序非常有用,但是需要注意在多线程环境下可能引发的问题,以及改变目录后对程序其他部分的影响。使用 chdir() 后,可以通过 getcwd() 函数来确认当前的工作目录是否已经更改至预期的路径。

三、/proc

/proc 并不是一个磁盘级别的文件系统,而是一个伪文件系统(virtual file system),用于向进程提供信息以及对进程进行控制。/proc 文件系统的内容由内核动态生成,反映了当前系统的状态信息,包括运行中的进程信息、系统设备信息、系统状态统计等。

pid_t getppid(void)

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

因为命令是在一个由 bash 启动的shell会话中执行的。当您登录到Linux系统并输入命令时,这些命令通常是由 bash 解释并执行的。因此,如果您在一个交互式的 bash shell中运行诸如 ps 或者 pgrep 这样的命令来查找父进程ID,那么这些命令的直接父进程往往就是 bash 本身。

命令行中,执行命令/程序,本质是bash的进程创建的子进程,由子进程来执行我们的代码

使用系统调用,创建进程

fork() 是一个系统调用,用于创建一个新进程,它是Unix及类Unix操作系统中进程创建的核心机制之一。fork() 创建的新进程称为子进程,而创建它的进程称为父进程。

功能:fork() 创建一个与父进程几乎完全相同的副本(子进程),两者共享相同的程序代码但拥有独立的数据空间。

This is a proc, its pid = 29740, its ppid = 29706
This is a child proc, its pid = 29740, its ppid = 29706
This is a child proc, its pid = 29741, its ppid = 29740

PID 为 29740 的进程是由 PID 为 29706 的进程创建的。
PID 为 29741 的进程是由 PID 为 29740 的进程创建的,因此它是 PID 为 29706 的进程的“孙子”进程。

This is a proc, its pid = 29804, its ppid = 29706
This is a father proc, its pid = 29804, its ppid = 29706, ret id = 29805
This is a child proc, its pid = 29805, its ppid = 29804, ret id = 0

返回值:fork() 调用会返回两次,一次在父进程中,一次在子进程中。在父进程中返回的是子进程的PID,在子进程中返回的是0。

父 : 子 = 1 : n

fork() → 两个进程 → 父子关系 → 一般而言,代码是会共享的,但是数据是各自私有一份的

【Q】为何数据是各自私有一份的呢?

【A】进程具有很强的独立性,多个进程之间,即便是父子关系,运行时也是互不影响

用途:常用于实现进程间的并行操作、创建子进程执行不同任务等。

#include <stdio.h>
#include <unistd.h>

int main(){
	int gval = 0;
	printf("This is a proc, its pid = %d, its ppid = %d\n", getpid(), getppid());
	pid_t id = fork();

	if(id > 0){
		while(1){
			printf("This is a father proc, its pid = %d, its ppid = %d, ret id = %d, gval = %d\n", getpid(), getppid(), id, gval);
			gval += 10;
			sleep(1);
		}
	}
	else if(id == 0){
		while(1){
			printf("This is a child proc, its pid = %d, its ppid = %d, ret id = %d, gval = %d\n", getpid(), getppid(),id, gval);
			++gval;
			sleep(1);
		}
	}
	return 0;
}

以上代码展示了父进程和子进程的并行执行。父进程不断地增加一个值并打印自己的状态,而子进程则以不同的速度增加同一个值并打印自己的状态。虽然它们共享一个变量 gval,但是它们的修改是独立的,因为每个进程有自己的内存空间。

四、创建多进程简例

#include <iostream>
#include <sys/types.h>
#include <vector>
#include <unistd.h>
using namespace std;

const int num = 10;

void SubProcRun(){
	while(true){
		cout << "This is a sub proc, its pid is " << getpid() << ", its ppid is " << getppid() <<  endl;
		sleep(5);
	}
}

int main(){
	vector<pid_t> allchild;
	for(int i = 0; i < num; ++i){
		pid_t id = fork();
		if(id == 0){
			SubProcRun();
		}
		//只有父进程会在这里执行
		allchild.push_back(id);
	}
	//父进程
	cout << "Each child is above:" << endl;
	for(auto e: allchild){
		cout << e << " ";
	}
	cout << endl;
	sleep(10);
	while(true){
		cout << "This is the father proc, its pid is " << getpid() << endl;
		sleep(1);
	}	
	return 0;
}	
ps ajx | grep mproc
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
      1   48073   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48074   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48075   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48076   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48077   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48078   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48079   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48080   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48081   48072   46010 ?             -1 S     1000   0:00 ./mproc
      1   48082   48072   46010 ?             -1 S     1000   0:00 ./mproc
  72826   73911   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73912   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73913   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73914   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73915   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73916   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73917   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73918   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73919   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73920   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73911   73921   73911   72826 pts/1      73911 S+       0   0:00 ./mproc
  73756   73934   73933   73756 pts/2      73933 S+       0   0:00 grep --color=auto mproc

 五、结合系统接口理解子进程的创建

1. id 的返回值,给父(subproc)给子(0)

2. 函数 fork() 怎么会有两个返回值?

#include <unistd.h>
pid_t fork(void)
  • 函数实现里多了一个 task_struct:创建子进程的时候,子进程的 task_struct 是拷贝自父进程的
  • 调整新的 task_struct 的部分属性
  • task_struct 连入到进程列表中 子进程已经创建

父子进程都已经运行了,代码是只读共享的,各自进行了 return id; 语句的执行,所以有两个返回值

3. 一个变量,怎么会有不同的值?

(1)进行需要独立性

(2)它是怎么做到的 (to be continued)

fork 之后,谁先运行,由OS的调度器自主决定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156284.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

串的存储实现方法(与链表相关)

一、 定义 字符串是由零个&#xff08;空串&#xff09;或多个字符组成的有限序列。 eg:S"Hello World!" 串相等&#xff1a;两个串长度相等并且对应位置的字符都相等时&#xff0c;两个串才相等。 二、串的存储实现 2.1 定长顺序串 2.2 堆串 和定长顺序串的…

【速成Redis】01 Redis简介及windows上如何安装redis

前言&#xff1a; 适用于&#xff1a;需要快速掌握redis技能的人&#xff08;比如我&#xff09;&#xff0c;在b站&#xff0c;找了个课看。 01.课程简介_哔哩哔哩_bilibili01.课程简介是【GeekHour】一小时Redis教程的第1集视频&#xff0c;该合集共计19集&#xff0c;视频…

乐橙云平台接入SVMSPro平台

乐橙云平台接入SVMSPro平台 步骤一&#xff1a;进入乐橙开放平台&#xff1a;https://open.imoulife.com/ &#xff0c;点右上角的登陆&#xff0c;填写自己的用户名密码&#xff0c;进入控制台&#xff1b; 步骤二&#xff1a;登陆进去后&#xff0c;我的应用—>应用信息&a…

Fyne ( go跨平台GUI )中文文档- 架构 (八)完结

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

Java集合HashSet——HashSet在底层原理

可点击此处&#xff1a;HashSet在底层原理 创建一个默认长度16&#xff0c;默认加载因子为0.75的数组&#xff0c;数组名table 16*0.75 12&#xff0c;如果存入的数据达到12&#xff0c;则数组自动扩容为原来的2倍 根据元素的哈希值跟数组的长度计算出应存入的位置 int index…

JAVA基础:正则表达式,String的intern方法,StringBuilder可变字符串特点与应用,+连接字符串特点

1 String中的常用方法2 1.1 split方法 将字符串按照指定的内容进行分割&#xff0c;将分割成的每一个子部分组成一个数组 分割内容不会出现在数组中 实际上该方法不是按照指定的简单的符号进行分割的&#xff0c;而是按照正则表达式进行分割 1.2 正则表达式 用简单的符号组合…

思维商业篇(4)—产业上下游定

思维商业篇(4)—产业上下游定位(微笑曲线) 产业上下游定位&#xff0c;帮助我们去观察一个企业在产业上下游中处于一个什么样的生态位。 上游 处于产业链开始端&#xff0c;百川东到海&#xff0c;百川的的起始端就是上游&#xff0c;东到海的海就是下游。 处在上游的企业一…

用友网络交付总监刘伟伟受邀为第四届中国项目经理大会演讲嘉宾

全国项目经理专业人士年度盛会 用友网络科技股份有限公司区域交付总监刘伟伟先生受邀为PMO评论主办的全国项目经理专业人士年度盛会——2024第四届中国项目经理大会演讲嘉宾&#xff0c;演讲议题为“如何有效提升项目经理领导力”。大会将于10月26-27日在北京举办&#xff0c;主…

UE学习篇ContentExample解读-----------Blueprint_Overview

文章目录 总览描述批次阅览1.1 Blueprint- Hello World1.2 Blueprint- Components1.3 Blueprint- Variables1.4 Blueprint- ConstructionScript1.5 Blueprint- Event Graph1.6 Blueprint- Simple Math1.7 Blueprint- Flow Control 概念总结致谢&#xff1a; 总览描述 打开关卡后…

机械设计中倒角与倒圆角

我们常说&#xff0c;机械设计要做到“一切尽在掌握中”。 包含两层意思&#xff1a;一是所有的结构细节都是仔细思考过并且完整表达&#xff0c;不能靠在制造过程中猜测设计意图、由制造人员再设计或自由发挥。 二是所有的设计都是有根据的&#xff0c;不能靠拍脑袋任意发挥…

【路径规划】自动泊车的 Simulink 模型

摘要 本文介绍了一个用于自主机器人路径规划和导航的 Simulink 模型&#xff0c;该模型结合了路径跟踪算法&#xff08;如 Pure Pursuit&#xff09;和动态机器人模型&#xff0c;实现了复杂环境中的路径跟随和导航控制。实验结果表明&#xff0c;模型能够在给定路径上精确控制…

【neo4j】neo4j和Cypher 查询语言相关知识点

【neo4j】neo4j和Cypher 查询语言相关知识点 1.什么是neo4j Neo4j 是一个广泛使用的图形数据库管理系统&#xff08;Graph Database Management System&#xff09;。它是一种NoSQL数据库&#xff0c;专为存储和查询图形数据而设计。Neo4j 支持图形数据模型&#xff0c;允许用…

误差评估,均方误差、均方根误差、标准差、方差

均方根误差 RMSE/RMS 定义 RMSE是观察值与真实值偏差的平方&#xff0c;对于一组观测值 y i y_i yi​ 和对应的真值 t i t_i ti​ R M S E 1 n ∑ i 1 n ( y i − t i ) &#xff0c;其中n是观测次数 RMSE\sqrt{\frac1n \sum_{i1}^n (y_i-t_i)} \text{&#xff0c;其中n是…

Python|OpenCV-实现识别目标图像中的圆圈(20)

前言 本文是该专栏的第22篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在处理图像检测项目的时候,可能会遇到需要检测目标图像中的“圆圈”需求。笔者在这里举个例子,如下图所示: 在图中有一个篮球,但是我们要找的目标对象并不是篮球,而是篮球它本身的这个…

智能BI平台项目

1.项目介绍 BI商业智能&#xff1a;数据可视化、报表可视化系统 4&#xff09;发布订阅 Resource 是基于名称进行查找的&#xff0c;而Spring框架中更常用的 Autowired 则是基于类型进行查找的。如果找不到匹配的bean&#xff0c;Autowired 会抛出异常&#xff0c;而 Resource…

java项目之基于spring boot的多维分类的知识管理系统的设计与实现源码

项目简介 基于spring boot的多维分类的知识管理系统的设计与实现实现了以下功能&#xff1a; 基于spring boot的多维分类的知识管理系统的设计与实现的主要使用者管理员可以管理用户信息&#xff0c;知识分类&#xff0c;知识信息等&#xff0c;用户可以查看和下载管理员发布…

如何创建标准操作规程(SOP)[+模板]

创建、分发和管理流程文档和逐步说明的能力是确定企业成功的关键因素。许多组织依赖标准操作规程&#xff08;SOP&#xff09;作为基本形式的文档&#xff0c;指导他们的工作流程操作。 然而&#xff0c;SOP不仅仅是操作路线图&#xff1b;它们就像高性能车辆中的先进GPS系统一…

01_RabbitMQ安装及工作模式

一、消息队列MQ 中间件 1.1 什么是消息队列 消息&#xff08;Message&#xff09;是指在应用间传送的数据。消息可以非常简单&#xff0c;比如只包含文本字符串&#xff0c;也可以更复杂&#xff0c;可能包含嵌入对象。 消息队列&#xff08;Message Queue&#xff09;是一…

5.工欲善其事,必先利其器!收集金融数据你必须先做这个!

在正式从网络上获取数据并存储到我们的数据库之前&#xff0c;我们还需要做一些准备工作。其中最重要的无疑是把Python环境配置好。 你可以不好好学习Python&#xff0c;毕竟我后边会一步步教大家&#xff0c;也会提供现成的Python脚本。但是你必须得在你的电脑上把Python安装…

YOLOv10改进,YOLOv10替换主干网络为PP-HGNetV2(百度飞桨视觉团队自研,独家手把手教程,助力涨点)

摘要 PP-HGNetV2(High Performance GPU Network V2) 是百度飞桨视觉团队自研的 PP-HGNet 的下一代版本,其在 PP-HGNet 的基础上,做了进一步优化和改进,最终在 NVIDIA GPU 设备上,将 “Accuracy-Latency Balance” 做到了极致,精度大幅超过了其他同样推理速度的模型。其在…