Linux 多进程编程详解
Linux 多进程编程详解
多进程编程是现代操作系统中一种重要的并发编程技术。通过在同一程序中运行多个独立的进程,可以实现并发处理,充分利用多核处理器的优势,提高程序的运行效率。本文将详细介绍Linux多进程的基本概念、创建方法、进程间通信、同步机制以及实际应用,配以C++示例代码,帮助读者深入理解和掌握多进程编程技术。
1. 多进程的基本概念
在Linux操作系统中,进程是程序的一个实例,是系统进行资源分配和调度的基本单位。每个进程都有独立的地址空间和资源,包括代码段、数据段、堆、栈以及文件描述符等。进程之间通过进程间通信(IPC)机制进行通信和同步。多进程编程就是在同一程序中创建并运行多个进程,以实现并发处理。
1.1 进程的生命周期
进程的生命周期包括以下几个状态:
创建(New):进程被创建,但尚未准备好执行。
就绪(Ready):进程已准备好执行,但尚未被分配CPU时间。
运行(Running):进程正在执行。
阻塞(Blocked):进程正在等待某些事件(如I/O操作)发生。
终止(Terminated):进程已完成执行或被终止。
进程的状态转换如下图所示:
+-------------------+| 创建 (New) |+-------------------+|v+-------------------+| 就绪 (Ready) |+-------------------+|v+-------------------+| 运行 (Running)|+-------------------+|v+-------------------+| 阻塞 (Blocked) |+-------------------+|v+-------------------+| 终止 (Terminated)|+-------------------+
进程由操作系统调度,从创建到就绪,再从就绪状态转移到运行状态。如果进程在运行过程中需要等待某些事件(如I/O操作),则会进入阻塞状态。当等待的事件发生时,进程重新进入就绪状态,等待调度运行。当进程完成任务或被终止时,进入终止状态。
1.2 进程控制块(PCB)
进程控制块(PCB,Process Control Block)是操作系统管理进程的主要数据结构,包含了进程的各种信息,包括:
进程标识符(PID):每个进程都有一个唯一的标识符。
进程状态:表示进程当前的状态(创建、就绪、运行、阻塞、终止)。
程序计数器(PC):保存进程下一条将要执行的指令地址。
寄存器:保存进程的上下文信息。
内存管理信息:包括进程的地址空间、页表等信息。
I/O状态信息:包括打开的文件描述符、I/O设备等信息。
PCB是操作系统进行进程切换和调度的重要依据。
2. 进程的创建
在Linux中,可以通过fork()系统调用创建一个新的进程。fork()会创建一个子进程,该子进程是父进程的副本,继承了父进程的所有资源和上下文。子进程有自己独立的地址空间,父子进程可以并发运行。
2.1 fork()系统调用
fork()系统调用的原型如下:
pid_t fork(void);
fork()返回两次,一次在父进程中返回子进程的PID,一次在子进程中返回0。如果fork()失败,则返回-1:
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork(); // 创建一个子进程if (pid < 0) {// fork失败std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程std::cout << "Hello from Child Process!" << std::endl;std::cout << "Child Process ID: " << getpid() << std::endl;std::cout << "Parent Process ID: " << getppid() << std::endl;} else {// 父进程std::cout << "Hello from Parent Process!" << std::endl;std::cout << "Parent Process ID: " << getpid() << std::endl;std::cout << "Child Process ID: " << pid << std::endl;// 等待子进程结束int status;waitpid(pid, &status, 0);if (WIFEXITED(status)) {std::cout << "Child process exited with status: " << WEXITSTATUS(status) << std::endl;}}return 0;
}
在上述代码中,fork()创建了一个子进程。父进程和子进程分别打印各自的PID和相关信息,并通过waitpid()等待子进程结束。
2.2 进程的终止
进程在完成任务后会终止,终止进程可以通过exit()系统调用实现。exit()系统调用的原型如下:
void exit(int status);
其中,status是进程的退出状态码,通常为0表示正常退出,非0表示异常退出。
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdlib>int main() {pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程std::cout << "Hello from Child Process!" << std::endl;std::cout << "Child Process ID: " << getpid() << std::endl;std::cout << "Parent Process ID: " << getppid() << std::endl;exit(0); // 子进程正常退出} else {// 父进程std::cout << "Hello from Parent Process!" << std::endl;std::cout << "Parent Process ID: " << getpid() << std::endl;std::cout << "Child Process ID: " << pid << std::endl;// 等待子进程结束int status;waitpid(pid, &status, 0);if (WIFEXITED(status)) {std::cout << "Child process exited with status: " << WEXITSTATUS(status) << std::endl;}}return 0;
}
3. 进程间通信
进程间通信(IPC)是多进程编程中的重要部分,用于在独立的进程之间传递数据和信息。常见的IPC机制包括管道、消息队列、共享内存和信号等。
3.1 管道(Pipe)
管道是一种半双工的通信机制,只能在父子进程或兄弟进程之间使用。管道由两个文件描述符组成,一个用于读端,一个用于写端。使用pipe()系统调用创建管道。
#include <iostream>
#include <unistd.h>
#include <cstring>int main() {int fd[2];if (pipe(fd) == -1) {std::cerr << "Pipe failed!" << std::endl;return 1;}pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程close(fd[0]); // 关闭读端const char* msg = "Hello from Child Process!";write(fd[1], msg, strlen(msg) + 1); // 写入管道close(fd[1]); // 关闭写端} else {// 父进程close(fd[1]); // 关闭写端char buffer[100];read(fd[0], buffer, sizeof(buffer)); // 从管道读取std::cout << "Parent Process received: " << buffer << std::endl;close(fd[0]); // 关闭读端}return 0;
}
在上述代码中,父子进程通过管道实现通信。子进程将消息写入管道,父进程从管道读取消息。
3.2 消息队列(Message Queue)
消息队列是一种消息传递机制,允许进程以消息的形式进行通信。消息队列是一个链表,每个消息包含一个消息类型和消息数据。使用msgget()、msgsnd()和msgrcv()系统调用管理消息队列。
#include <iostream>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <cstring>struct message {long msg_type;char msg_text[100];
};int main() {key_t key = ftok("progfile", 65); // 生成唯一键int msgid = msgget(key, 0666 | IPC_CREAT); // 创建消息队列message msg;msg.msg_type = 1;strcpy(msg.msg_text, "Hello from Child Process!");pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程,发送消息msgsnd(msgid, &msg, sizeof(msg.msg_text), 0);std::cout << "Message sent from Child Process." << std::endl;} else {// 父进程,接收消息msgrcv(msgid, &msg, sizeof(msg.msg_text), 1, 0);std::cout << "Parent Process received: " << msg.msg_text << std::endl;// 删除消息队列msgctl(msgid, IPC_RMID, NULL);}return 0;
}
在上述代码中,父子进程通过消息队列实现通信。子进程发送消息,父进程接收消息。
共享内存(Shared Memory)
共享内存是一种高效的进程间通信机制,允许多个进程共享一块内存区域。使用 shmget()、shmat() 和 shmdt() 系统调用管理共享内存。
共享内存是所有 IPC 机制中最快的一种,因为进程可以直接访问内存中的数据,而不需要通过内核中介。但是,这也意味着需要额外的同步机制来确保多个进程不会同时修改共享数据而导致数据不一致。
#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>int main() {key_t key = ftok("shmfile", 65); // 生成唯一键int shmid = shmget(key, 1024, 0666 | IPC_CREAT); // 创建共享内存pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;} else if (pid == 0) {// 子进程,写入共享内存char* str = (char*) shmat(shmid
好了,今天的分享到这里就结束了,感谢大家的支持!
相关文章:
Linux 多进程编程详解
Linux 多进程编程详解 多进程编程是现代操作系统中一种重要的并发编程技术。通过在同一程序中运行多个独立的进程,可以实现并发处理,充分利用多核处理器的优势,提高程序的运行效率。本文将详细介绍Linux多进程的基本概念、创建方法、进程间通…...

C语言之大小端理解
目录 1前言2 大小端理解与区分3 大小端的识别和基本切换操作4 总结 1前言 在汽车CAN通讯报文中往往会接触到Intel类型和motorola类型,实际项目中涉及到多机通讯也会接触到大小端问题 2 大小端理解与区分 大端(Big_Endian) :低字节放在高地址小端(Little_Endian):…...
GIT相关操作,推送本地分支到远程仓库流程记录学习
git流程 切换到源文件夹:cd 源文件夹克隆远程仓库:git clone [ssh]进入项目文件夹:cd .\project\查看本地分支:git branch获取远程仓库更新,使远程同步:git fetch查看所有分支(包括远程分支&am…...

网络协议 — Keepalived 高可用方案
目录 文章目录 目录Keepalived 是实现了 VRRP 协议的软件Keepalived 的软件架构VRRP StackCheckersKeepalived 的配置Global configurationvrrp_scriptVRRP Configurationvrrp synchroization groupvrrp instancevirtual ip addressesvirtual routesLVS Configurationvirtual_s…...

前端报错adding CSS “touch-action: none“ to this element解决方案
目录 如图所示控制台出现报错: 原因: touch-action 介绍: 解决方案: 1.手动设置touch-action: 2.使用条件渲染: 3.CSS样式隔离: 4.浏览器兼容性: 5. 忽略警告 如图所示控制台…...

使用phpMyAdmin操作MYSQL(四)
一. 学会phpMyAdmin? phpMyAdminhttp://water.ve-techsz.cn/phpmyadmin/ 虽然我我们可以用命令行操作数据库,但这样难免没有那么直观,方便。所以接下来我们使用phpMyAdmin来操作MySQL,phpMyAdmin是众多MySQL图形化管理工具中使用…...
webpack配置代理请求
在 Webpack 中,可以通过配置devServer中的proxy选项来设置代理请求,以解决开发环境中的跨域问题或实现特定的请求转发逻辑。以下是一个常见的 Webpack 配置示例,展示了如何设置代理: module.exports {// 其他配置项...devServer…...

热门软件缺陷管理工具2024:专业评测与建议
国内外主流的10款软件缺陷管理工具软件对比:PingCode、Worktile、禅道、Tapd、Teambition、Tower、JIRA、Bugzilla、MantisBT、Trac。 在软件开发过程中,管理缺陷和漏洞常常成为一项挑战,尤其是在项目规模庞大时。选择一个高效的软件缺陷管理…...

冒泡,选择,插入,希尔排序
目录 一. 冒泡排序 1. 算法思想 2. 时间复杂度与空间复杂度 3. 代码实现 二. 选择排序 1. 算法思想 2. 时间复杂度与空间复杂度 3. 代码实现 三.插入排序 1. 直接插入排序 (1). 算法思想 (2). 时间复杂度与空间复杂度 (3). 代码实现 2. 希尔排序 (1). 算法思想 …...

【HarmonyOS学习】Calendar Kit日历管理
简介 Calendar Kit提供日历与日程管理能力,包括日历的获取和日程的创建能力。 Calendar Kit为用户提供了一系列接口来获取日历账户,并使用特定的接口向日历账户中写入日程。 如果写入的日程带有提醒时间则系统会在时间到达时向用户发送提醒。 约束点…...

RDMA 高性能架构基本原理与设计方案
RDMA的主要优点包括低延迟、高吞吐量、减少CPU负担和支持零拷贝网络。它允许数据直接在网络接口卡(NIC)和内存之间传输,减少了数据传输过程中的中间环节,从而显著降低了延迟。RDMA技术能够实现高速的数据传输,适用于需…...
【Springboot】事件机制发布与订阅的使用实践
文章目录 为什么要使用事件监听机制概念和原理使用场景用户注册系统实践案例1. 创建事件类2. 发布事件3. 监听事件3.1 通过注解EventListener实现监听3.2 通过实现ApplicationListener接口实现监听 4. 测试事件机制 总结 为什么要使用事件监听机制 在Springboot中,…...

新版网页无插件H.265播放器EasyPlayer.js如何测试demo视频?
H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,支持H.264与H.265编码格式,性能稳定、播放流畅;支持WebSocket-FLV、HTTP-FLV,HLS(m3u8࿰…...

PXE、Kickstart和cobbler
一.系统装机 1.1 三种引导方式 启动操作系统 1.硬盘 2.光驱(u盘) 3.网络启动 pxe 1.2 系统安装过程 1.加载boot loader: Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设 备、建立内存空间的映射图,从而将系统的软硬…...
【GameFramework扩展应用】6-3、GameFramework框架增加日志保存功能
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录: https://blog.csdn.net/q764424567/article/details/1…...
将独热码应用到神经网络中
引言 接上回,本文继续说如何用TensorFlow将独热编码应用到一个简单的神经网络中,以实现从一段随机文本到另一段随机文本的转换。 步骤一:导入库 import tensorflow as tf import numpy as np import random import string步骤二࿱…...
在CSS中,使用Flexbox布局时,可以通过几个属性来控制容器内的项目之间的间距
display弹性布局,flex:1是占据剩下的空间 关于displa:flex /* 水平和垂直居中,水平和垂直方向上的间距均匀分布 / .container { display: flex; justify-content: space-between; / 左右对齐 / align-items: center; / 上下间距 */ flex-direction: ro…...
关于HDFS 和HBase
Apache HBase 被设计为在 Hadoop 分布式文件系统 (HDFS) 上运行的一个特殊类型的数据库。大白话: 想象一下,你有一个巨大的图书馆,这个图书馆就像 HDFS,它的架子上堆满了各种各样的书籍,每本书都非常厚,而…...

【HarmonyOS】HarmonyOS NEXT学习日记:二、ArkTs语法
【HarmonyOS】HarmonyOS NEXT学习日记:二、ArkTs语法 众所周知TS是JS的超集,而ArkTs则可以理解为是Ts的超集。他们的基础都基于JS,所以学习之前最好就JS基础。我的学习重点也是放在ArkTs和JS的不同点上。 文章主要跟着官方文档学习,跳过了一…...
Web前端-Web开发CSS基础2-选择器
一. 基础 1. 选中所有的<p>标签; 2. 选中所有的<ol>标签; 3. 选中所有的<ul>标签; 4. 选中所有id为happy的标签; 5. 选中所有id为sad的标签; 6. 选中所有id为angry的标签; 7. 选中所有类…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

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

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...