从零开始学习Linux(6)----进程控制

1.环境变量

        环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,我们在编写C/C++代码时,链接时我们不知道我们链接的动态静态库在哪里,但可以连接成功,原因是环境变量帮助编译器进行查找,环境变量通常具有某些特殊用途,还有在系统当中中通常具有全局特性。

        环境变量不是一个而是一堆,彼此之间其实没有关系。

        环境变量一般是系统内置的具有特殊作用的变量。

        定义变量的本质,其实是开辟空间,在运行期间我们的程序也能开辟空间,操作系统/bash是用C语言写的程序,它能在运行中开辟空间,系统的环境变量,本质就是系统自己开辟空间,给他名字和内容即可。

1.命令行参数

int main(int argc,char *argv[],char *env[])

#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
    if(argc!=2)
    {
        printf("Usage:\n\t%s -number[1-3]\n",argv[0]);
        return 1;
    }
    if(strcmp("-1",argv[1])==0)
    {
        printf("function 1\n");
    }                                                     
    else if(strcmp("-2",argv[1])==0)
    {
        printf("function 2\n");
    }
    else if(strcmp("-3",argv[1])==0)
    {
        printf("function 3\n");
    }
    else
    {
        printf("unknown!\n");
    }
}

        我们可以通过不同的选项,让我们的同一个程序执行它内部不同的功能。命令行参数时Linux指令的基础。

        在上面的演示中,为什么我们不能像ls命令一样执行而是./的方式来执行,这时需要将你的程序所在的路径添加到环境变量中。

        指令env查看系统所有环境变量。命令行参数env[]中存放的也是系统所有环境变量,export命令导入环境变量。环境变量是可以被子进程继承下去的!(方式1),环境变量具有全局属性,会被所有的子进程继承。还可通过第三方变量environ,和getenv方法来获取。本地变量只能bash内部有效。

2.程序地址空间

        子进程按照父进程为模版,父子并没有对变量进行任何修改,如果子进程先修改,完成之后父进程再读取,我们发现父子进程输出地址是一致的,但是变量内容不一样,所以:

        变量内容不一样,所以父子进程输出的变量绝对不是同一个变量但地址值是一样的,说明,该地址绝对不是物理地址! 在Linux地址下,这种地址叫做 虚拟地址,我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理。OS必须负责将 虚拟地址 转化成 物理地址 。
        同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了
不同的物理地址。

1.什么是地址空间

        进程地址空间,每一个进程,都会存在一个进程地址空间,32【0,4GB】;进程地址空间是数据结构,就是特点数据结构的对象。区域划分本质就是区域内的各个地址,都可以使用,我们的地址空间不具备对我们的代码和数据的保存能力,将地址空间上的地址转化到物理内存中,给我们的进程提供一张映射表---页表。

2.为什么要有地址空间+页表

        将物理内存从无序变有序,让进程以统一的视角看待内存。

        将进程管理和内存管理进行解耦合。

        地址空间+页表是保护内存安全的重要手段。

​​​​​​ 1.写时拷贝

        进程调用fork,当控制转移到内核中的fork代码后,内核做:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

        通常,父子代码共享,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。所以,fork之前父进程独立执行,fork之后,父子两个执行流分别执行。

3.进程终止

        main函数的返回值叫做进程的退出码,一般0,表示进程执行成功,非零表示失败,不同的数字表示不同的错误原因。可以通过echo $?查看进程退出码。

        错误码转化为错误描述:1.可以使用系统自带的。2.自定义。除了进程退出,函数退出,我们怎么知道函数的执行情况。函数有返回值,调用函数,我们通常想看到两种结果:1.函数的执行结果。2.函数的执行情况--成功,失败,原因。

        进程退出的场景就三种:1.代码执行完,结果是正确的。2.代码执行完,结果是不正确的。3.进程代码没有执行完,进程出异常了(是进程收到了异常信号,每个信号都有不同的编号,不同的信号编号表明异常的原因)。

        任何进程最终的执行情况,我们可以使用两个数字表明具体执行的情况。

        exit就是用来终止进程的。exit(退出码)在我们的进程代码中,任意地方调用exit,都表示进程退出,exit会支持刷新缓冲区,_exit不支持,我们之前所说的缓冲区绝对不是操作系统里面的缓冲区,而是上层的库的缓冲区。

4.进程等待

  • 之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
  • 另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。

1.父进程通过wait方式,回收子进程的资源(必然)

2.通过wait方式,获取子进程的退出信息(可选的)

wait默认会进行阻塞等待,等待任意一个子进程,返回值>0:等待成功,等待子进程的pid,<0:等待失败。

pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
waitpid
pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
        当正常返回的时候waitpid返回收集到的子进程的进程ID;
        如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
        如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
        pid:
                Pid=-1,等待任一个子进程。与wait等效。
                Pid>0.等待其进程ID与pid相等的子进程。
        status:
                WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
                WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
        options:
                WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。
  • 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  • 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  • 如果不存在该子进程,则立即出错返回。
获取子进程status
  • wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
  • 如果传递NULL,表示不关心子进程的退出状态信息。
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
  • status不能简单的当作整形来看待,可以当作位图来看待(只研究status低16比特位.

5.进程程序替换

1.替换原理

        什么是程序替换:

                a.我们的程序,只能执行我们的代码。

                b.如果我们创建的子进程,想执行其他程序的代码呢?

        在替换过程中,有没有创建新的进程???没有!

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

2.替换函数

        有六种以exec开头的函数,统称为exec函数:

#include <unistd.h>
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[]);
int execve(const char *path, char *const argv[], char *const envp[]);
        这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
        如果调用出错则返回-1
        所以exec函数只有出错的返回值而没有成功的返回值
l(list) : 表示参数采用列表
v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
e(env) : 表示自己维护环境变量
        更改为多进程版本,我们为什么要这么做:父进程能得到执行结果。
        替换为什么没有影响父进程:进程具有独立性,替换的时候,发生写时拷贝。
        默认可以通过地址空间继承的方式,让所以得子进程拿到环境变量
        进程程序替换,不会替换环境变量数据
1.如果我们想让子进程继承全部的环境变量,直接能拿到
2.如果单纯的新增呢?putenv
3.如果我想设置全新的环境变量给子进程呢?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单粗暴的翻译英文pdf

背景&#xff1a;看书的时候经常遇到英文pdf&#xff0c;没有合适的翻译软件可以快速翻译全书。这里提供一个解决方案。 Step 1 打开英文pdfCTRLA全选文字CTRLC复制打开记事本CTRLV复制保存为data.txt Step 2 写一个C脚本 // ToolPdf2Html.cpp : 此文件包含 "main&quo…

【HMGD】GD32/STM32 DMA接收不定长串口数据

单片机型号&#xff1a;GD32F303系列 CubeMX配置 配置串口参数 开启DMA 开启中断 示例代码 使用到的变量 uint8_t RX_Buff_FLAG 0; uint8_t RX_Buff[300] {0}; uint8_t TX_Buff[300] {0};串口接收空闲函数 // 串口接收空闲函数 void HAL_UARTEx_RxEventCallback(UART_H…

Redisson中分布式锁的实现原理

redisson版本&#xff1a;3.27.2 简介 锁归根结底就是对同一资源的竞争抢夺&#xff0c;不管是在单体的应用亦或者集群的服务中&#xff0c;上锁都是对同一资源进行修改的操作。至于分布式锁&#xff0c;那就是多个服务器或资源&#xff0c;同时抢占某一单体应用的同个资源了。…

基于Springboot+Vue的Java项目-农产品直卖平台系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

AD软件针对分散的元器件归一排列

先框选 然后快捷键TOL 绿色的十字箭头选框选位置 完成

将excel表中的数据导入到navicat中

1.将excel中的表头改成英文 2.在navicat中右键表&#xff0c;选择【导入向导】 3.在弹出的导入向导中选择Excel文件&#xff0c;然后点击【下一步】 4.选择需要导入的excel&#xff0c;选中后&#xff0c;在下方会罗列出excel中的sheet&#xff0c;勾选需要导入的sheet&#xf…

Chromium 调试指南2024 Windows11篇-使用日志来辅助调试(八)

1. 日志&#xff1a;你的第一个调试工具 日志是开发者最简单也是最常用的调试工具之一&#xff0c;它能够提供程序运行时的详细记录。通过合理的日志记录策略&#xff0c;开发者可以快速定位问题发生的上下文&#xff0c;理解程序的运行流程和状态。 2. 如何在Chromium中使用…

QMT如何写代码获取基金数据?方法总结!

此函数被设计为只支持单一基金查询&#xff0c;用于获取详细的股票信息。该函数可以让您接收关于特定基金的深度信息&#xff0c;包括但不限于其涨跌停价格、上市日期、退市日期以及期权到期日等重要数据。这将为您提供详尽的信息&#xff0c;以便更好地理解并分析股票的历史和…

【vue2项目经验总结:a标签干扰路由】

当我们点击页面中的a标签实现跳转时&#xff0c;会发现网页上方的路由也切换成了a标签的id值&#xff1a; 刷新后页面也会变成空白&#xff1a; 解决方法&#xff1a; 添加Click方法&#xff0c;传入的参数与id值保持一致 scrollIntoView() 方法&#xff0c;将该元素滚动到…

pycharm连接远程服务器,解决终端出现乱码问题

在终端输入命令时会有乱码问题&#xff0c;是字体编码设置错误。 根据上述步骤&#xff0c;设置完成后重启就可以了。

C#语言进阶

一、简单数据结构类 1. ArrayList ArrayList是一个 C# 为我们封装好的类&#xff0c;它的本质是一个 object 类型的数组。ArrayList类帮助我们实现了很多方法&#xff0c;比如数组的增删查改 1.1 声明 using System.Collections;ArrayList array new ArrayList(); 1.2 增…

MyBatis的创建和测试

创建项目点击Spring Initializr然后点击next 点击SQL 选择里面的Mybatis Framework和Mysql Driver 按如下图片创建项目 user表中的数据 #下面这些内容是为了让MyBatis映射 #指定Mybatis的Mapper文件 mybatis.mapper-locationsclasspath:mappers/*xml #指定Mybatis的实体目录 my…

亿级流量系统架构设计与实战

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

强烈推荐的AI生成PPT软件,快捷高效

提起PPT&#xff0c;大家的第一反应就是痛苦。经常接触PPT的学生党和打工人&#xff0c;光看到这3个字母&#xff0c;就已经开始头痛了&#xff1a; 1、PPT内容框架与文案挑战重重&#xff0c;任务艰巨&#xff0c;耗费大量精力。 2、PPT的排版技能要求高&#xff0c;并非易事…

EmotiVoice 实时语音合成TTS;api接口远程调用

参考:https://github.com/netease-youdao/EmotiVoice 测试整体速度可以 docker安装: 运行容器:默认运行了两个服务,8501 一个streamlit页面,另外8000是一个api接口服务 docker run -dp 8501:8501 -p 8250:8000 syq163/emoti-voice:latest##gpu运行 (gpu运行遇到CUDA er…

高效且安全的传输工具:FileLink跨网文件传输

在数字化时代&#xff0c;文件传输已成为我们日常工作和生活不可或缺的一部分。无论是企业内部的资料共享&#xff0c;还是企业对外的文件交换&#xff0c;都需要一个高效、稳定且安全的传输工具。而FileLink跨网文件传输正是满足这些需求的理想选择。 FileLink跨网文件传输 首…

【环境安装】nodejs 国内源下载与安装以及 npm 国内源配置

前言 Node.js 是一个基于 Chrome V8 引擎构建的 JavaScript 运行时环境&#xff0c;它能够使 JavaScript 在服务器端运行。它拥有强大的包管理器 npm&#xff0c;使开发者能够轻松管理和共享 JavaScript 代码包。 在中国&#xff0c;由于众所周知的原因&#xff0c;我们可能会…

Spring,SpringMVC,SpringBoot知识总结

1.简述Spring,SpringMVC&#xff0c;SpringBoot各自特点及联系 Spring、Spring MVC 和 Spring Boot 是 Java 开发中常用的三个框架&#xff0c;它们之间有以下关系&#xff1a; Spring&#xff1a;是一个全功能的 JavaEE 应用程序框架。它提供了一系列的解决方案&#xff0c…

VUE2+ffmpeg处理非h264编码格式视频

1、安装npm install ffmpeg/ffmpeg0.10.0 ffmpeg/core0.9.8 video.js8.12.0 2、在vue.config.js中devServer配置 headers: {// 如果需要用到ffmpeg确保ShareArrayBuffer能够正常使用,可能会有安全隐患Cross-Origin-Embedder-Policy: require-corp,Cross-Origin-Opener-Policy:…

XM1553B 航电总线协议模块(内置总线收发器)

是一款4M速率的高性能1553B模块&#xff0c;兼容1Mbps通信速率&#xff0c;支持单功能&#xff08;BC,orRT,or BM&#xff09;和多功能&#xff08;BC&1RT&BM&#xff09;&#xff0c;该模块内部集成32K16bit的双端口RAM和4M 1553B收发器。 主机端接口支持串口和SPI。串…