栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

进程的深度理解

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

进程的深度理解

进程地址空间
什么是进程地址空间?
每个进程都有一个进程的地址空间,系统中可能存在多个进程,所以系统一定存在多个地址空间。
地址空间是如何被管理的呢?
答:先描述:地址空间本质是一个数据结构
struct mm_struct{}
再组织
为什么要有进程地址空间呢?
1.为了连续存储数据
2.封装性,保护数据,防止野指针等非法访问。
对于进程地址空间的理解:
进程地址空间不是物理内存,它是对物理内存的一种虚拟。
申请空间的本质:向内存索要空间,得到物理地址然后在特定区域申请没有被使用的虚拟地址,建立映射关系,返回虚拟地址即可。

进程的优先级
s=使用ps -l命令查看

UID:执行者的身份
PID:这个进程的代号
PPID:代表这个进程是由哪个进程发展衍生而来的,即这个该进程的父亲的代号
PRI(默认值是80):代表这个进程可被执行的优先级。其值越小优先级越高
NI(-20<=nice<=19):代表这个进程的nice值
PRI(new) = PRI(old)+nice (其中PRI(old)始终等于80)
使用top命令更改已存在进程的nice值
1.top
2.进入top后按”r“ -> 输入进程pid -> 输入nice值
进程的四个特性:
1.竞争性:系统进程数目众多,而CPU资源只有少量,甚至一个,所以进程之间是具有竞争性的。为了高效率完成任务,更合理竞争相关资源,便具有了优先级。
2.独立性:多进程运行,需要独享各种资源,多进程运行期间互不打扰
3.并行:多个进程在多个CPU下分别,同时进行运行,这称之为并行
4.并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

进程的创建:
fork系统调用接口函数——pid_t id = fork();
1.如何理解进程的创建:创建进程,本质是系统多了一个进程,多了一个进程,系统则就要多一组管理进程的数据结构+该进程对应的代码和数据。
2.fork为什么会有两个返回值?
pid_t id = fork();
{//创建子进程;
//给子进程创建task_struct
return id;}
3.fork父子执行顺序和代码和数据复制的问题-初始
进程数据=代码+数据
父进程创建子进程的时候,代码是共享的,数据是个私自有一份(写实拷贝)
通过数据私有,显示进程的独立性。
代码是逻辑,一般是不可修改的,数据通常下即可读又可写。
父子进程谁先运行是由linux内核中的调度器来决定的。
读取退出信息 echo ¥? 最近一次命令运行的退出码
写时拷贝(本质是修改页表与物理内存的映射关系)
通常父子代码共享,父子在不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。
父子代码共享是因为代码不可被修改(只读权限)这个权限是由页表设置的,各自私有代码的话会浪费空间。

进程等待
进程等待的必要性:
为了防止进程变成僵尸状态从而造成内存泄露,父进程可以通过进程等待的方式,回收子进程资源,获取子进程的退出信息
1.
pid_t wait(int *status); ->status:输出型参数,获取子进程退出状态,不关心则设置成为NULL
阻塞父进程,让其等待,等待子进程退出
失败返回-1,成功返回被等待进程pid
2.
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):若为正常终止子进程返回的状态,则为真。(查看进程是否正常退出)
等价于:!(status & 0x7F)
WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。
等价于((status>>8)&0xFF)

#include
 #include
   #include
   #include                                                                                                                                                   
   using namespace std;
   int main()
   {
       pid_t ret = fork();
       if(ret == 0)
      {
          //child
         cout<<"I am son: "<0 && (status& 0x7F)==0)//正常退出
          {
    cout<<"child exit code:"<<((status>>8)&0xFF<0)//异常退出
         {
              cout<<(status&0x7F)< 

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

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[]);
参数:
第一个参数代表你要执行什么,后续参数表示在命令行中如何调用执行(等同于命令行参数)
l(list):表示参数采用列表
v(vector):参数用数组
p(path):有p自动搜索环境变量PATH
e(env):表示自己维护环境变量
函数解释
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回
如果调用出错则会返回-1
即只有当调用exec函数失败的时候才会有返回值

进程终止
程序退出场景:
1.代码运行完毕,结果正确
2.代码运行完毕,结果不正确
3.代码异常终止
正常退出的情况:
·从main返回
·调用exit(库函数)
·_exit(系统调用)
异常退出的情况:
·ctrl+c 信号终止

调用exit的过程:

return:叫做终止函数,在main函数中return相当于进程退出。
在其他函数中renturn相当于函数返回值。
exit(库函数):终止整个进程,任何地方调用都会终止进程
_exit(系统调用接口):
与exit的区别有1.exit会执行用户定义的清理函数
2.exit会刷新缓冲区,关闭所有打开的流
而_exit则会直接退出进程。啥事都不干。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/299815.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号