【APUE】网络socket编程温度采集智能存储与上报项目技术------多进程编程

作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习
擅长领域:驱动开发,嵌入式软件开发,BSP开发
作者主页:一个平凡而乐于分享的小比特的个人主页
文章收录专栏:网络socket编程之温度采集智能存储与上报项目,本专栏为网络socket编程之温度采集智能存储与上报项目技术简介,实现流程分析
项目源码:https://gitee.com/TJF865975/project1_ds18b20,README部分包含项目功能及实现,欢迎大家Watch、Star、Fork。
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

1. 多进程编程基础知识

1.1 什么是进程?

在操作系统原理使用这样的术语来描述的:正在运行的程序及其占用的资源(CPU、内存、系统资源等)叫做进 程。站在程序员的角度来看,我们使用vim编辑生成的C文件叫做源码,源码给程序员来看的但机器不识别,这时我们需要使用 编译器gcc编译生成CPU可识别的二进制可执行程序并保存在存储介质上,这时编译生成的可执行程序只能叫做程序而不能叫进 程。而一旦我们通过命令(./a.out)开始运行时,那正在运行的这个程序及其占用的资源就叫做进程了。

1.2 进程空间内存布局

在这里插入图片描述
:栈内存由编译器在程序编译阶段完成,进程的栈空间位于进程用户空间的顶部并且是向下增长,每个函数的每次调用都会在栈空间中开辟自己的栈空间,函数参数、局部变量、函数返回地址等都会按照先入者为栈顶的顺序压入函数栈中,函数返回后该函数的栈空间消失,所以函数中返回局部变量的地址都是非法的。
:堆内存是在程序执行过程中分配的,用于存放进程运行中被动态分配的的变量,大小并不固定,堆位于非初始化数据段和栈之间,并且使用过程中是向栈空间靠近的。当进程调用 malloc 等函数分配内存时,新分配的内存并不是该函数的栈帧中,而是被动态添加到堆上,此时堆就向高地址扩张;当利用 free 等函数释放内存时,被释放的内存从堆中被踢出,堆就会缩减。因为动态分配的内存并不在函数栈帧中,所以即使函数返回这段内存也是不会消失。
非初始化数据段:通常将此段称为 bss 段,用来存放未初始化的全局变量和 static 静态变量。并且在程序开始执行之前,就是在 main()之前,内核会将此段中的数据初始化为 0 或空指针。
初始化数据段:用来保已初始化的全局变量和 static 静态变量。
文本段也称代码段:这是可执行文件中由 CPU 执行的机器指令部分。正文段常常是只读的,以防止程序由于意外而修改其自身的执行。

Linux 内存管理的基本思想就是只有在真正访问一个地址的时候才建立这个地址的物理映射,Linux C/C++语言的分配方式共有3 种方式。
(1)从静态存储区域分配。就是数据段的内存分配,这段内存在程序编译阶段就已经分配好,在程序的整个运行期间都存在,例如全局变量,static 变量。
(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是系统栈中分配的内存容量有限,比如大额数组就会把栈空间撑爆导致段错误。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用free 或 delete 释放内存。此 区域内存分配称之为动态内存分配。动态内存的生存期由我们决定,使用非常灵活,但问题也最多,比如指向某个内存块的指针取值发生了变化又没有其他指针指向 这块内存,这块内存就无法访问,发生内存泄露。

1.3 四次握手模型

在这里插入图片描述

2.实现函数

2.1 fork()系统调用

fork()系统调用会创建一个新的子进程,这个子进程是父进程的一个副本。这也意味着,系统在创建新的子进程成功后,会将父进程的文本段、数据段、堆栈都复制一份给子进程,但子进程有自己独立的空间,子进程对这些内存的修改并不会影响父进程空间的相应内存。这时系统中出现两个基本完全相同的进程(父、子进程),这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。如果需要确保让父进程或子进程先执行,则需要程序员在代码中通过进程间通信的机制来自己实现。

2.2 exec*()执行另外一个程序

在fork()之后紧接着调用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[]);  

2.3 vfork()系统调用

在fork()之后常会紧跟着调用exec来执行另外一个程序,而exec会抛弃父进程的文本段、数据 段和堆栈等并加载另外一个程序,所以现在的很多fork()实现并不执行一个父进程数据段、堆和栈的完全副本拷贝。作为替代,使用了写时复制(CopyOnWrite)技术: 这些数据区域由父子进程共享,内核将他们的访问权限改成只读,如果父进程和子进程中的任何一个试图修改这些区域的时候,内核再为修改区域的那块内存制作一个副本。

vfork()是另外一个可以用来创建进程的函数,他与fork()的用法相同,也用于创建一个新进程。 但vfork()并不将父进程的地址 空间完全复制到子进程中,因为子进程会立即调用exec或exit(),于是也就不会引用该地址空间了。不过子进程再调用exec()或 exit()之前,他将在父进程的空间中运行,但如果子进程想尝试修改数据域(数据段、堆、栈)都会带来未知的结果,因为他会影响 了父进程空间的数据可能会导致父进程的执行异常。此外,vfork()会保证子进程先运行,在他调用了exec或exit()之后父进程才 可能被调度运行。如果子进程依赖于父进程的进一步动作,则会导致死锁。

2.4 system()与popen()函数

如果我们在程序中,想执行另外一个Linux命令时,可以调用fork()然后再exec执行相应的命令即可,但这样相对比较麻烦。Linux系统提供了一个system()库函数,该库函数可以快速创建一个进程来执行相应的命令。

int system(const char *command);

对于之前我们使用fork()+execl()函数来执行ifconfig命令,并将该命令执行的结果写入到文件后再来读取的实现,这个过程相对比较麻烦,另外涉及到了创建文件和读取文件的过程。其实也有另外一个函数popen()可以执行一条命令,并返回一个基于管道(pipe)的文件流,这样我们可以从该文件流中一行样解析了。

2.5 wait()与waitpid()函数

当一个进程正常或异常退出时,内核就会向其父进程发送SIGCHLD信号。因为子进程退出是一个异步事件,所以这种信号也是内核向父进程发送的一个异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即将被执行的函数,父进程可以调用wait()或waitpid()可以用来查看子进程退出的状态。

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项可使调用者不用阻塞。 waitpid并不等待在其调用的之后的第一个终止进程,他有若干个选项,可以控制他所等待的进程。 如果一个已经终止、但其父进程尚未对其调用wait进行善后处理(获取终止子进程的有关信息如CPU时间片、释放它锁占用的资源如文件描述符等)的进程被称僵死进程(zombie),ps命令将僵死进程的状态打印为Z。如果子进程已经终止,并且是一个僵死进程,则wait立即返回该子进程的状态。所以,我们在编写多进程程序时,最好调用wait()或waitpid()来解决僵尸进程的问题。

此外,如果父进程在子进程退出之前退出了,这时候子进程就变成了孤儿进程。当然每一个进程都应该有一个独一无二的父进程,init进程就是这样的一个“慈父”,Linux内核中所有的子进程在变成孤儿进程之后都会被init进程“领养”,这也意味着孤儿进程的父进程最终会变成init进程。

3.多进程改写服务器程序

在了解Linux下多进程编程之后,我们就可以使用多进程编程模型改写服务器的多进程实现,其流程图如下:
在这里插入图片描述

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

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

相关文章

《数据结构学习笔记---第九篇》---循环队列的实现

文章目录 1.循环队列的定义 2.循环队列的判空判满 3.创建队列并初始化 4.入队和出队 5. 返回队尾队首元素 6.释放循环队列 1.循环队列的定义 定义:存储队列元素的表从逻辑上被视为一个环。 我们此次实现的循环队列,采用顺序表 typedef struct {int…

9、逆序对的数量(含源码)

逆序对的数量 难度&#xff1a;简单 题目描述 给定一个长度为n的整数数列&#xff0c;请你计算数列中的逆序对的数量。 逆序对的定义如下&#xff1a;对于数列的第 i 个和第 j 个元素&#xff0c;如果满足 i < j 且 a[i] > a[j]&#xff0c;则其为一个逆序对&#xf…

Open3D(C++) 基于三维激光扫描点云的树冠体积计算方法

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、原理概述 针对树冠形状不规则,树冠体积难以测量和计算的问题,提出一种基于三…

Html提高——视频标签音频标签及其相关属性

HTML5 在不使用插件的情况下&#xff0c;也可以原生的支持音视频格式文件的播放&#xff0c;当然&#xff0c;支持的格式是有限的。 1、video标签 1.1、video标签的语法 <video src"文件地址" controls"controls"></video> video标签的内部…

7.java openCV4.x 入门-Mat之转换、重塑与计算

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;我们唯一拥有的就是今天&#xff0c;唯一能把握的也是今天建议把本文当作笔记来看&#xff0c;据说专栏目录里面有相应视频&#x1f92b; &#x1f9ed;文…

全国土壤类型分布数据/土壤有机质/土壤含水量分布/土壤温度/土壤质地/土壤PH

数据下载链接&#xff1a;数据下载链接 引言 土壤是指地球表面的一层疏松的物质&#xff0c;由各种颗粒状矿物质、有机物质、水分、空气、微生物等组成&#xff0c; 能生长植物。土壤是一个国家最重要的自然资源&#xff0c;它是农业发展的物质基础。我国幅员辽阔&#xff0c;自…

SD-WAN组网面临的安全挑战?如何提供有效的安全措施

SD-WAN&#xff08;软件定义广域网&#xff09;技术的广泛应用&#xff0c;企业面临着越来越多的网络安全挑战。尽管SD-WAN带来了灵活性和效率的提升&#xff0c;但其开放性和基于云的特性也带来了一系列安全威胁。本文将探讨SD-WAN组网面临的安全挑战&#xff0c;并提供一些有…

0201基础集成与使用-微信支付-支付模块-项目实战

文章目录 一、前言二、springboot集成2.1 配置信息与配置类2.2 微信相关枚举信息2.3 工具类2.4 业务接口 三、演示-支付与退款结语 一、前言 下面我以微信支付v3为例&#xff0c;通过spirngboot集成到我们的项目中&#xff0c;不依赖其他第三方框架。当然适用简单项目&#xf…

Linux多进程通信(4)——消息队列从入门到实战!

Linux多进程通信总结——进程间通信看这一篇足够啦&#xff01; 1.基本介绍 1&#xff09;消息队列的本质其实是一个内核提供的链表&#xff0c;内核基于这个链表&#xff0c;实现了一个数据结构&#xff0c;向消息队列中写数据&#xff0c;实际上是向这个数据结构中插入一个…

Vue项目登录页实现获取短信验证码的功能

之前我们写过不需要调后端接口就获取验证码的方法,具体看《无需后端接口,用原生js轻松实现验证码》这个文章。现在我们管理后台有个需求,就是登录页面需要获取验证码,用户可以输入验证码后进行登录。效果如下,当我点击获取验证码后能获取短信验证码: 这里在用户点击获取…

win11安装WSL UbuntuTLS

win11安装WSL WSL 简介WSL 1 VS WSL 2先决要求安装方法一键安装通过「控制面板」安装 WSL 基本命令Linux发行版安装Ubuntu初始化相关设置root用户密码网络工具安装安装1panel面板指导 WSl可视化工具问题总结WSL更新命令错误Ubuntu 启动初始化错误未解决问题 WSL 简介 Windows …

Sybase ASE中的char(N)的坑以及与PostgreSQL的对比

1背景 昨天,一朋友向我咨询Sybase ASE中定长字符串类型的行为,说他们的客户反映,同样的char类型的数据,通过jdbc来查,Sybase库不会带空格,而PostgreSQL会带。是不是这样的?他是PostgreSQL的专业大拿,但因为他手头没有现成的Sybase ASE环境,刚好我手上有,便于一试。 …

hive 慢sql 查询

hive 慢sql 查询 查找 hive 执行日志存储路径&#xff08;一般是 hive-audit.log &#xff09; 比如&#xff1a;/var/log/Bigdata/audit/hive/hiveserver/hive-audit.log 解析日志 获取 执行时间 执行 OperationId 执行人 UserNameroot 执行sql 数据分隔符为 \001 并写入 hiv…

vuepress-theme-hope 添加谷歌统计代码

最近做了个网站,从 cloudflare 来看访问量,过去 30 天访问量竟然有 1.32k 给我整懵逼了,我寻思不应该呀,毕竟这个网站内容还在慢慢补充中,也没告诉别人,怎么就这么多访问?搜索了下, cloudflare 还会把爬虫的请求也就算进来,所以数据相对来说就不是很准确 想到了把 Google An…

如何同时安全高效管理多个谷歌账号?

您的业务活动需要多个 Gmail 帐户吗&#xff1f;出海畅游&#xff0c;Gmail账号是少不了的工具之一&#xff0c;可以关联到Twitter、Facebook、Youtube、Chatgpt等等平台&#xff0c;可以说是海外网络的“万能锁”。但是大家都知道&#xff0c;以上这些平台注册多账号如果产生关…

Cisco交换机安全配置

Cisco交换机安全配置 前提 我们以下命令一般都要先进入Config模式 S1> enable S1# conf t S1(config)#端口安全保护 禁用未使用的端口 以关闭fa0/1到fa0/24的端口为例 S1(config)# interface range fa0/1-24 S1(config-if-range)# shutdown缓解MAC地址表攻击 防止CAM…

蓝桥杯刷题第六天(昨天忘记发了)

今天想从不一样的角度来解题&#xff1a;从时间紧张暴力求解到思路阔达直接通过所有案例 暴力方法&#xff1a; 思路第一眼看到这个问题我就想到了第一个思路就是先用两个数组一个存石子数一个存颜色状态&#xff0c;每次遍历一遍看看有没有相邻石子颜色一样且为和最小的。 im…

前端订阅后端推送WebSocket定时任务

0.需求 后端定时向前端看板推送数据&#xff0c;每10秒或者30秒推送一次。 1.前言知识 HTTP协议是一个应用层协议&#xff0c;它的特点是无状态、无连接和单向的。在HTTP协议中&#xff0c;客户端发起请求&#xff0c;服务器则对请求进行响应。这种请求-响应的模式意味着服务器…

Spring-IoC 基于注解

基于xml方法见&#xff1a;http://t.csdnimg.cn/dir8j 注解是代码中的一种特殊标记&#xff0c;可以在编译、类加载和运行时被读取&#xff0c;执行相应的处理&#xff0c;简化 Spring的 XML配置。 格式&#xff1a;注解(属性1"属性值1",...) 可以加在类上…

纯C代码模板

一、快排 void QuickSort(int *a,int left,int right){if(left>right) return;else{int low left,high right;int pivot a[low];while(low<high){while(a[high] > pivot && low < high){high--;}a[low] a[high]; //必须先动a[low]while(a[low] < …