【linux服务器编程学习】9、多进程编程
创始人
2025-05-31 13:28:57

多进程编程

多进程编程主要包括

  • 复制进程映像的fork和替换进程映像的exec系列
  • 进程间通信(IPC)的方式,包括管道、信号量、消息队列、共享内存。

fork

#include
#includepid_t fork(void);

linux下创建一个新进程。

该函数返回两次,在父进程中返回子进程的pid,在子进程中返回0,以此来判断进程是父进程还是子进程。
失败时返回-1并设置errno

fork函数复制当前进程,在内核进程表中创建一个新进程表项,很多属性与父进程相同,比如堆指针、栈指针、标志寄存器的值,但是pid和信号处理都不同了。

子进程的代码和父进程完全相同,还会复制父进程的数据,如堆数据、栈数据、静态数据,打开的文件描述符也是一样的,被引用计数,当父子进程都关闭时才完全关闭文件描述符。

exec系列

在子进程中执行其他程序,即替换当前进程映像,用到exec系列。

int execl(const char *path, const char *arg, ...);int execlp(const char *file, const char *arg, ...);int execle(const char *path, const char *arg, ..., char * const envp[]);int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);path 参数表示你要启动程序的名称包括路径名。arg 参数表示启动程序所带的参数,
一般第一个参数为要执行命令名,
不是带路径且 arg 必须以NULL 结束。返回值:成功返回 0,失败返回 -1。1、带 l 的exec函数:execl、execlp、execle,表示后边的参数以可变参数的形式给出且都以一个空指针结束。
2、带 p 的 exec 函数:execlp、execvp,表示第一个参数 path 不用输入完整路径,只有给出命令名即可,它会在环境变量 PATH 当中查找命令
3、不带 l 的 exec 函数:execv、execvp 表示命令所需的参数以 char *arg[] 形式给出且 arg 最后一个元素必须是 NULL 。
4、带 e 的 exec 函数:execle 表示,将环境变量传递给需要替换的进程

参考:exec系列函数(execl、execlp、execle、execv、execvp)使用

处理僵尸进程

对于多进程,父进程一般需要跟踪子进程的退出状态,当子进程结束运行时,内核不会立即释放其进程表项,让父进程后续对该子进程退出信息查询。在子进程结束运行,父进程读取其退出状态之前,称该子进程处于僵尸态。另一种让子进程处于僵尸态的情况是,父进程结束或异常终止,而子进程继续运行。此时子进程的ppid被设为1,init进程接管该子进程等待它结束。在父进程退出之后,子进程退出之前,子进程处于僵尸态。
处于僵尸态的子进程占据内核资源。要处理僵尸进程,要在父进程中调用以下函数,等待子进程结束并获取子进程的返回信息。

#include
#include
pid_t wait(int* stat_loc);
pid_t waitpid(pid_t pid,int * stat_loc,int options);

wait将阻塞进程,知道进程的某个子进程结束运行为止,返回结束运行子进程的pid,并将退出信息保存在stat_loc中。
waitpid只等待pid参数指定的子进程。如果pid取值为-1就和wait相同。

信号量

当多个进程同时访问系统上的某个资源,需要考虑进程的同步问题,确保任何时候只有一个进程可以拥有对资源的独占式访问。
信号量是一种特殊的变量,他只能取自然数值并且只支持等待和信号两种操作。
等待操作p:如果sv的值大于0就减1,如果为0,则挂起执行
信号操作v:如果进程因为其他等待被挂起,则唤醒,否则sv加1

创建信号量
int semget((key_t)key , int nsems , int flag)key:是一个信号标识,唯一标识一个信号量集,
若多个进程使用同一个信号量集,要求在调用semget方法时的key值相同
nsems:在创建时使用,用来执行创建的信号量集中信号量的个数
flag:指定操作权限,同时可以通过设置IPC_CREAT,来指明本次需要创建的信号量集
返回值:失败返回-1,成功返回内核对象的ID值,用于后续的其他方法改变信号量的值
int	semop(int semid,struct sembuf *buf,int buflength)
semid:semget方法返回的id值。
buf是一个sembuf类型的数组首地址
buflength:数组的元素个数
返回值:成功返回0,失败返回-1struct sembuf{short sem_num;//除非使用一组信号量,否则它为0,对应信号集中的一个信号量short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,//一个是+1,即V(发送信号)操作。short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,//并在进程没有释放该信号量而终止时,操作系统释放信号量直接控制信号量
int semctl(int semid, int sem_num, int cmd, ...);semid指定信号量集
sen_num 信号量集合中的下标,指定对哪个信号量进行操作,一般来说只有一个信号量,也就是为 0
cmd 指定操作类型,一般有如 GETVAL , IPC_RMID, SETVAL, SETVALL 等操作
arg用于设置或返回信号量信息

共享内存

共享内存实现进程间通信,是操作系统在实际物理内存开辟一块空间,一个进程在自己的页表中,将该空间和进程地址空间上的共享区的一块地址空间形成映射关系。另外一进程在页表上,将同一块物理空间和该进程地址空间上的共享区的一块地址空间形成映射关系。

当一个进程往该空间写入内容时,另外一进程访问该空间,会得到写入的值,即实现了进程间的通信。

#include创建共享内存
int shmget(key_t key, size_t size, int shmflg);
key,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名
size以字节为单位指定需要共享的内存容量
shmflg是权限标志,它的作用与open函数的mode参数一样,
如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。函数成功时返回一个与key相关的共享内存标识符(非负整数),
用于后续的共享内存函数。调用失败返回-1.启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
void *shmat(int shm_id, const void *shm_addr, int shmflg);shm_id是由shmget()函数返回的共享内存标识。
shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shm_flg是一组标志位,通常为0。调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.将共享内存从当前进程中分离。
注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
int shmdt(const void *shmaddr)
shmaddr是shmat()函数返回的地址指针,调用成功时返回0,失败时返回-1.用来控制共享内存
int shmctl(int shm_id, int command, struct shmid_ds *buf);
shm_id是shmget()函数返回的共享内存标识符。
command是要采取的操作,它可以取下面的三个值 :IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值IPC_RMID:删除共享内存段
buf是一个结构指针,它指向共享内存模式和访问权限的结构。struct shmid_ds{uid_t shm_perm.uid;uid_t shm_perm.gid;mode_t shm_perm.mode;};

消息队列

消息队列是在两个进程之间传递二进制块数据的一种简单有效的方式。每个数据块都有特定类型,接收方可以根据类型有选择的接收数据。


#include
#include
#include创建和访问一个消息队列
int msgget(key_t key, int msgflg);
key:某个消息队列的名字
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1消息队列的控制函数
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid:由msgget函数返回的消息队列标识码
cmd:是将要采取的动作,(有三个可取值)
返回值:成功返回0,失败返回-1
cmd取值如下:IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值IPC_SET  在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值IPC_RMID 删除消息队列把一条消息添加到消息队列中
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgid:由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备发送的消息,
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
返回值:成功返回0;失败返回-1是从一个消息队列接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgid:由msgget函数返回的消息队列标识码
msgp:是一个指针,指针指向准备接收的消息,
msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
msgtype:它可以实现接收优先级的简单形式
msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事
返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1msgtype=0返回队列第一条信息
msgtype>0返回队列第一条类型等于msgtype的消息 
msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
msgtype>0且msgflg=MSG_EXCEPT,接收类型不等于msgtype的第一条消息。

后记

人生大事,尽心尽力。

相关内容

热门资讯

EL表达式JSTL标签库 EL表达式     EL:Expression Language 表达式语言     ...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
工信部、中汽协紧急发声!汽车“... 文/刘育英新一轮汽车价格战再起。近日,工信部、中汽协纷纷发声表示反对。工业和信息化部表示,将加大对汽...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
募资39亿,全亏光了,账上不到... 关于天然气,用户的感觉是价格一直在上涨,但很奇怪,不管怎么涨,天然气企业仍然亏,还亏得一塌糊涂。这是...
资阳房产评估公司 这是(tel-15828298733)整理的信息,希望能帮助到大家 在当今社会,随着经济的发展和城...
华桥汇利(中国)投资基金管理有... 今年第一季度,美国企业利润出现大幅下降,且面临着来自关税上升的持续压力,这一局面可能会在今年进一步加...
ESG 报告合规与鉴证:全球政... 在当下全球经济格局里,ESG(环境、社会和公司治理)已然成为衡量企业可持续发展能力的关键指标。随着全...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...
与锤巨子生物的大嘴博士持股同一... 医美龙头巨子生物“成分争议”风波持续发酵。日前,美妆博主大嘴博士(香港大学化学博士郝宇)发文,质疑巨...
Linux之进程间通信 目录 进程间通信介绍 一、为什么要进行进程间通信? 二、进程间通信目的 三、进程间通信...
从“造城”到“留客”,文旅局长... 你有没有刷到最近各地文旅局局长全体“尬舞”的视频?领导们放下架子开始跳魔性舞蹈,这场舞的背后啊,可不...
Hazel引擎学习(十一) 我自己维护引擎的github地址在这里,里面加了不少注释,有需要的可以看...
孩子的教育金,分享3个「有效」... 点击 “简七读财” ,发送消息“ 理财小工具 ”免费领取“40个赚钱工具资源包”晚上好,我是简七编...
iZotope RX 10(专... iZotope RX 10是一款专业的音频修复和增强软件,具有音频修复工具、音频增强工...
我的docker随笔40:cl... 本文介绍 clickhouse 数据库的容器化部署。 起因 某项目需生产环境数据库,因...
透视一周牛熊股:最牛股路桥信息... 过去一周(5月26日—5月30日)A股三大指数集体下跌。截至5月30日收盘,上证指数报3347.49...
基于matlab创建地面固定雷... 一、前言此示例演示如何创建和显示包含地面固定雷达、转弯飞机、等速飞机和移动地面车辆的多平台方案。二、...
暗夜发光,独自闪耀,盘点网页暗... 众所周知,网页的暗黑模式可以减少屏幕反射和蓝光辐射,减少眼睛的疲劳感&#...
C语言-程序环境和预处理(2) 文章目录预处理详解1.预定义符号2.#define2.1#define定义的标识符2.2#defin...
MySQL数据库知识整理 MySQL数据库知识整理 MySQL事务详解 事务四大特性ACID 原子性(Atomi...
Docker基础篇——最全讲解 文章目录一、CentOS安装docker二、启动帮助类命令三、镜像命令1.名词概念2.常用命令2.1...
五问“恒大论”,比亚迪回应车圈... “车圈恒大”引发的舆论风暴还在进一步发酵。近日,比亚迪集团品牌及公关处总经理李云飞在微博发文,引用多...
javafx实现聚光灯效果,圆... 系列文章专栏:javafx图形绘制、桌面录屏录音源码合集 目录 一、实现的效果 二、实现思路
300左右哪款蓝牙耳机适合学生... 近年来,随着蓝牙耳机的发展,不管是音质、外观、佩戴还是降噪都有了很大的提...
深蓝汽车5月全系交付25521... 新京报贝壳财经讯 6月1日,深蓝汽车发布的数据显示,今年5月,深蓝汽车全系交付25521辆,同比增长...
react常用hook(一) Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 sta...
docker替换源docker... docker替换源 先看下docker下原有的信息docker info 主要的代码块 Docke...
王胜升任申万宏源研究所总经理 ... 21世纪经济报道记者 孙永乐 上海报道21世纪经济报道记者获悉,近期,上海申银万国证券研究所有限公司...
下周A股多空激辩!AI+应用又... 数据是个宝 数据宝 投资少烦恼 本周(5月26日至30日),A股市场成交规模连续维持在1万亿元以上。...