Linux网络编程2——多进程编程

一.进程

1.概念复习

程序:程序(program)是存放在磁盘文件中的可执行文件
进程:程序的执行实例被称为进程(process)。

  • 进程具有独立的权限与职责。
  • 如果系统中某个进程崩溃,它不会影响到其余的进程。
  • 每个进程运行在其各自的虚拟地址空间中,进程之间可以通过由内核控制的机制相互通讯。

进程ID:每个linux进程都一定有一个唯一的数字标识符,称为进程ID(process ID),进程ID总是一非负整数。

task_struct===》进程表项(进程控制块)

2.main()函数

我们知道:

void main(){}int main()
{return 0;
}

但是main()函数我们或多或少见识过带参数的,比如:

int main(int argc,char *argv[])
{return 0;
}
  • argc:函数内参数的个数,编译器自动计算传入
  • argv:函数内的参数都会被当作字符串类型存储到这里,中间默认用空格分隔

启动例程:

  • 启动例程在main()函数执行之前内核就会启动
  • 在编译时,启动例程代码就会和用户写的代码进行编译链接到可执行文件中
  • 启动例程的作用是收集命令行的参数传递给main()函数的argcargv

3.进程终止方式

正常终止:

  • main函数返回
  • 调用exit(标准c库函数)
  • 调用 _exit_Exit(系统调用)
  • 最后一个线程从其启动例程返回
  • 最后一个线程调用pthread_exit

异常终止:

  • 调用abort
  • 接受到一个信号并终止
  • 最后一个线程对取消请求做处理响应

4.atexit函数

#include <stdlib.h>
int atexit(void (*function)(void))                 //传入自定义终止函数的函数指针//返回: 若成功则为0,若出铅则为-1
//功能: 向内核登记终止函数
  • 每个启动的进程都默认登记了一个标准的终止函数
  • 终止函数在进程终止时释放进程所占用的一些资源
  • 登记的多个终止函数执行顺序是以栈的方式执行,先登记的后执行。

二.进程控制

1.fork()函数

作用:创建一个子进程

在这里插入图片描述

通过fork()创建的子进程类似于父进程的复制版本,fork()以前的代码子进程虽然也有但已不再执行,而fork()后面的代码父子进程分开执行,从而导致有两个返回值,子进程创建成功则返回0,而父进程则返回创建的子进程的pid

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>void term_fun1()
{printf("first term function\n");
}void term_fun2()
{printf("second term function\n");
}int main()
{printf("before fork1\n");printf("before fork2\n");pid_t pid=fork();if(pid<0){perror("fork error\n");exit(1);}else if(pid==0){printf("---child process is created\n");}else if(pid>0){printf("---praent process:my child process is %d\n",pid);}printf("===============================end process\n");
}

结果:

before fork1
before fork2
—praent process:my child process is 10114
===============================end process
—child process is created
===============================end process

先执行父进程,再执行子进程。

2.getpid与getppid

  • getpid:获取自己的pid号
  • getppid:获取父进程的pid号

改一下上面代码:

    if(pid<0){perror("fork error\n");exit(1);}else if(pid==0){printf("---child process is created,my_pid:%d,my_prapid:%d\n",getpid(),getppid());}else if(pid>0){printf("---praent process:my child process is %d,my_pid:%d,my_prapid:%d\n",pid,getpid(),getppid());}

3.循环建立n个进程

问题一:

  • 怎么建立n个?
  • 怎么保证顺序?
int main()
{for(int i=0;i<5;i++){if(fork()==0)break;}if(5==i){sleep(5);printf("I'm parent\n");}else{sleep(i);printf("I'm %dth child\n",i+1);}return 0;
}

三.其他函数

1.exec函数族

fork 创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用 exec 并不创建新进程,所以调用exec前后该进程的 id 并未改变。重点掌握:execlexeclp

execlp

  • 加载一个进程,借助 PATH 环境变量

    int execlp(const char *file, const char *arg, ...);
    
  • 参数 1:要加载的程序的名字。该函数需要配合 PATH 环境变量来使用,当 PATH 中所有目录搜索后没有参数 1(即环境变量中没有对应的程序)则出错返回。

  • 该函数通常用来调用系统程序。如: ls、date、cp、cat 等命令。“

execl

  • 加载一个进程,通过 路径+程序名 来加载。

    int execl(const char *path, const char *arg, ...);
    
  • 对比execlp,如加载"ls"命令带有-1,-F 参数,使用参数1给出的绝对路径搜索。

    execlp("ls","ls","-l","-F",NULL);
    execl("/bin/s","ls","-l","-F",NULL);
    

2.孤儿进程与僵尸进程

  • 孤儿进程:父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程变为init进程,也可以叫init进程领养孤儿进程。

    怎么处理一个孤儿进程:直接kill杀死

  • 僵尸进程:进程终止,父进程尚未回收,子进程残留资源PCB存放在内核中,变成僵尸进程。

    怎么处理一个僵尸进程:kill杀死其父进程,使其变为孤儿进程,init进程发现其是僵尸进程后自动被回收。

  • 守护进程:守护进程运行在后台,不跟任何控制终端关联

    作用:确保运行程序完整执行

3.wait和waitpid

作用:waitpidwait,但可以指定pid进程清理

注意:一次wait/waitpid的函数调用,只能回收一个子进程。

语法:

pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
  • wait函数成功执行返回要终止(回收)子进程的pid;失败则返回-1
  • waitwaitpid里的int *wstatus参数意思是把回收子进程的状态信息存储到int *所指的内存空间里,这里的状态信息是以宏的方式存储
  • options:利用进程发送变换的状态进行回收,一般选择WNOHANG
  • waitpid函数的pid传-1,代表回收任意子进程

代码理解:

wait(NULL);                                //阻塞直至回收任意一个进程
wpid=waitpid(-1,NULL,WNOHANG);             //回收任意子进程,没有结束的子进程,父进程直接返回0
wpid=waitpid(-1,NULL,0);                   //阻塞回收某一子进程

四.进程间通信(未完待续)

同一主机的进程间通信:

  • 管道(Pipe):用于父子进程间通信
  • 命名管道(FIFO):不相关的进程间通信,不适合大量数据传输
  • 消息队列(Message Queue):适用于需要缓冲和异步处理的场景
  • 共享内存(Shared Memory):允许多个进程访问同一块内存区域,适合大数据量传输
  • 信号量(Semaphore):用于控制对共享资源的访问
  • 信号(Signal):用于通知接收进程某个事件已经发生(重点)

不同主机间的进程通信:

  • 服务器与客户端(Socket):网络编程

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker打包镜像

Docker打包镜像 前置工作 1.虚拟机中配置好docker环境&#xff0c;并导入nginx&#xff0c;mysql&#xff0c;jdk的镜像 2.下载docker for windows 用idea打包镜像和创建容器需要这个东西支持 下载安装包后执行&#xff0c;无脑回车即可 3.idea中配置docker连接 完成配置后&…

WPS Office for Linux 12 个人版上线deepin 23商店:UI 视觉重构,新增多项 AI 功能

查看原文 全新WPS Office For Linux个人版&#xff08;12.1.0.17881&#xff09;与deepin 23的AI功能深度融合&#xff0c;正式上架在社区商店啦&#xff01; 这是 Linux 版本的一次里程碑式的重大更新。在产品能力层面上&#xff0c;在 deepin 23 上WPS Office 几乎实现了与 …

AMD MI300X vs Nvidia H100/H200:AI计算领域的新一轮较量

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;计算引擎的性能竞赛也愈演愈烈。近期&#xff0c;MLCommons发布的最新AI训练和推理基准测试结果&#xff0c;他们构建了一套 MLPerf AI 训练和推理基准&#xff0c;将AMD的Instinct“Antares”MI300X GPU与Nv…

软件开发人员从0到1实现物联网项目:项目架构的思考

文章目录 前言单体应用足矣摒弃传统的微信对接后期的维护投入上真正的“云”&#xff1a;云托管0服务器免运维免费的CDN和DDoS防护 技术架构小结 前言 因为种种原因&#xff0c;《软件开发人员从0到1实现物联网项目》这个项目的进度停滞了将近一个月。 鉴于该项目的前期开发和…

【hot100篇-python刷题记录】【跳跃游戏 II】

R7-贪心算法 目录 方法1&#xff1a; 方法2&#xff1a; 很贪心啊&#xff0c;局部最优解就是全局最优解&#xff0c;要求到达nums[n-1]的最小步数&#xff0c;我们每一步都走最远。 方法1&#xff1a; class Solution:def jump(self, nums: List[int]) -> int:nlen(n…

【车载开发系列】ParaSoft入门介绍

【车载开发系列】ParaSoft入门介绍 【车载开发系列】ParaSoft入门介绍 【车载开发系列】ParaSoft入门介绍一. ParaSoft的背景二. 设计理念三. ParaSoft C/CTest简介四. 具备常用功能1&#xff09;静态代码分析2&#xff09;代码覆盖率分析3&#xff09;模糊测试4&#xff09;自…

AI边缘控制器:重塑工业自动化与控制的新篇章

在智能制造和工业4.0的浪潮下&#xff0c;AI边缘控制器作为新一代智能控制设备&#xff0c;正逐步成为推动工业自动化与数字化转型的关键力量。这类基于x86架构的高性能IPC&#xff08;工业个人计算机&#xff09;形态产品&#xff0c;不仅继承了传统PC的可扩展性、开放性和可视…

RPKI应急管控网络拓扑搭建

应急管控网络拓扑搭建 一、网络拓扑图 二、拓扑配置 1.资源库批量导入roas 在rpki.qcl.edu.cn服务器上的/usr/local/rpki/目录下执行脚本 sh roa_get.sh add#!/bin/dash# TODO Aadd Rremove start10000 sum254 run(){for i in seq 1 20dofor j in seq 1 250doas_numberexpr…

深度学习中常见的损失函数

关注B站可以观看更多实战教学视频&#xff1a;hallo128的个人空间 深度学习中常见的损失函数 损失函数的作用 损失函数是衡量神经网络输出与真实标签之间差距的指标。在训练过程中&#xff0c;神经网络的目标是最小化损失函数的值。常见的损失函数包括均方误差&#xff08;MS…

弗洛伊德(Floyd)算法(C/C++)

弗洛伊德算法&#xff08;Floyds algorithm&#xff09;&#xff0c;又称为弗洛伊德-沃尔什算法&#xff08;Floyd-Warshall algorithm&#xff09;&#xff0c;是一种用于在加权图中找到所有顶点对之间最短路径的算法。这个算法适用于有向图和无向图&#xff0c;并且可以处理负…

网络层 VIII(网络层设备——路由器)【★★★★★★】

一、冲突域与广播域 这里的“域”表示冲突或广播在其中发生并传播的区域。 1. 冲突域 冲突域是指连接到同一物理介质上的所有结点的集合&#xff0c;这些结点之间存在介质争用的现象&#xff08;能产生冲突的所有设备的集合&#xff09;。也就是说&#xff0c;若这些设备同时发…

「滚雪球学MyBatis」教程导航帖(已完结)

写在前面 我是bug菌&#xff0c;CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家&#xff0c;C站博客之星Top30&#xff0c;华为云2023年度十佳博主&#xff0c;掘金多年度人气作者Top40&#xff0c;掘金等各大社区平台签约作者&#xff0c;51CTO年度博…

酒茶香链接心灵——探寻现代人幸福生活

科技在飞速发展&#xff0c;人类社会以前所未有的速度向前跃进&#xff0c;物质世界的繁荣达到了前所未有的高度。 然而&#xff0c;这光鲜的背后&#xff0c;却无形中拉远了人与人之间的距离&#xff0c;割裂了传统文化的根脉。 传统文化势弱、“快餐文化”层出不穷&#xff0…

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤&#xff08;UserCF&#xff09;2. 基于物品的协同过滤&#xff08;ItemCF&#xff09;3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过…

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Xilinx FPGA 原语解析(二):IBUFDS差分输入缓冲器(示例源码及仿真)

目录 前言&#xff1a; 一、原语使用说明 二、原语实例化代码模版 三、使用示例 1.设计文件代码 2.仿真文件代码 3.仿真结果 前言&#xff1a; 本文主要参考资料xilinx手册&#xff0c;《Xilinx 7 Series FPGA and Zynq-7000 All Programmable SoC Libraries Guide for…

全志A527 A133 A523 T527 T133 H6 H8应用无法开启后台服务

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改4.1 代码修改方法14.2 代码修改方法24.3 代码修改方法35.彩蛋1.前言 像全志的很多平台,普通的app并不能正常的启动后台的服务,这样对于应用层很困扰,无法启动后台的服务,功能就不能正常使用…

【自考zt】【软件工程】【21.10】

关键字&#xff1a; 软件需求基本性质、软件系统需求挑战、耦合&#xff08;高内容&#xff0c;低无直接&#xff09;、内聚&#xff08;初始化时间&#xff09;、uml包、rup边界类、测试首要目标、单元测试最后工作、性能需求 软件开发本质、软件需求规约三种风格、提炼、用…

【MySQL】MySQL库的操作

目录 创建数据库字符集和效验规则查看系统默认字符集和效验规则查看数据库支持的字符集查看数据库支持的字符集效验规则字符集对数据库的影响 操纵数据库查看数据库显示创建语句修改数据库数据库删除总结 数据库的备份和恢复备份恢复注意事项 查看数据库的连接情况 创建数据库 …

【C++】 Vector

文章目录 1 背景2 什么是 vector&#xff1f;3 vector 特性4 基本函数实现5 基本用法6 例子在 vector 最后移除和插入数据clear() 清除 vector 中所有数据排序访问&#xff08;直接数组访问&迭代器访问&#xff09;二维数组两种定义方法 7、参考 1 背景 C 中的容器&#x…