进程管理(电脑进程管理器)
进程管理(电脑进程管理器)
linux服务器开发相关视频解析:
360度无死角讲解进程管理,调度器的5种实现
linux多线程之epoll原理剖析与reactor原理及应用#include<stdio.h>#include<string.h>#include<stdlib.h>#include<unistd.h> voidmain(){charstr[6]="hello"; pid_tpid=fork(); if(pid==0) { str[0]='b';printf("子进程中str=%s\n",str);printf("子进程中str指向的首地址:%x\n",(unsignedint)str); }else { sleep(1);printf("父进程中str=%s\n",str);printf("父进程中str指向的首地址:%x\n",(unsignedint)str); } }
子进程中str=bello
子进程中str指向的首地址:bfdbfc06
父进程中str=hello
父进程中str指向的首地址:bfdbfc061、背景介绍
这里就涉及到物理地址和逻辑地址(或称虚拟地址)的概念。
从逻辑地址到物理地址的映射称为地址重定向。分为:
静态重定向--在程序装入主存时已经完成了逻辑地址到物理地址和变换,在程序执行期间不会再发生改变。
动态重定向--程序执行期间完成,其实现依赖于硬件地址变换机构,如基址寄存器。
逻辑地址:CPU所生成的地址。CPU产生的逻辑地址被分为 :p (页号) 它包含每个页在物理内存中的基址,用来作为页表的索引;d (页偏移),同基址相结合,用来确定送入内存设备的物理内存地址。
物理地址:内存单元所看到的地址。用户程序看不见真正的物理地址。用户只生成逻辑地址,且认为进程的地址空间为0到max。物理地址范围从R+0到R+max,R为基地址,地址映射-将程序地址空间中使用的逻辑地址变换成内存中的物理地址的过程。由内存管理单元(MMU)来完成。
可执行程序在存储(没有调入内存)时分为代码区,数据区,未初始化数据区三部分。
(1)代码区存放CPU执行的机器指令。通常代码区是共享的,即其它执行程序可调用它。代码段(code segment/text segment)通常是只读的,有些构架也允许自行修改。
(2)数据区存放已初始化的全局变量,静态变量(包括全局和局部的),常量。static全局变量和static函数只能在当前文件中被调用。
(3)未初始化数据区(Block Started by Symbol,BSS)存放全局未初始化的变量。BSS的数据在程序开始执行之前被初始化为0或NULL。
代码区所在的地址空间最低,往上依次是数据区和BSS区,并且数据区和BSS区在内存中是紧挨着的。
text段和data段在编译时已分配了空间,而bss段并不占用可执行文件的大小,它是由链接器来获取内存的。
bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。
数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含数据段和BSS段的整个区段此时通常称为数据区。
可执行程序在运行时又多出了两个区域:栈区和堆区。
(4)栈区。由编译器自动释放,存放函数的参数值,局部变量等。每当一个函数被调用时,该函数的返回类型和一些调用的信息被存储到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。栈区是从高地址位向低地址位增长的,是一块连续的内在区域,最大容量是由系统预先定义好的,申请的栈空间超过这个界限时会提示溢出,用户能从栈中获取的空间较小。
(5)堆区。用于动态内存分配,位于BSS和栈中间的地址位。由程序员申请分配(malloc)和释放(free)。堆是从低地址位向高地址位增长,采用链式存储结构。频繁地malloc/free造成内存空间的不连续,产生碎片。当申请堆空间时库函数按照一定的算法搜索可用的足够大的空间。因此堆的效率比栈要低的多。
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
2、fork
fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了"写时复制"技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
fork时子进程获得父进程数据空间、堆和栈的复制,所以变量的地址(当然是虚拟地址)也是一样的。
每个进程都有自己的虚拟地址空间,不同进程的相同的虚拟地址显然可以对应不同的物理地址。因此地址相同(虚拟地址)而值不同没什么奇怪。
具体过程是这样的:
fork子进程完全复制父进程的栈空间,也复制了页表,但没有复制物理页面,所以这时虚拟地址相同,物理地址也相同,但是会把父子共享的页面标记为"只读"(类似mmap的private的方式),如果父子进程一直对这个页面是同一个页面,知道其中任何一个进程要对共享的页面"写操作",这时内核会复制一个物理页面给这个进程使用,同时修改页表。而把原来的只读页面标记为"可写",留给另外一个进程使用。
这就是所谓的"写时复制"。正因为fork采用了这种写时复制的机制,所以fork出来子进程之后,父子进程哪个先调度呢?内核一般会先调度子进程,因为很多情况下子进程是要马上执行exec,会清空栈、堆…这些和父进程共享的空间,加载新的代码段…,这就避免了"写时复制"拷贝共享页面的机会。如果父进程先调度很可能写共享页面,会产生"写时复制"的无用功。所以,一般是子进程先调度滴。
假定父进程malloc的指针指向0x12345678, fork 后,子进程中的指针也是指向0x12345678,但是这两个地址都是虚拟内存地址 (virtual memory),经过内存地址转换后所对应的 物理地址是不一样的。所以两个进城中的这两个地址相互之间没有任何关系。
(注1:在理解时,你可以认为fork后,这两个相同的虚拟地址指向的是不同的物理地址,这样方便理解父子进程之间的独立性)
(注2:但实际上,linux为了提高 fork 的效率,采用了 copy-on-write 技术,fork后,这两个虚拟地址实际上指向相同的物理地址(内存页),只有任何一个进程试图修改这个虚拟地址里的内容前,两个虚拟地址才会指向不同的物理地址(新的物理地址的内容从原物理地址中复制得到))3、exec家族
exec家族一共有六个函数,分别是:<spanstyle="font-family:MicrosoftYaHei;font-size:12px;"> (1)intexecl(constchar*path,constchar*arg,......); (2)intexecle(constchar*path,constchar*arg,......,char*constenvp[]); (3)intexecv(constchar*path,char*constargv[]); (4)intexecve(constchar*filename,char*constargv[],char*constenvp[]); (5)intexecvp(constchar*file,char*constargv[]); (6)intexeclp(constchar*file,constchar*arg,......);</span>
其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。
飞影电影城(为何全球仅有5座环球影城?)飞影电影城(为何全球仅有5座环球影城?)9月1日,北京环球影城结束为期3个多月的压力内测后,开启了试运行。19天后的9月20日,北京环球影城将正式开园。这是亚洲第三座全球第五座环球
dnf怎么组队(未央怎么组队)作者明空云上长安是非常具有特色的搬砖摸金本,且玩法新颖,既有稳赚不赔的稳定搬砖玩法,又有高投入高回报的摸金玩法。不过这个副本相较于风暴航路这类常规砖厂略显复杂,本文就带刚进入未央的
500人派对不戴口罩近日500人派对不戴口罩登录了热搜,也是在网上引起了网友们的关注,那么很多小伙伴可能还不清楚具体的情况如何,小编也是在网上查阅了一些信息,那么接下来就分享给大家来了解下500人派对
巴黎正式推行户外强制戴口罩不戴口罩者直接罚款近日巴黎正式推行户外强制戴口罩不戴口罩者直接罚款登录了热搜,也是在网上引起了网友们的关注,那么很多小伙伴可能还不清楚具体的情况如何,小编也是在网上查阅了一些信息,那么接下来就分享给
什么人不能打新冠疫苗(新冠疫苗不强制为啥还要证明)根据近阶段的接种情况为进一步落实好新冠病毒疫苗接种工作及时为公众和接种人员提供新冠病毒疫苗接种禁忌和注意事项的科学识别与应对新冠病毒疫苗接种禁忌和注意事项指引(第三版)来啦更新了3
新冠疫苗什么人不能打(七种病不能打疫苗)随着奥密克戎等变异毒株的出现,现有的新冠疫苗可能会受到影响,而且随着时间推移,体内抗疫的保护力也会降低。因此为了提高免疫力,接种新冠疫苗加强针或是必不可少的。目前不少地方都相继开展
狂犬疫苗多久打有效(小孩千万不要打狂犬疫苗)近日,杭州萧山一女孩姜某因被狗伤后未及时注射疫苗而引发狂犬病导致脑死亡的事件在网络热议。根据萧山区疾病预防控制中心通报称,姜某某家今年3月曾从外捡回一只流浪狗,因4月该犬出现乱咬犬
狂犬疫苗多久内打有效(医生不建议打狂犬疫苗)夏季是狂犬病的高发季。被猫狗抓(咬)伤后,应及时接种狂犬疫苗,并视情况注射狂犬病免疫球蛋白。究竟多久接种疫苗才算及时呢?狂犬疫苗必须在24小时内接种才有效吗?如果超过24小时还没接
狂犬病为什么治不好(打狂犬疫苗5年后死了)去年底,杭州女孩疑似患狂犬病致脑死亡的事件冲上热搜,再次将狂犬病这一病症暴露在众人眼前。被动物抓伤后放任不管不及时给家养动物接种兽用狂犬疫苗这些情况均藏有潜在的危险信号。一旦发病,
hpv疫苗二价四价九价区别(二价四价九价HPV疫苗该咋选?)hpv疫苗二价四价九价区别(二价四价九价HPV疫苗该咋选?)2020年5月18日,武汉十岁女孩可可接种了国产二价HPV疫苗,成为了国产二价HPV疫苗的首位接种者。图片来源研究所留言
hpv是什么疫苗多少钱(彩虹医生hpv疫苗是骗局吗)每经记者舒冬妮7月初的一天下午,张丽在家里百无聊赖地玩着手机,心情有些烦闷。她小半年前在社区医院预约接种的疫苗,到现在还没打上。张丽想要接种的是九价HPV疫苗,这种疫苗可以预防女性