进程与进程函数

news2024/9/22 11:24:51

目录

进程与程序

1.1进程是什么

1.2程序,进程之间的关系

1.3进程的生存环境

1.4进程的状态转换

1.5关于内核层与用户层

1.6保存和恢复处理器现场

进程原语

2.1fork()

​编辑

2.1.1父子进程的继承

2.1.2父子进程共享fork()栈帧

2.1.3打印进程id和父进程id

2.1.4循环创建进程

2.1.5fork()版本

2.2execl()

2.3wait()

2.4waitpid()


进程与程序

1.1进程是什么

进程是一个任务执行单元(逻辑单元)。

1.2程序,进程之间的关系

程序是静态数据(静态表现)存储在磁盘中。

进程是逻辑执行单位在cpu,内存,磁盘帮助用户使用系统资源完成特定任务。

程序是进程的静态表现,进程是程序的动态表现。

创建一个进程

生成可执行程序

我们发现把可执行程序删除后,进程依旧进行。

如果进程执行时,没有回访文件数据,那么这些文件数据都可以删除,程序文件与进程是没有必然联系的。

1.3进程的生存环境

内核层(系统层)->PCB(进程控制块)pid-----------------------------(概括一下就是:存储进程信息)

用户层->命令行参数(int argc char** argv),环境变量(系统默认),栈(0xc3000),库,堆,DATA(已初始化的全局静态变量),BSS(未初始化的全局数据),Text 代码段------------------------(概括一下就是:存储进程业务逻辑和任务数据)->映射机制,虚拟内存映射到物理内存,内存管理器有一个虚拟内存映射表。

x32位系统用户层和内核层有两种分配方式,0~3G 3~4G,0~2G 2G~4G,32位系统可用3级指针寻址。

x64位系统0~8T 8~16T,64位·系统是四级间接寻页。

每个进程通过映射方式访问物理内存,可以后序通过交换机制将闲置内存给别人使用,最大化利用内存,虚拟内存概念,可以避免用户直接访问物理内存。

每个进程执行时拥有独立的物理内存,进程资源独享。

内核空间映射内存是共享内存。用户空间映射内存是独立内存。

内存的基本单位是page,一般是4k。

内存的权限:PROT_READ只读,PROT_WRITE只写,PROT_EXEC执行,PROT_NONE都不行

1.4进程的状态转换

就绪态:进程准备就绪等待cpu资源而后开始运行。

终止态:进程结束退出,进程资源释放。

运行态:进程得到时间片开始执行。

阻塞态:放弃时间片,可以被强制中断EINTR,阻塞的进程资源在内存中。

挂起态:放弃时间片,无法被强制中断,挂起的进程资源被交换到外存中。

(僵尸态Linux下)

(孤儿态Linux下)

例子:当前进程a占用cpu,现在要把cpu释放交给进程b,怎么办?sleep(0);sleep释放cpu,进程有就近原则就是b,sleep让进程切换成阻塞态放弃cpu。

就绪态可以切换到运行态,运行态可以切换到就绪态。

挂起态可以切换到就绪态,阻塞态可以切换到就绪态。

进程在任意一种状态都能切换到终止态。

1.5关于内核层与用户层

电脑中所有设备都是cpu来访问控制的。

cpu有寄存器,运算器,控制器,译码器。

电脑中所有设备都是cpu来访问控制的,用户层执行以低权限使用cpu系统资源和设备,内核层执行以高权限使用cpu系统资源和设备。(系统调用就是cpu的权限切换)

1.6保存和恢复处理器现场

假设一个进程在执行指令的过程中耗尽时间片,那么会触发中断,保存处理器现场,内核栈->用于保存恢复处理器现场,这样保证再多的进程共享寄存器也不会引发异常。

进程原语

操作系统提供的一些列系统函数接口,让用户完成进程开发。

2.1fork()

父进程调用fork()创建一个子进程。

在Linux操作系统中几乎所有进程都有父亲。

根进程,刚开机就创建出来了。就根进程没父进程。根进程也称为init进程,系统的1号进程。

强亲缘关系:子进程从被创建直到进程结束,父进程全程参与。

如果是多级别的父子进程那么具备一定的亲缘关系(继承)。

fork();返回值类型是pid_t。

父进程从代码的起始位置执行到末尾,子进程从fork之后执行到末尾。

ps -ajx查看亲缘关系。

2.1.1父子进程的继承

在创建子进程之后,父进程将部分内容继承给子进程,子进程执行。

拷贝继承:

子进程可以访问父进程所有资源,无论是堆栈数据还是代码段。

父进程的资源数据完全拷贝给子进程,子进程任意访问修改与父进程无关。

2.1.2父子进程共享fork()栈帧

克隆完之后返回子进程id,父进程接收到然后返回。fork()它自己有个返回值,子进程来的时候最后执行了一个return 0。

因为printf会将输出缓存到缓冲区中,所以有可能在子进程中的输出还没有刷新到屏幕上之前,两个进程都已经执行了后续的代码。所以先输出那个666了。

2.1.3打印进程id和父进程id

getpid()当前进程id,父进程id。

2.1.4循环创建进程

如果在循环中不加是子进程就退出,那会创建出2^{n}-1个进程。

如图:

如果加上就正常了,不能让子进程也进入循环。

2.1.5fork()版本

第一版本:

采用拷贝继承,父进程拷贝资源是强制性的,如果子进程不需要父进程资源,那么这个拷贝开销毫无意义。

第二版本:

使用vfork函数,不会产生用户层拷贝开销,一定需要结合execl函数使用。

第三版本:

可以察觉子进程是否需要资源,读时共享,写时复制。

有一个映射内存,可以让子进程来访问父进程资源,如果子进程尝试访问修改映射内存数据,触发写复制机制,父进程将特定数据拷贝给子进程。写时复制,父子对映射内存数据写,都触发写时复制。父进程修改数据为了保证子进程不异常,子进程要复制之前的数据。

2.2execl()

进程功能重载。

重载可以复制其他进程的功能,无需对程序进行代码实现,重载即可。

which 命令名#寻址命令。

execl(命令的绝对路径,命令第一个参数,命令第二个参数,...,命令第n个参数,哨兵节点(NULL));

execl,预启动命令,重载目标用户层,但是目标程序没有被执行。重载成功后子进程代码被覆盖,最终程序是在重载程序中的代码段结束。如果子进程想要执行自己定义代码,要在fork之后execl之前完成。

重载ls -l

先找到绝对路径。

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
    pid_t pid;
    pid=fork();
    if(pid>0)
    {
    printf("father pid success %d",getpid());
    pid_t wpid = wait(NULL);
    printf("wait pid success %d",wpid);
    }
    else if(pid==0)
    {
    printf("A\n");
    execl("/usr/bin/ls","ls","-l",NULL);
    printf("B\n");
    exit(4);
    }
    else exit(0);
    return 0;
}

execl可以便于功能拓展,使用极少的代价重载使用复杂功能。可以实现主程序不动的情况下,动态迭代,只需要让主程序定时重载即可。

代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int main()
{
    pid_t pid;
    pid=fork();
    if(pid>0)
    {
     while(wait(NULL)>0)
     {
         sleep(1);
       pid=fork();
      if(pid==0) goto biu;
     }
    }
 else if(pid==0){
biu:         execl("/home/zzj/doit","doit",NULL);
printf("dddd\n");
 }
    else exit(0);
    return 0;
}   
#include<stdio.h>
int main()
{
    printf("hhhhhhh\n");
}

改了之后就这样。

2.3wait()

进程结束后需要对其进行回收,否则该进程会称为僵尸进程,引发内存泄漏。

当进程结束后,PCB未被释放,导致内存泄漏,这种现象被称为僵尸进程。。

Linux或Unix操作系统中,子进程只能由父进程回收。exit(0)调用操作系统中_EXIT(),用户空间内存被完全释放,也会释放部分内核空间,但是残留PCB导致内存泄漏,父进程负责回收释放子进程PCB,对子进程进行验尸操作,了解子进程的退出原因。

wait()函数返回值是pid_t。回收成功返回僵尸进程的pid。没有子进程尝试回收,wait立即失败返回。wait函数是阻塞回收函数,等待子进程结束后立即回收,它可以回收任意一个子进程,每次回收一个僵尸进程。验尸:pid_t zpid=wait(int * status);可以传出子进程退出原因,不验尸:pid_t zpid=wait(NULL);

让子进程变为僵尸进程,然后父进程回收

这里看见进程已经被回收了。

2.4waitpid()

高级回收函数。

pid_t zpid=waitpid(pid_t pid,int* status,WNOHANG);

返回值>0回收成功,返回值为僵尸的pid。返回时-1,表示回收失败,返回值0,表示当前子进程未结束,非阻塞返回0.。

pid_t pid; pid=-1(回收任意子进程),pid>0(指定回收一个子进程),pid=0(同组回收),pid<-1(跨组回收)。

非阻塞回收代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int main()
{
    pid_t pid;
    int i;
    for( i=0;i<5;i++)
    {
    pid=fork();
    //printf("%d\n",pid);
    if(pid==0)break;
    }
    if(pid>0)
    {//printf("%d\n",pid);
    printf("father pid %d\n",getpid());
     pid_t wpid;
     while((wpid=waitpid(-1,NULL,WNOHANG))!=-1)
     {
         if(wpid>0)
         {
             printf("waitpid success %d\n",wpid);
         }
         else if(wpid==0){

         printf("I am running\n");
         usleep(500000);
         }
     }
    }
    else if(pid==0)
    {
    printf("son pid %d\n",getpid());
    sleep(i);
    exit(i);
    }
  else exit(0);
return 0;
}

结果,首先父进程创建子进程,上面提到过fork会给两个返回值,一个是给父进程的子进程id,一个是给子进程返回的0,返回0之后会立即执行else if那,而父进程等创建完最后一个29866>0,执行if>0,所以输出是乱序的。

非阻塞回收比阻塞回收版本有更高的自由度,可以执行自身代码段。

无论是阻塞回收还是非阻塞回收都称为主动回收,这并不合理在子进程未结束前父进程产生大量回收开销,后序讲解被动回收方案。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenREALM学习笔记:14】单目视觉SLAM方法在UAV影像上重建三维地形的思考

最近在学习SLAM技术与测绘三维影像重建的相关知识&#xff0c;结合自己的感受&#xff0c;撰写一下对于单目视觉SLAM利用无人机影像重建三维地形的一些看法。 1. 单目视觉SLAM系统在三维地形重建中所面临的挑战有哪些&#xff1f; 单目视觉SLAM众所周知的一个问题是&#xff…

C# 委托函数 delegate

在C#中&#xff0c;委托&#xff08;Delegate&#xff09;是一种特殊的类型&#xff0c;它可以持有对方法的引用。 委托是实现事件的基础。事件本质上是多播委托&#xff0c;允许多个方法被触发 委托允许你将方法作为参数传递给其他方法&#xff0c;或者将方法作为返回值从方法…

feed流(投喂)

1、拉模式&#xff1a; 优缺点&#xff1a;节省空间&#xff0c;只存一份&#xff0c;赵六在需要的时候直接去读。延迟高&#xff0c;耗时长。如果关注的人多的话&#xff0c;就会一次性拉取的很大&#xff0c;造成拥塞。 2、推模式 优缺点&#xff1a;延迟低&#xff0c;耗时少…

嵌入式C++、STM32、树莓派4B、OpenCV、TensorFlow/Keras深度学习:基于边缘计算的实时异常行为识别

1. 项目概述 随着物联网和人工智能技术的发展,智能家居安全系统越来越受到人们的关注。本项目旨在设计并实现一套基于边缘计算的智能家居安全系统,利用STM32微控制器和树莓派等边缘设备,实时分析摄像头数据,识别异常行为(如入侵、跌倒等),并及时发出警报,提高家庭安全性。 系…

内存卡损坏读不出怎么修复?内存卡数据恢复的7个方法请收好!

当面对内存卡损坏、无法读取数据的困扰时&#xff0c;许多人会感到焦虑和困惑。尤其是当这些卡中存储着珍贵的照片、视频或文件时&#xff0c;这种困扰更显得令人不安。您是否也曾因内存卡损坏而无法显示照片或遭遇需要格式化的提示而感到困扰&#xff1f;在我们日常的生活中&a…

power bi文本,截取及查找函数

power bi文本,截取及查找函数 1. 文本函数1.concatenate函数2. exact 函数3. find函数4. search函数 2. 截取函数1. fixed 函数2. 大小写转换3. trim函数4.rept函数5. replace 函数6. substitute函数 3. 查找匹配函数1 contains函数2. treatas 函数3. ContainsString函数4. Con…

GPT模型为什么能生成有意义的文本

GPT模型的底层&#xff0c;其实是谷歌团队推出的Transformer模型。但是在GPT-3出现之前&#xff0c;大家一直对它没有多少了解。直到它的参数数量突破1750亿个的时候&#xff0c;它才建立起一个庞大的神经网络&#xff0c;这个神经网络最突出的特点是大数据、大模型和大计算。其…

宠物经济纵深观察:口红效应显著,呈可持续发展态势

七月以来&#xff0c;全国各地陆续开启高温模式。和人一样&#xff0c;“毛孩子们”同样也难耐高温&#xff0c;由此&#xff0c;围绕猫猫狗狗的“宠物经济”迅速升温&#xff0c;宠物冰垫、宠物饮水机、宠物烘干机......一系列宠物单品掀起夏日消费热潮。 就在几天前&#xf…

mysql的主从复制和读写分离:

mysql的主从复制和读写分离&#xff1a; 主从复制 面试必问&#xff1a;主从复制的原理 主从复制的模式&#xff1a; 1、mysql的默认模式&#xff1a; 异步模式 主库在更新完事务之后会立即把结果返回给从服务器&#xff0c;并不关心从库是否接受到&#xff0c;以及从库是…

汽车研发项目管理系统排行榜:五大热门汽车项目管理系统推荐

汽车研发项目管理软件在汽车制造行业中扮演着至关重要的角色&#xff0c;本文介绍了五款在汽车及零部件领域专业的项目管理软件。 一、 奥博思 PowerProject 企业级项目管理系统 奥博思 PowerProject 项目管理系统&#xff08;支持项目管理、项目集管理、项目组合管理三位一体…

LLM之RAG理论(十二)| RAG和Graph RAG对比

最近Graph RAG非常火&#xff0c;它来自微软的一篇论文《From Local to Global: A Graph RAG Approach to Query-Focused Summarization》&#xff0c;论文地址&#xff1a;https://arxiv.org/pdf/2404.16130。本文将对RAG 和 Graph RAG在架构和成本方面做简要分析。 一、RAG …

家里灰尘多又不想打扫。教你一招,省时省事,除尘很轻松

出差半个月前&#xff0c;我住在新装修的房子里两周。在新餐桌上铺了一块桌布&#xff0c;结果一周后布上就积了一层灰尘。而且&#xff0c;那些夜里&#xff0c;我经常听到妻子剧烈咳嗽&#xff0c;令人担心。她有中度肺部疾病&#xff0c;平时非常注意卫生&#xff0c;每天都…

mysql高阶语句:

mysql高阶语句&#xff1a; 高级语法的查询语句&#xff1a; select * from 表名 where limitsdistinct 去重查询like 模糊查询 排序语法&#xff1a;关键字排序 升序和降序 默认的排序方式就是升序 升序&#xff1a;ASC 配合order by语法 select * from 表名…

大模型应用—大模型赋能搜索

大模型赋能搜索 AI正在改变搜索体验,使其对我们来说更加智能、个性化和高效。 你可能会想,“但是谷歌已经足够好了!”首先,谷歌的搜索相关性和个性化是有代价的,那么跨不同媒体类型的搜索呢?对于最相关的信息格式,甚至是自动化某些任务,比如抓取网站、索引内容和搜索…

因为很会用工具,拿下了很多客户!

作为一名想要得到更多业绩的打工人&#xff0c;能提高工作效率的工具一定要拥有&#xff01; 今天&#xff0c;就给大家分享一个职场必备的提效神器&#xff0c;一起来看看它都有哪些功能吧&#xff01; 1、多渠道客源 它可以从多个渠道去获取你想要的客户资源&#xff0c;无…

CSS画边框线带有渐变线和流光边框实例

流光边框css流光边框动画效果_哔哩哔哩_bilibili流光边框css流光边框动画效果_哔哩哔哩_bilibili纯CSS写一个动态流水灯边框的效果&#xff5e;_哔哩哔哩_bilibili荧光边框CSS 动画发光渐变边框特效_哔哩哔哩_bilibili [data-v-25d37a3a] .flow-dialog-custom {background-col…

简单使用SpringMVC写一个图书管理系统的登入功能和图书展示功能

准备好前端的代码 这里已经准备好了前端的代码&#xff0c;这里仅仅简单的介绍登入功能&#xff0c;和展示图书列表的功能。 如图&#xff1a; 如上图所示&#xff0c;这里的前端代码还是比较多的&#xff0c;在这里我介绍&#xff0c;login.html还有book_list.html这两个。 l…

springboot智慧草莓基地管理系统--论文源码调试讲解

3 系统分析 当用户确定开发一款程序时&#xff0c;是需要遵循下面的顺序进行工作&#xff0c;概括为&#xff1a;系统分析-->系统设计-->系统开发-->系统测试&#xff0c;无论这个过程是否有变更或者迭代&#xff0c;都是按照这样的顺序开展工作的。系统分析就是分析…

golang 基础 泛型编程

&#xff08;一&#xff09; 示例1 package _caseimport "fmt"// 定义用户类型的结构体 type user struct {ID int64Name stringAge uint8 }// 定义地址类型的结构体 type address struct {ID intProvince stringCity string }// 集合转列表函数&#…

83. UE5 RPG 实现属性值的设置

在前面&#xff0c;我们实现了角色升级相关的功能&#xff0c;在PlayerState上记录了角色的等级和经验值&#xff0c;并在变动时&#xff0c;通过委托广播的形式向外广播&#xff0c;然后在UI上&#xff0c;通过监听委托的变动&#xff0c;进行修改等级和经验值。 在这一篇里&a…