科林Linux_3 进程

一、进程基础

操作系统基础的执行单元,调度单位

静态数据:只占用磁盘空间,不消耗其他资源

动态数据:磁盘 内存 CPU

1. 编译器将源码编译成一个可执行文件.exe/.elf

2. 运行后系统生成一个同名的进程

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

3. 进程在创建时,要分配虚拟内存(线程不分配内存)

进程是最小的分配资源单位,也是调度单位

因为每个进程创建时分配内存资源,所以被成为分配资源单位

进程没有实体,由复杂的逻辑关系构成

进程的生存环境,形态:

PCB 进程控制块,是一个300多个成员的结构体,记录了详细的进程信息

虚拟内存地址通过内存映射访问真正的物理内存地址

进程中虚拟地址不同,但是指向相同的物理地址,实现共享内存【内核空间】

不同的进程内存独立【用户空间】(以防互相影响,内核空间只有系统拥有权限,不怕被修改)

程序优化:系统占用以及系统开销(CPU 内存)

内存基本单位:Page(页) 1Page=4KB=4096Bytes

malloc(8192) ——> 一次分配两页内存

malloc(5000) ——>分配两页内存,对剩余内存空间进行限制访问

malloc(3192) ——>检查是否使用完毕,并解除限制

内存的权限:PROT_READ 只读 PROT_WRITE 只写 PROT_EXEC 执行 PROT_NONE 无权限

虚拟内存:32位系统,三级间接寻页:1024*1024*1024=GB

63位系统,四级间接寻页,1024*1024*1024*1024=TB


 

二、进程状态以及状态转换

进程的五种常态

就绪态Ready:进程已准备除处理器外所需资源,等待cpu资源

运行态Running:占用cpu,正在执行指令

阻塞态Blocked:由于进程等待某种条件(如I/O操作或进程同步)被暂停(释放cpu),在条件满足之前无法继续执行。

挂起态Suspend:由于用户和系统的需要被暂停(释放cpu),把进程从内存转到外存

终止态Terminated:进程退出,释放进程内存资源

阻塞态和挂起态的区别?

1. 阻塞态可以被中断,在等待的资源得到满足后,进入就绪状态;挂起态无法被中断,只有将其挂起的对象唤醒后,才可以让其继续

2. 阻塞态释放了cpu,但是阻塞的进程还在内存中;挂起的进程通过swp交换到外存中(磁盘空间)

3. 阻塞态发生在进程等待资源时,挂起是由于用户和系统需要

任意状态都可以切换为终止态

Linux独有的状态

僵尸态Zombie:子进程退出结束,但是PCB残留,导致内存泄漏,叫做僵尸进程

孤儿态Orphan:父进程先挂掉,子进程会被1号进程领养,我们可以理解为操作系统,或者说父进程先结束,子进程必须被操作系统领养,因为无主进程,一直僵尸浪费资源,我们将这种进程称之为孤儿进程。 还会将自己变成后台进程。

分时复用原则(时间片)

多进程共享使用CPU,每个进程按时间片(10us)使用,而后快速切换,既可以让多个进程共享使用,以提高cpu使用率

单任务操作系统(软盘) ——> 多任务操作系统(充分共享使用硬件)

大多数系统的程序都是并发执行的(快速交替执行)

保存与恢复处理器现场

CPU原件:控制器、寄存器(Eax,Ebx,Edx,Eflag....)、编码器、译码器、运算器

寄存器:

内存:快速缓存数据及计算过程

每个进程都有自己独立的PCB,每个PCB都有一个内核栈指针kernel_ptr,指向自己的内核栈

多任务基准:分时+保存与恢复
 

什么是线程?什么是进程?

进程或者线程就是寄存器(CPU的访问权)和栈(内核栈)

进程、线程、纤程:调度单位

协程、管程:管理单元

超线程:硬件,模拟多核

二、进程源语

2.1 进程源语函数

系统支持进程开发提供的一系列API函数接口

pid_t pid;进程id类型

pid_t pid=getpid(void);//调用获取进程pid

2.1.1 fork() 创建子进程

pid_t pid=fork(); //创建子进程,执行一次创建一个进程

子进程与父进程pid连续,父进程最小

父进程调用fork,系统创建子进程,子进程从fork之后执行

关于子进程继承的问题?

 1. 拷贝继承

2. 区分父子进程代码段,实现父子执行不同的代码任务

使用fork的返回值pid进行父子进程的区分

子进程不允许踏出工作区

1. 永久阻塞 2. 进程退出

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>//parent start
int main(){pid_t pid;pid=fork();  //创建子进程if(pid>0){printf("parent pid %d, Running...\n",getpid());}else if(pid==0){//child startprintf("child pid %d, Running...\n",getpid());while(1)sleep(1);//child end}else if(pid==-1){perror("fork call failed");exit(0);}printf("self id %d\n",getpid());while(1)sleep(1);return 0;
}
//parent end

windows的printf自带刷新缓冲区

linux下\n刷新缓冲区

3. 创建多进程

循环创建多进程

int i;
for(int i=0;i<3;i++){pid=fork();if(pid==0)break;
}

4. 子进程执行fork,并且得到返回值0

两个进程执行同一个fork()

栈帧

不同的函数有各自的函数栈帧地址,其他位置无法访问函数内部资源

父子进程可以共享同一个函数的栈帧地址,实现调用同一个函数,执行一部分

gdb可以实现栈帧的跳转

第一版 fork,拷贝继承版本

如果子进程不需要拷贝父进程数据,而是自行获取用户空间,那么父进程的拷贝流程和开销变成无意义的系统开销

第二版 vfork,无拷贝过程,但是不能直接使用

通过vfork创建的子进程没有用户空间,需要用户自行生成用户层,vfork必须结合execl函数使用

第三版 fork,读共享写复制

读时共享,虚拟地址不同,物理地址相同

父子进程写都会导致子进程复制共享内存数据

例题:

2*9+1=19个子进程

2*10-1=19

2.1.2 execl() 进程重载

系统名都是程序,执行命令时创建进程,完成特定功能

重载只替换进程工作数据,与PCB进程信息无关

    execl("程序路径",argv[0]/*文件名|命令*/,argv[1]/*参数*/,NULL/*哨兵,结束*/);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>int main(){pid_t pid;pid=fork();if(pid>0){printf("parent pid %d\n",getpid());while(1)sleep(1);}else if(pid==0){printf("child pid %d\n",getpid());printf("child execl...\n");execl("/usr/bin/firefox","firefox","www.bilibili.com",NULL);printf("execl failed\n");exit(0);}else if(pid<0){printf("fork failed\n");exit(0);}return 0;
}

使用execl

1. vfork创建子进程无法直接使用,必须重载才可以使用

2. 重载方便程序的功能扩展,很多现有的命令在进程中可以直接使用

3. 动态迭代

在程序不下线的情况下,动态更新功能

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>int main(){pid_t pid;printf("MyWeb Vesion 1.o Running...\n");while(1){pid=fork();if(pid==0)break;sleep(5);}if(pid==0)execl("./MOD/mod1","mod1",NULL);return 0;
}

此时只需要修改mod1.c文件内容并重新编译,就可以在线修改主程序的功能

2.1.3 wait() waitpid() 回收函数

僵尸态Zombie:子进程退出结束,但是PCB残留,导致内存泄漏,叫做僵尸进程

_EXIT(0) 结束进程时,完全释放了用户空间,释放了部分内核空间,只有PCB残留——内存泄漏

危害:1. 内存泄漏 2. 僵尸进程残留PCB无法给新进程使用,影响进程创建数量

系统为何要保留PCB?

僵尸进程需要父进程进行手动回收、检验子进程是否正常退出

关于ps -aux进程状态stat的中Ss、S<l、Ssl、SLl、SNl、R、R+的解释_ps aux 进程 tl sl-CSDN博客

int stat;
pid_t zpid=wait(NULL);    //表示只回收pcb不进行回收的验证操作,返回值为僵尸进程pid
pid_t zpid=wait(&stat);    //返回子进程状态

wait() 失败原因:没有子进程立即失败
wait() 是阻塞函数,阻塞回收,如果子进程未结束,无需回收,wait阻塞等待

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>int main(){pid_t pid;pid_t zpid;pid=fork();if(pid>0){zpid=wait(NULL);printf("parent pid %d, child pid %d, zpid %d\n",getpid(),pid,zpid); while(1)sleep(1);}else if(pid==0){printf("child alive 10s\n");sleep(10);exit(0);}else {perror("fork failed");exit(0);}return 0;
}

只有父进程可以回收子进程,其他进程无法代替 

init 1号进程没有父进程,称作根进程

子进程先于父进程死亡,必然会成为僵尸;父进程先于子进程死亡,子进程必然会成为孤儿

waitpid(pid_t pid,int* state,WNOHANG/*非阻塞关键字*/);    
//返回值:>0 成功返回| -1 失败| =0 非阻塞返回pid==-1 回收任意子进程pid>0 回收指定子进程(进程号)pid==0 同组回收pid<-1 跨组回收(-进程组号)

waipid() 支持非阻塞回收,相比wait() 更加灵活。在等待回收时,父进程可以执行自己的任务和代码。

Linux之进程的基本概念(进程,进程组,会话关系)_linux 会话id-CSDN博客

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>int main(){pid_t pid;pid_t zpid;pid=fork();if(pid>0){while((zpid=waitpid(-1,NULL,WNOHANG))!=-1){if(zpid>0)printf("parent pid %d, child pid %d, zpid %d\n",getpid(),pid,zpid); else if(zpid==0){printf("parent exec jobs\n");sleep(1);}}while(1)sleep(1);}else if(pid==0){printf("child alive 10s\n");sleep(10);exit(0);}else {perror("fork failed");exit(0);}return 0;
}

2.2 多进程拷贝

单进程的CPU使用资源受限,可以采用多进程模型,获取更多的时间片,加快任务完成速度,提高效率

两种常见的多进程:多进程任务较为复杂;多进程任务单一

串行:逐次完成任务

并行:多核CPU且每一个工作进程都能加载到对应的处理核心上【由CPU决定,不可控】

并发:单个处理器,逻辑上同步执行【有并行的概率】多进程并发、多线程并发

程序的执行效率由cpu的占用及使用频率决定,占用越多效率越高

单进程模型因阻塞或其他原因放弃本轮cpu使用,但是多进程或者多进程模型,根据就近原则,放弃的进程可以交替给相邻的进程,让任务继续

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

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

相关文章

网络变压器的磁芯在使用中起着至关重要的作用

网络变压器的磁芯在使用中起着至关重要的作用。它主要有以下几个功能&#xff1a; 1. **提供磁通路径**&#xff1a;磁芯为变压器中电磁感应提供了闭合的磁通路径。这有助于提高变压器的效率&#xff0c;因为它确保了磁场能够有效地通过绕组。 2. **减少能量损失**&#xff1…

开发环境中的调试视图(IDEA)

当程序员写完一个代码时必然要运行这个代码&#xff0c;但是一个没有异常的代码却未必满足我们的要求&#xff0c;因此就要求程序员对已经写好的代码进行调试操作。在之前&#xff0c;如果我们要看某一个程序是否满足我们的需求&#xff0c;一般情况下会对程序运行的结果进行打…

Spring框架九大核心功能全面揭秘(一)

目录 资源管理 Java资源管理 1、来个Demo 2、原理 Spring资源管理 1、资源抽象 Resource WritableResource 2、资源加载 3、小结 环境 1、Environment 2、配置属性源PropertySource 3、SpringBoot是如何解析配置文件 类型转换 1、类型转换API …

Ubuntu+Systemd服务+实现开机自启

1.创建一个新的 systemd 服务文件 现在随便一个地方创建txt文档 如果想要启动sh脚本&#xff0c;就把下面的代码输入到txt文档中 [Unit] DescriptionRun Python script on specific executable run Afternetwork.target[Service] Typesimple ExecStart/home/tech/run_on_exe…

光接入网络的超宽带半导体光放大器

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 新颖的双有源层结构获得宽增益光谱&#xff0c;应用于多波单纤双向光放大 ----翻译Xiao Sun等人2016年撰写的文章&#xff0c;文中给出了宽光谱SOA的一种新颖的结构设计方法和仿真结果&#xff0c;但并未给…

社交媒体数据恢复:Instagram

Instagram数据恢复方法 在本文中&#xff0c;我们将详细介绍如何恢复在Instagram上删除的照片、消息和其他数据。请注意&#xff0c;这些方法可能适用于其他类型的社交媒体数据&#xff0c;但具体效果取决于数据的实际状态和存储设备的健康状况。 一、准备工作 在开始数据恢…

四川赢涟电子商务有限公司深耕抖音电商服务

在当今数字化、网络化高速发展的时代&#xff0c;电子商务行业异军突起&#xff0c;成为推动经济增长的重要力量。四川赢涟电子商务有限公司凭借其敏锐的市场洞察力和创新精神&#xff0c;专注于抖音电商服务&#xff0c;致力于为广大消费者提供便捷、高效、个性化的购物体验&a…

kafka启动报错(kafka.common.InconsistentClusterIdException)

文章目录 前言kafka启动报错(kafka.common.InconsistentClusterIdException)1. 查找日志2. 定位问题/解决 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不…

基于YOLOv8+Pyqt5火焰烟雾检测系统

1、YOLOv8的基本原理 YOLOv8是一种前沿的目标检测技术&#xff0c;它基于先前YOLO版本在目标检测任务上的成功&#xff0c;进一步提升了性能和灵活性。主要的创新点包括一个新的骨干网络、一个新的 Ancher-Free 检测头和一个新的损失函数&#xff0c;可以在从 CPU 到 GPU 的各…

Golang | Leetcode Golang题解之第47题全排列II

题目&#xff1a; 题解&#xff1a; func permuteUnique(nums []int) (ans [][]int) {sort.Ints(nums)n : len(nums)perm : []int{}vis : make([]bool, n)var backtrack func(int)backtrack func(idx int) {if idx n {ans append(ans, append([]int(nil), perm...))return}…

数据分析学习资源(未完)

1、PDF 数据分析自学攻略 增长黑客&#xff08;AARRR&#xff09; 量化思维

glib读写ini文件测试

函数简介 g_key_file_load_from_file g_key_file_load_from_file() 是 GLib 库中的一个函数&#xff0c;用于从指定的文件路径加载一个键值对文件&#xff08;通常是一个 .ini 风格的配置文件&#xff09;。这个函数是 GKeyFile 结构体相关API的一部分&#xff0c;GKeyFile 用…

C++面向对象程序设计 - 重载运算符进一步讨论

函数重载就是对一个已有的函数赋予新的含义&#xff0c;使之实现新的功能。因此一个函数名就可以用来代表不同功能的函数&#xff0c;也就是一名多用。运算符也可以重载&#xff0c;即运算符重载&#xff08;operator overloading&#xff09;。 一、非成员、非友元的重载运算…

STM32F103学习笔记 | 1.Keil5详细安装教程

Keil5详细安装教程 https://www.keil.com/download/product/

使用API有效率地管理Dynadot域名,自查账户信息

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

大型组织企业 怎么实现便捷高效的跨地区文件交换?

大型组织企业&#xff0c;尤其是银行、邮政、大型集团、跨国企业等&#xff0c;都会存在多个分支机构&#xff0c;会面临跨地区文件交换的场景和需求。 跨地区文件交换可能会遇到以下问题&#xff1a; 1、网络带宽限制&#xff1a;跨国或跨大陆传输时&#xff0c;网络带宽可能…

CC攻击频发,企业如何做好网络安全,该怎么防护能免遭CC攻击?

在当前网络现状下&#xff0c;随着信息技术的飞速发展&#xff0c;网络攻击手段也愈发多样化和复杂化。其中&#xff0c;CC攻击作为一种针对Web应用层的拒绝服务攻击&#xff0c;其危害日益凸显&#xff0c;对企业和个人造成了严重的威胁。下面我们就从多个角度详细分享关于CC攻…

LyricWikia, 一个让你玩物丧志的Python库

文章目录 LyricWikia: Python的歌词查找库背景LyricWikia是什么&#xff1f;安装简单的库函数使用方法场景示例搜索并显示歌词获取歌手的热门歌曲搜索并下载歌词 常见问题和解决方案总结 LyricWikia: Python的歌词查找库 背景 LyricWikia是一个用于查找和获取歌曲歌词的Python…

【项目实战】基于高并发服务器的搜索引擎

【项目实战】基于高并发服务器的搜索引擎 目录 【项目实战】基于高并发服务器的搜索引擎搜索引擎部分代码index.htmlindex.hpplog.hppparser.cc&#xff08;用于对网页的html文件切分且存储索引关系&#xff09;searcher.hpputil.hpphttp_server.cc&#xff08;用于启动服务器和…

【Linux的git操作】

Linux学习笔记---010 Linux的git操作1、什么是gitee2、git 准备工作2.1、查看是否安装了 git 版本工具2.2、安装 git 工具/更新成最新版本2.3、在gitee上创建远程仓库&#xff08;略&#xff09;2.4、提交file的初始化操作 3、git的“三板斧”3.1、add3.2、commit3.3、push3.4、…