Linux系统进程控制

1、进程创建

shell命令行启动程序指令皆是创建了进程,我们通常通过调用fork()函数创建子进程。注意进程皆是操作系统创建的,父进程只是通过fork函数去创建子进程,本质还是由操作系统去完成的

1.1、fork()函数用法简介

 调用fork后,操作系统内核将:

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

1.2、fork函数返回值

子进程返回0,父进程返回的是子进程的pid

原因:fork之后进入内核,申请内存构建子进程PCB、虚拟内存、页表,将子进程设置R状态,放入调度队列,由于创建子进程之后父子进程共享代码,所以父子进程都会有return返回值。返回值返回给变量本质发生了写时拷贝,改变了子进程对应页表的指向,数据映射到了其他区域

还有一种理解是,ret一开始是父进程创建的,由于fork之后,返回值有两个都要放入到变量ret中,所以发生写时拷贝(父进程要对ret赋值,子进程也要)。

1.3、写时拷贝

由于进程要独立,代码不可修改,数据可改,所以默认数据各有一份,但是内存是有限度的,如果把父进程数据全部再拷贝一份,那么太浪费内存,甚至导致fork失败。通常通过写时拷贝实现,就是当父或子进程修改数据时,将要修改的数据拷贝一份,让子进程页表指向新的重复数据在发生修改

为啥要有写时拷贝呢?父子进程创建的时候,直接数据各自拷贝一份不就完了?

1、不是所有数据都需要拷贝一份对于只读的数据,父子都拷贝一份浪费资源

2、fork时,创建数据结构,如果还要对数据拷贝一份,fork效率降低

3、fork本身就是向系统要更多的资源,要更多的资源相较于要更少的资源容易失败。

 2、进程终止

2.1、进程退出场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

 代码跑完使用退出码标识,命令行使用echo $?查看,没跑完使用信号

2.2、进程退出方法

main函数中,return那个数据就是退出码,通常给系统看,默认0代表正确,非0代表错误。退出码可以人为的定义,也可以使用系统的错误码。不同的错误码映射到不同的字符串

 exit表示终止进程,刷新缓冲区,_exit是系统函数,不会刷新,两者返回值就是退出码,return只有在main函数中才能终止进程

 2.3、站在OS角度,如何理解进程终止

进程终止的核心思想就是归还资源:

1、释放为了管理进程所维护的所有的数据结构对象

2、释放程序代码和数据占用的内存空间

3、取消改进程的链接关系

第一个释放,通常不是把数据结构和对象销毁,而是设置为不用状态,保存起来,通常保存在数据结构池

第二个释放不是将代码和数据清空,只是把内存设置为无效

 3、进程等待

3.1、为啥要等待

1、回收僵尸进程,解决内存泄露,释放空间

2、需要获取子进程的运行结束状态

3、尽量父进程要晚于子进程退出,可以规范化进行资源回收

3.2、进程等待的方法

wait,等待任意一个子进程,当子进程退出,wait就可以返回

成功返回子进程pid,失败返回-1,status为输出型参数,不关心可设置为NULL

 

 waitpid的方法:

pid_t waitpid(pid_t pid,int*status,int options);

 

status是一个输出型参数,从子进程的task_struct中拿到,低7位是信号,如果信号为0说明正常退出(status& 0x7F),如果退出状态( (status>>8) & 0xff )为0,说明正常退出

1、为啥要使用输出型参数status,是否可通过设置全局变量,告知父进程子进程的退出码?绝对不行,会发生写时拷贝

2、waitpid中的pid是从那里拿到的呢?虽然子进程已经退出了,但是子进程的task_struct并没有立即释放,只有等待成功,内存才释放,所以从控制块中可以拿到子进程的status(这里是退出码)

 

 第一个参数Pid =-1,等待任意一个子进程,与wait等效,Pid>0,等待进程ID与Pid相等的子进程

第三个参数options,WNOHANG:若pid指定的指定的子进程没有结束,waitpid()函数返回0,不予以等待。若正常结束,返回该子进程的id

将WNOHANG传给第三个参数时称为非阻塞式等待,传0称为阻塞式等待

在非阻塞式等待三种状态:1、失败:子进程还没退出,下次在检测 2、成功:子进程退出,已经返回 3、失败:真正的等待失败

4、进程程序替换

fork创建子进程有两个作用:

1、想让子进程执行父进程代码的一部分

2、想让子进程执行与父进程不同的事

进行进程替换时并没有创建新进程,没有PCB,没有改变PID,只是发生了写时拷贝,本质上用该程序的代码和数据修改页表的映射

4.1、替换函数

 l(list):表示参数采用列表

v(vector>:参数使用数组

p(path):有p自动搜索环境变量

e(env):表示自己维护环境变量

 这里没有替换成功不知道错在哪里了

 在proc中使用程序替换execl函数去执行我们写的程序

也可将环境变量由proc传给excmd

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值