【Linux操作系统】深入探索Linux进程:创建、共享与管理
进程的创建是Linux系统编程中的重要概念之一。在本节中,我们将介绍进程的创建、获取进程ID和父进程ID、进程共享、exec函数族、wait和waitpid等相关内容。
文章目录
- 1. 进程的创建
- 1.1 函数原型和返回值
- 1.2 函数示例
- 2. 获取进程ID和父进程ID
- 2.1 函数原型和返回值
- 2.2 函数示例
- 3. exec函数族
- 3.1 `exec()`函数族的常见成员:
- 3.2 函数示例
- 4. wait和waitpid
- 4.1 函数解释
- 4.2 函数示例
- 总结
1. 进程的创建
在Linux系统中,进程的创建使用fork()
系统调用。fork()
系统调用会创建一个与当前进程相同的子进程,子进程会复制父进程的所有资源,包括代码、数据和文件描述符等。
1.1 函数原型和返回值
fork()
函数的原型如下:
#include <unistd.h>pid_t fork(void);
fork()
函数 没有任何参数 ,它的返回值是一个pid_t
类型的整数。具体解释如下:
- 如果调用成功,
fork()
函数会在父进程中返回子进程的PID(子进程ID),在子进程中返回0。 - 如果调用失败,
fork()
函数会返回-1,并设置errno
来指示错误类型。
1.2 函数示例
代码示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid == -1) {printf("Failed to fork a new process.\n");return 1;} else if (pid == 0) {printf("This is the child process.\n");} else {printf("This is the parent process.\n");}return 0;
}
上述代码中,fork()
系统调用会返回两次,分别在父进程和子进程中返回。通过判断返回值,我们可以区分父进程和子进程,并执行不同的代码逻辑。
2. 获取进程ID和父进程ID
在Linux系统中,可以使用getpid()
和getppid()
系统调用来获取当前进程的ID和父进程的ID。
2.1 函数原型和返回值
getpid()
和getppid()
函数的原型如下:
#include <sys/types.h>
#include <unistd.h>pid_t getpid(void);
pid_t getppid(void);
这两个函数都 没有任何参数 ,它们的返回值都是一个pid_t
类型的整数。具体解释如下:
getpid()
函数返回调用进程的进程ID(PID)。getppid()
函数返回调用进程的父进程的进程ID(PPID)。
2.2 函数示例
代码示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main() {pid_t pid = getpid();pid_t ppid = getppid();printf("Process ID: %d\n", pid);printf("Parent Process ID: %d\n", ppid);return 0;
}
3. exec函数族
在Linux系统中,exec()
函数族可以用于将当前进程替换为新的程序。exec()
函数族包括execl()
、execv()
、execle()
、execve()
等函数。这些函数可以根据不同的参数形式来执行不同的替换方式。
3.1 exec()
函数族的常见成员:
-
int execl(const char *path, const char *arg, ...);
- 参数
path
是要执行的新程序的路径。 - 参数
arg
是一个字符串,表示新程序的第一个参数。 - 可变参数列表是新程序的其他参数,必须以
NULL
结束。 - 函数执行成功时不会返回,如果返回则表示执行失败。
- 参数
-
int execv(const char *path, char *const argv[]);
- 参数
path
是要执行的新程序的路径。 - 参数
argv
是一个字符串数组,表示新程序的参数列表,最后一个元素必须是NULL
。 - 函数执行成功时不会返回,如果返回则表示执行失败。
- 参数
-
int execle(const char *path, const char *arg, ..., char *const envp[]);
- 参数
path
是要执行的新程序的路径。 - 参数
arg
是一个字符串,表示新程序的第一个参数。 - 可变参数列表是新程序的其他参数,必须以
NULL
结束。 - 参数
envp
是一个字符串数组,表示新程序的环境变量列表,最后一个元素必须是NULL
。 - 函数执行成功时不会返回,如果返回则表示执行失败。
- 参数
-
int execvp(const char *file, char *const argv[]);
- 参数
file
是要执行的新程序的文件名。 - 参数
argv
是一个字符串数组,表示新程序的参数列表,最后一个元素必须是NULL
。 - 函数执行成功时不会返回,如果返回则表示执行失败。
- 参数
这些函数在执行成功时不会返回,而是直接将当前进程替换为新程序。如果返回,则表示执行失败,可以根据返回值来判断错误类型。
exec()
函数族可以用于在当前进程中加载和执行新程序,可以实现程序的动态切换和功能扩展。一般情况下,exec()
函数族会在调用fork()
函数创建子进程后使用,以替换子进程的代码和数据。
3.2 函数示例
代码示例如下:
#include <stdio.h>
#include <unistd.h>int main() {printf("Before exec()\n");execl("/bin/ls", "ls", "-l", NULL);printf("After exec()\n");return 0;
}
上述代码中,execl()
函数会将当前进程替换为ls -l
命令。execl()
函数的第一个参数是要执行的程序路径,后续参数是传递给新程序的命令行参数。
4. wait和waitpid
在Linux系统中,父进程可以使用wait()
或waitpid()
系统调用等待子进程的结束。这些系统调用会阻塞父进程的执行,直到子进程结束。
4.1 函数解释
wait()
和waitpid()
是用于等待子进程结束并获取子进程的退出状态的函数。
-
pid_t wait(int *status);
- 函数会挂起当前进程,直到一个子进程结束。
- 如果成功等到子进程结束,函数会返回子进程的进程ID。
- 参数
status
是一个指向整型的指针,用于存储子进程的退出状态信息。 - 如果调用失败,函数会返回-1。
-
pid_t waitpid(pid_t pid, int *status, int options);
- 函数会挂起当前进程,直到指定的子进程结束。
- 参数
pid
指定要等待的子进程的进程ID。 - 参数
status
是一个指向整型的指针,用于存储子进程的退出状态信息。 - 参数
options
是一个整型值,用于指定等待的选项。 - 如果调用失败,函数会返回-1。
wait()
和waitpid()
函数的返回值是子进程的进程ID,如果调用失败,则返回-1。通过参数 status
可以获取子进程的退出状态信息,包括退出码、终止信号等。
waitpid()
函数相比于wait()
函数更加灵活,可以通过参数 pid
和 options
控制等待的子进程。
其中,pid
的取值可以是:
-1
:等待任意子进程。0
:等待与当前进程组ID相同的子进程。- 具体的子进程ID:等待指定的子进程。
options
参数可以通过位掩码的方式指定多个选项,常用的选项有:
WNOHANG
:非阻塞方式,如果没有子进程结束,立即返回。WUNTRACED
:也会返回已经停止的子进程的状态。WCONTINUED
:也会返回已经继续运行的子进程的状态。
wait()
和waitpid()
函数可以用于处理子进程的退出状态,释放子进程的资源,并进行进程间的同步。在使用这两个函数时,需要注意处理错误情况和避免僵尸进程的产生。
4.2 函数示例
代码示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>int main() {pid_t pid = fork();if (pid == -1) {printf("Failed to fork a new process.\n");return 1;} else if (pid == 0) {printf("This is the child process.\n");} else {wait(NULL);printf("This is the parent process.\n");}return 0;
}
上述代码中,父进程使用wait(NULL)
系统调用等待子进程的结束。wait()
系统调用会阻塞父进程的执行,直到子进程结束。
总结
fork()
函数:用于创建子进程,返回值不同表示在不同的进程中执行。exec()
函数族:用于在当前进程中加载和执行新程序,可以实现程序的动态切换和功能扩展。execl()
:接受可变参数的形式,参数以字符串形式传递。execle()
:接受可变参数的形式,同时传递环境变量。execvp()
:接受参数数组的形式,参数以字符串数组形式传递。
wait()
和waitpid()
函数:用于等待子进程结束并获取子进程的退出状态。wait()
:等待任意子进程结束。waitpid()
:可以指定等待的子进程。- 通过参数
status
可以获取子进程的退出状态信息。 - 可以通过
options
参数控制等待的选项,如非阻塞方式等。 - 需要注意处理错误情况和避免僵尸进程的产生。
这些函数和系统调用可以用于进程的创建、执行和等待,实现进程间的同步和协作。通过这些函数,可以实现进程的动态切换、功能扩展和资源释放。同时,需要注意处理错误情况,避免产生僵尸进程和资源泄漏的问题。
相关文章:

【Linux操作系统】深入探索Linux进程:创建、共享与管理
进程的创建是Linux系统编程中的重要概念之一。在本节中,我们将介绍进程的创建、获取进程ID和父进程ID、进程共享、exec函数族、wait和waitpid等相关内容。 文章目录 1. 进程的创建1.1 函数原型和返回值1.2 函数示例 2. 获取进程ID和父进程ID2.1 函数原型和返回值2.…...

【云原生、k8s】Calico网络策略
第四阶段 时 间:2023年8月17日 参加人:全班人员 内 容: Calico网络策略 目录 一、前提配置 二、Calico网络策略基础 1、创建服务 2、启用网络隔离 3、测试网络隔离 4、允许通过网络策略进行访问 三、Calico网络策略进阶 1、创…...
Unity3D 测试总结
windows 平台上导出 exe 文件 在Unity界面中,点击菜单栏的“File”,选择“Build Settings”。 在“Build Settings”窗口中,选择要生成的平台(例如Windows)。 点击“Player Settings”按钮,进入“Player Se…...

【无线点对点网络时延分析和可视化】模拟无线点对点网络中的延迟以及物理层和数据链路层之间的相互作用(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

在思科(Cisco)路由器中使用 SNMP
什么是SNMP SNMP,称为简单网络管理协议,被发现可以解决具有复杂网络设备的复杂网络环境,SNMP 使用标准化协议来查询网络上的设备,为网络管理员提供保持网络环境稳定和远离停机所需的重要信息。 为什么要在思科设备中启用SNMP S…...
【压测】wg/wrk 轻量级压测
wg/wrk 轻量级压测 说明:环境是 centos,不过现在 centos 免费版本不再更新和维护了,所以大家可以用阿里云的或者用 ubuntu 内核 用的 https://github.com/wg/wrk.git 有 35k star 然后据我了解,windows 用 wrk 压测有点麻烦&…...
Redis可以用作消息队列吗?如何实现简单的消息队列功能?
是的,Redis可以被用作简单的消息队列。下面是一种实现简单消息队列功能的方式: 生产者(Producer)端: 使用LPUSH命令将消息推送到一个列表中,作为消息队列的实现。例如,使用LPUSH命令将消息推送到…...
[Java基础]对象转型
系列文章目录 【Java基础】Java总览_小王师傅66的博客-CSDN博客 [Java基础]基本概念(上)(标识符,关键字,基本数据类型)_小王师傅66的博客-CSDN博客 [Java基础]基本概念(下)运算符,表达式和语句,分支,循环,方法,变量的作用域,递归调用_小王师傅66的博客-CSDN博客 Java字节码…...

JVM——类文件结构
文章目录 一 概述二 Class 文件结构总结2.1 魔数2.2 Class 文件版本2.3 常量池2.4 访问标志2.5 当前类索引,父类索引与接口索引集合2.6 字段表集合2.7 方法表集合2.8 属性表集合 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class …...

银河麒麟服务器v10 sp1 .Net6.0 上传文件错误
上一篇:银河麒麟服务器v10 sp1 部署.Net6.0 http https_csdn_aspnet的博客-CSDN博客 .NET 6之前,在Linux服务器上安装 libgdiplus 即可解决,libgdiplus是System.Drawing.Common原生端跨平台实现的主要提供者,是开源mono项目。地址…...
C#实现普通的语音播报
Windows有文字转语音功能,C#提供了调用的类库Interop.SpeechLib.dll 使用方法很简单,在你的项目中添加Interop.SpeechLib.dll引用,在类中引用: using SpeechLib;这里提供一个CVoice类 帮助实现语音播报 public class CVoice{pri…...
django中实现事务的几种方式
1.实现事务的三种方式 1.1 全局开启事务---> 全局开启事务,绑定的是http请求响应整个过程 DATABASES {default: {#全局开启事务,绑定的是http请求响应整个过程ATOMIC_REQUESTS: True, }} from django.db import transaction# 局部禁用事务 transac…...
【es6】具名组匹配
1、组匹配 正则表达式使用圆括号进行组匹配,如:const RE_DATE /(\d{4})-(\d{2})-(\d{2})/;,三个圆括号形成了三个组匹配。 代码: const RE_DATE /(\d{4})-(\d{2})-(\d{2})/;const matchObj RE_DATE.exec(1999-12-31); const year matchO…...

自然语言处理技术:NLP句法解析树与可视化方法
自然语言处理(Natural Language Processing,NLP)句法解析树是一种表示自然语言句子结构的图形化方式。它帮助将句子中的每个词汇和短语按照语法规则连接起来,形成一个树状结构,以便更好地理解句子的语法结构和含义。句法解析树对于理解句子的句法关系、依存关系以及语义角…...
flinksql报错 Cannot determine simple type name “org“
flink版本 1.15 报错内容 2023-08-17 15:46:02 java.lang.RuntimeException: Could not instantiate generated class WatermarkGenerator$0at org.apache.flink.table.runtime.generated.GeneratedClass.newInstance(GeneratedClass.java:74)at org.apache.flink.table.runt…...
e.target.value和 binding.value 区别
e.target.value 和 binding.value 都是在 Vue.js 中用于处理事件绑定时的值,但它们的使用场景和含义有所不同,分别用于普通的 DOM 事件和自定义指令。 e.target.value: 这是常用于原生 DOM 事件处理函数中的一个属性,用于获取事件…...
软链接与exec进程替换运行路径问题
目录 1. 代码(1)启动进程execvp(2)替换的新进程new_proc 2. 验证(1)new_proc与execvp源文件同一目录(2)new_proc与execvp软链接同一目录 3. 总结4. errno.h 用execvp软链接启动进程&…...

【Go】锁相关
文章目录 Mutex锁mutex源码分析LockUnLock mutex两种运行模式mutex normal 正常模式自旋 mutex starvation 饥饿模式 锁的底层实现类型 RWMutexRWMutex 实现其他共享内存线程安全的方式 思考如何设计一个并发更高的锁? Mutex锁 mutex源码分析 Locker接口ÿ…...

git环境超详细配置说明
一,简介 在git工具安装完成之后,需要设置一下常用的配置,如邮箱,缩写,以及git commit模板等等。本文就来详细介绍些各个配置如何操作,供参考。 二,配置步骤 2.1 查看当前git的配置 git conf…...
使用阿里云服务器搭建PostgreSQL主从架构图文流程
阿里云百科分享使用阿里云服务器搭建PostgreSQL主从架构图文流程,PostgreSQL被业界誉为最先进的开源数据库,支持NoSQL数据类型(JSON/XML/hstore)。本文档介绍在CentOS 7操作系统的ECS实例上搭建PostgreSQL主从架构的操作步骤。 目…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...