做社交网站的预算,成都网络营销网站,网站建设实验总结报告,微信小程序怎么做目录
一、进程创建
1、实例
2、fork函数详解
(1)fork函数模板
(2). fork() 函数的工作原理
(3). fork() 返回值和错误处理
3、如何理解进程创建过程
二、进程终止
1、终止是在做什么#xff1f;
2、进程终止#xff0c;有三种情况
3、进程如何终止#xff1f;
三…目录
一、进程创建
1、实例
2、fork函数详解
(1)fork函数模板
(2). fork() 函数的工作原理
(3). fork() 返回值和错误处理
3、如何理解进程创建过程
二、进程终止
1、终止是在做什么
2、进程终止有三种情况
3、进程如何终止
三、进程等待
1、为什么要等待
2、怎么等待
1wait函数
2waitpid函数
四、阻塞等待与非阻塞等待 一、进程创建
1、实例
int main()
{ pid_t pid;pid fork();if(pid 0){//创建失败printf(forkfailed\n);return 1;//终止程序退出码设置为1以显示错误退出}else if(pid 0){//子进程printf(I am a child process!,chailPID:%d\n,getpid());}else {//父进程返回值0 printf(I am a father process!,fatherPID:%d,childPID:%d\n,getpid(),pid);}return 0;
}2、fork函数详解
(1)fork函数模板
#include unistd.hpid_t fork(void);fork() 函数返回两次 一次在父进程中返回子进程的进程 ID PID), 一次在子进程中返回 0。 如果 fork() 失败返回一个负值表示错误。
(2). fork() 函数的工作原理
调用 fork() 函数时操作系统会创建一个新的进程子进程该子进程是调用进程父进程的一个副本。 新进程子进程会复制父进程的地址空间、代码段、数据段和堆栈等信息但是它们会有各自独立的内存空间。 子进程的 PID 和父进程不同但是它们会继承父进程的文件描述符和信号处理器等。 fork() 后父进程和子进程同时开始执行代码但是它们执行的顺序和执行的内容可能有所不同具体取决于操作系统的调度策略。
(3). fork() 返回值和错误处理
如果 fork() 返回值 0则这是在父进程中返回的子进程的 PID。 如果 fork() 返回值等 0则这是在子进程中返回的。 如果 fork() 返回值 0则表示创建新进程失败可能是因为系统资源不足或者其他错误。
3、如何理解进程创建过程
进程内核的相关管理数据结构task_struct mm_struct 页表 代码和数据 上述对进程的描述是从进程具有独立性的角度出发去看待 进程具有独立性说明有各自的PCB、页表、数据 而代码虽然是共享的但是权限是只读的不能修改因此互不影响
当使用fork创建进程时 分配新的内存块和内核数据结构给子进程 将父进程部分数据结构内容拷贝给子进程 添加子进程到系统进程列表中 fork返回开始调度器调度
为什么给父进程返回子进程的PID给子进程返回0 前者因为方便父进程对子进程标识的管理 后者因为返回创建成功与否的标志
fork常规用法子进程执行和父进程类似的任务 / 子进车执行全新的任务
fork调用失败的原因 系统进程太多资源不够
二、进程终止
1、终止是在做什么
释放曾经的代码和数据所占据的空间 释放内核数据结构但是task_struct延后Z状态的僵尸进程
2、进程终止有三种情况
a、代码跑完结果正确
b、代码跑完结果不正确 那么代码跑完正确不正确我怎么知道怎么判断 可以通过进程的退出码决定
c、代码没有跑完异常提前退出 如果进程异常退出码就没有意义 但是如果出现了异常我想知道为什么出现异常出现了什么异常 出现什么异常通过看退出信号是多少判断 进程出现异常本质是因为进程收到了OS发给进程的信号 例如kill -9 XXX 这个命令本质是XXX进程收到了OS的信号为9就会以killed的形式终止
那么如何判断进程终止是处于上述三种情况的哪一种 1、先确认是否异常退出 2、如果不是异常就说明代码跑完看退出码
因此衡量一个进程退出到底是什么情况 需要两个数字退出码跑完 退出信号异常的组合 而这个退出信息要给父进程bash知道确保父进程对子进程的管理 因此进程的PCB task_struct就会存在两个属性 int sig_code int exit_code 在vs编程运行崩溃时发生了什么 是因为进程做了不该做的事情OS杀掉了进程
main函数的返回值是什么意思 int main() { //... return 0; } 是本进程的退出码这个退出码交给父进程让父进程知道子进程退出的情况成功 / 失败且失败的原因是什么 退出码为0表示成功 退出码不为0表示失败
查看退出码
echo $?
这个问号是父进程bash获取到的最近一个子进程退出的退出码
返回值返回给谁返回给父进程bash 这个返回值是退出码退出码交给bash之后如果不是0表示错误 此时bash会通过一定的形式将退出码转化为错误描述strerrot函数 char* strerrot(int erronum)错误码转化为错误描述 以下是常见错误
错误码 (errnum)错误描述 (错误码对应的错误描述)1操作不允许的权限2系统找不到指定的文件3系统找不到指定的路径4系统没有空间供处理此操作5输入/输出错误6设备不可用7存储设备无法访问8请求的文件描述符超出范围9文件已经打开10操作过多的文件系统11资源暂时不可用12文件名过长13权限不足拒绝访问14资源暂时不可用尝试再次
main函数为什么要有返回值 这是因为本质上我们自己写的所有进程任务都是bash的子进程 而子进程的运行状况如何父进程得知道便于对子进程的管理 所以父进程怎么知道子进程的状态呢通过main函数的返回值判断 所以main函数返回值的本质是通知父进程任务执行情况
又为什么返回0?0表示进程执行成功 非0表示失败而且用不同的非0数字表示错误的原因类型每个数字对应一个错误的描述 char* strerrot(int erronum)错误码转化为错误描述 3、进程如何终止
a、main函数中直接return表示进程终止非main函数return表示函数结束
b、代码调用exit函数引起一个正常的进程终止 参数类似于main函数的return退出码 当调用exit函数时可以在进程的任意位置退出
c、_exit终止一个调用进程 exit和_exit的区别是什么 区别在于exit在退出时会刷新缓冲区_exit不会 exit是C语言库函数_exit是系统调用 所以本质上exit一定会调用_exit系统接口 因为不允许用户直接越过操作系统访问底层的进程数据 所以我们可以知道缓冲区是介于系统调用和库函数之间的 也就是说缓冲区不是操作系统内核缓冲区
三、进程等待
任何进程在退出的情况下一般必须要被父进程进行等待 如果退出时父进程不管不顾退出进程就会处于Z僵尸状态长期如此就会造成内存泄漏 僵尸状态进程没有被执行不在CPU的运行队列此时操作系统就会回收存在内存中的代码数据但是不会释放PCB结构体 同时僵尸进程无法被杀死因为已经死了的僵尸不能死两次 具体详情可以参考博主的其他文章零基础进程最详解进程状态、僵尸进程、孤儿进程、阻塞态、挂起态、进程切换、进程常用命令、进程创建、队列优先级_僵尸进程孤儿进程-CSDN博客https://blog.csdn.net/qq_51216031/article/details/140850173?spm1001.2014.3001.5501
1、为什么要等待
1通过父进程等待解决子进程退出时的僵尸问题回收系统资源 2获取子进程的退出信息因为父进程要知道子进程因为什么退出但是并非必要
2、怎么等待
通过wait / waitpid函数
1wait函数
wait 函数是一个阻塞式的系统调用用于暂停父进程的执行直到一个子进程结束或者收到一个信号为止。一旦子进程终止wait 函数会获取子进程的终止状态并返回。 pid_t wait (int *status);//返回值是等待成功时子进程的pid status等待父进程中任意一个子进程退出如果不关心子进程的退出状态可以传入 NULL。 返回值如果成功返回终止子进程的进程IDPID。 如果出错返回 -1。
如果子进程没有退出父进程一直在阻塞等待状态即Ssleeping状体 这种阻塞本质是在等待子进程这个软件状态就绪即返回信息再死亡释放子进程
2waitpid函数 pid_t waitpid(pid_t pid, int *status, int options); 返回值当正常返回的时候返回收集到子进程的进程ID 参数
第一个参数pid等待的子进程PID -1等待进程组ID等于pid绝对值的任何子进程。 -1等待任何子进程。 0等待与调用进程在同一进程组的任何子进程。 0等待指定PID的子进程。
第二个参数status一个整型指针用于存储子进程的退出状态信息。如果不关心子进程的退出状态可以传入 NULL。
第三个参数options指定等待的选项例如 WNOHANG 可以使 waitpid 成为非阻塞的。
返回值如果成功返回终止子进程的进程IDPID。 如果出错返回 -1。 WIFEXITEDstatus获取退出码返回值非0为正常退出不正常为0 子进程返回的信息就是通过wait_pid中的参数status获取的 因此status不能简单视为一个整数 status在32位下我们只关心低16位 在这16位中8-15表示退出状态0-6表示退出信号
低16位的含义
退出状态位于低16位的8-15位。这个部分表示子进程的退出状态。通常如果子进程正常退出这个状态会是0。 退出信号位于低16位的0-6位。这部分表示导致子进程终止的信号。如果子进程不是正常退出比如因为接收到了某个信号而终止那么这部分会包含有关信号的信息。
四、阻塞等待与非阻塞等待
如果子进程没有退出 此时父进程在执行waitpid进行等待处于阻塞等待状态 进程阻塞的本质就是进程不在运行调度队列中状态不为R 如果父进程一直处于阻塞状态就相当于父进程什么也没有做就只是在等待子进程的退出 这样不好 那么可不可以让父进程不处于阻塞状态去等待呢 可以这种状态叫做非阻塞等待 怎么做设置函数参数 pid_t waitpid(pid_t pid, int *status, int options); 对于该函数的options参数值设置为WNOHANG值一个宏 WNOHANG 是一个宏定义通常在使用 waitpid 函数时用作参数用于指定在调用 waitpid 函数时的父进程处于非阻塞等待状态。 具体来说WNOHANG 的全称是 Wait No Hang。非阻塞等待的时候 循环 非阻塞轮询 在非阻塞轮询情形下父进程就可以做其他的事情
如何理解呢
假设你有一个女朋友假设注意我说的是假设哈 你在大学谈了一个女朋友 周末你约她出去玩可是她说他要化妆要打扮一下 于是你就到她的宿舍楼下等 此时你和你女朋友的处境就相当于子进程和父进程 你是父进程你女朋友是子进程
如果在等的期间你一句话都不敢说啥也不敢做 就像一个二棒槌一样杵在楼下等待 那么此时你这个父进程就相当于阻塞等待状态 啥也没做就是等浪费生命浪费时间
但是如果你在等的期间你每隔几分钟打个电话问个情况说好了没有啊 如果她告诉你好了就出发 如果她告诉你没有好那你也不能像棒槌一样干杵着 所以你就刷刷抖音欣赏欣赏风景做自己的事情 然后再时不时打电话问情况 好了就出发没好就做自己的事情 于是此时你和你女朋友的状态就相当于非阻塞等待状态 打电话相当于一个函数调用她给你的答复好没好是返回值 你拿到这个返回值当作一个参数作为参考 返回值为好了你就结束等待 返回值为没好你就继续做手头的事情 这就是非阻塞等待状态 同时你每隔几分钟打一次电话 这个就叫做轮询 所以非阻塞等待的时候 循环 非阻塞轮询 在非阻塞轮询情形下父进程就可以做其他的事情 虚拟地址空间是时代技术发展的产物 代码是只读属性为什么是只读 因为页表的权限设置只有只读而我们使用的都是虚拟地址 会被页表部分修改命令被拦截