基于Ubuntu 多进程基础知识笔记
进程的相关概念
基本概念
- 资源分配和拥有的基本单位
- 进程CPU环境(栈,寄存器,页表,和文件句柄等)的保存以及新调度的进程CPU环境的设置
- 操作系统控制
- 内核栈
- CPU资源、内存资源、文件资源和句柄等
- 不同进程之间切换实现并发,各自占有CPU实现并行
- 切换虚拟地址空间,切换内核栈和硬件上下文,CPU高速缓存失效、页表切换,开销很大。
- 进程间通信需要借助操作系统
程序和进程
程序:是编译好的二进制文件,存放在磁盘上,占用的是磁盘空间,是一个静态的概念。
进程:一个启动的程序,占用系统资源。如:物理内存,CPU,终端等;是一个动态的概念
并行和并发
并行:多个CPU
并发:多个时间片
PCB-进程控制块
每个进程在内核中都有一个进程控制块(PCB)
进程ID,唯一。
进程的状态:就绪、运行、挂起、停止等状态。
CPU寄存器,哟用于**切换进程,**保留进程信息。
虚拟地址空间的信息
控制终端的信息
当前工作目录
umask掩码
文件描述符表,包含很多指向file结构体的指针
和信号相关的信息。
用户ID和组ID
会话(Session)和进程组
进程可以使用的资源上限ulimit -a
进程的状态
创建进程
fork函数(创建子进程)
函数作用:创建子进程
谁先抢到时间片,谁先执行
//原型: pid_t fork(void); //函数参数 无 //返回值 //父进程返回子进程PID 子进程返回0
fork函数示例
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h>int main() {printf("before fork pid==[%d]\n",getpid());//执行一次//创建子进程//pid_t fork(void)pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){//父进程执行printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());sleep(10);//确保父进程后执行完}else if(pid==0){//子进程执行printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());sleep(10);//确保父进程后执行完}printf("after fork pid==[%d]\n",getpid()); //执行二次return 0; }
1、执行顺序
2、父进程先退出
子进程被[1]进程接受
循环创建n个进程
函数示例:
#include<string.h> #include<sys/types.h> #include<unistd.h> int main() {int i = 0;for(i=0;i<3;i++){//创建子进程pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());//sleep(1);//确保父进程后执行完}else if(pid==0){printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());break;//防止生成孙子进程}}if(i==0){//子进程1printf("[%d]-----[%d] :child\n",i,getpid());}if(i==1){//子进程2printf("[%d]-----[%d] :child\n",i,getpid());}if(i==2){//子进程3printf("[%d]-----[%d] :child\n",i,getpid());}if(i==3){//父进程 会打印三次printf("[%d]-----[%d] :child\n",i,getpid());}//sleep(10);return 0; }
结果
father: pid==[76192],fpid==[75878] //i=0 father: pid==[76192],fpid==[75878] //i=1 father: pid==[76192],fpid==[75878] //i=2 [3]-----[76192] :child //父进程 chlid: pid==[76195],fpid==[1] //子进程 父进程早就死了 [2]-----[76195] :child chlid: pid==[76194],fpid==[1] [1]-----[76194] :child chlid: pid==[76193],fpid==[1] [0]-----[76193] :child
父子进程不能共享全局变量
- 父子进程变量不共享,但指向同一个地址
- 读时共享,写时不共享
读写示意图
写时,会将物理内存映射到一个新的地方。
代码示例
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> int g_var = 99; int main() {int i = 0;for(i=0;i<3;i++){//创建子进程pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){printf("father: g_var==[%d]\n",g_var);g_var++;printf("father: g_var==[%d]\n",g_var);sleep(1);//确保父进程后执行完printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());printf("[%p]",&g_var);//地址相同}else if(pid==0){sleep(1);printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());printf("child: g_var==[%d]\n",g_var);//值不同printf("[%p]",&g_var);//地址相同break;}}//sleep(10);return 0; }
ps命令和kill命令
查看进程
ps -aux | grep "xxx" //配合管道查找指定内容 ps -ajx | grep "xxx"-a:(all) 当前系统所有用户的进程 -u:查看进程所有者及其他一些信息 -x:显示没有控制终端的进程 -j:累出与作业相关的信息
结束进程
//查看系统有哪些信号 kill -l //杀死某个线程 kill -9 pid
调用程序
exec函数族(拉起一个程序)
在一个子进程里拉起一个可执行程序(系统命令或应用程序)
execl函数(自己的程序)
一个进程里拉起一个可执行程序
//函数原型: int execl(const char *path,const char *arg, .../*(char *) NULL */); //参数介绍://path: 要执行程序的决定路径 + 名称//变参arg: 要执行的程序的需要的参数//arg: 占位,通常写应用程序的名字//arg后面的: 命令的参数//参数写完之后:NULL //返回值//若是成功,则不返回,不会再执行exec函数后面的代码;若是失败,会执行
execlp函数(系统命令)
//函数原型: int execlp(const char *file,const char *arg, .../*(char *) NULL */); // 不带路径 // file:执行命令的名字,根据PATH环境变量来搜索该命令
内部原理
- 代码段 .txt被替换
- 子进程pid,地址空间不变
execl函数代码示例
#include<stdio.h> int main(int argc;char *argv[]) {int i = 0;for(i=0; i<argc; i++){ printf("[%d]:[%s]\n",i,argv[i]);}return 0; }
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> int main() {//函数原型://创建子进程pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());}else if(pid==0){printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());//execl("/bin/ls","ls","-l",NULL);//execlp("ls","ls","-l",NULL); 搜索环境变量execl("./test","test","hello","world","ni","hao",NULL);perror("execl error");//成功不会执行}return 0; }
进程回收
当一个进程退出之后,进程能够回收自己的用户区的资源,但不能回收内核空间的PCB资源,必须由它的父进程调用wait或者waitpid函数完成对子进程的回收,避免造成系统资源的浪费。
- 系统自动回收用户区资源
- 不能回收内核空间资源
- 必须通过父进程回收内核资源
孤儿进程(不是一个错误)
1、若父进程死掉。
2、会被init进程领养,父进程pid变为1。会被init进程回收资源
僵尸进程(重点)
子进程先退出,但是父进程没有回收子进程的资源,子进程为僵尸进程
无法用kill处理子进程
简单处理方法:
1、kill -9 强制删除父进程
2、init进程领养僵尸进程,最后由inti进程回收僵尸进程。
wait函数
函数作用:
阻塞并等待子进程退出
回收子进程残留资源
获取子进程结束状态(退出原因)特点
- 阻塞 确保父进程后退出
- 父进程中调用
函数原型
//父进程中调用 pid_t wait(int *status); //返回值: 成功:清除掉的子进程PID 失败:-1 //status参数: 各种宏 保存子进程退出状态 //WIFEXITED(status) 为非0 进程正常结束 //WEXITSTAUS(status) 获取进程退出状态 //WIFSIGNALED(status) 为非0 进程异常终止 //WTERMSIG(status) 取得进程终止的信号编号 // man 2 wait 查看
wait函数示例
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/wait.h> #include<unistd.h> int main() {//创建子进程pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){//父进程printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());//pid_t wpid = wait(NULL);//printf("wpid==[%d]\n",wpid);int status;pid_t wpid = wait(&status);printf("wpid==[%d]\n",wpid);if(WIFEXITED(status)){//正常退出printf("child normal exit,status ==[%d]\n",WEXITSTATUS(status));// =9返回状态}else if(WIFSIGNALED(status)){//被信号杀死printf("child killed by signal, signo ==[%d]\n",WTERMSIG(status));}}else if(pid==0){//子进程printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());sleep(10);//确保子进程后退出return 9;//返回状态}return 0; }
waitpid函数
基本语法
pid_t waitpid(pid_t pid, int *status,in options); //函数参数: pid = -1 等待任一子进程 pid > 0 等待进程ID与pid相等的子进程 pid = 0 回收组内所有进程 pid < -1 等待其组ID等于pid的绝对值的任一子进程(子进程在其他组的情况 //options 设置为WNOHANG,函数非阻塞 设置为0, 函数阻塞 //函数返回值 >0:返回回收掉的子进程ID -1:无子进程 =0:参数3为WNOHANG,且子进程正在运行
waitpid函数示例
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/wait.h> #include<unistd.h> int main() {//创建子进程pid_t pid = fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){printf("father: pid==[%d],fpid==[%d]\n",getpid(),getppid());int status;while(1){//pid_t wpid = waitpid(pid,&status,0);pid_t wpid = waitpid(-1,&status,WNOHANG);//printf("wpid==[%d]\n",wpid);if(wpid > 0){if(WIFEXITED(status)){//正常退出printf("child normal exit,status ==[%d]\n",WEXITSTATUS(status));}else if(WIFSIGNALED(status)){//被信号杀死printf("child killed by signal, signo ==[%d]\n",WTETTMSIG(status));}}else if(wpid == 0) {//子进程还活着printf("cild is living ,wpod==[%d]\n",wpid);}else(wpid == -1){//没有子进程printf("no cild is living ,wpod==[%d]\n",wpid);break;}}}else if(pid==0){//子进程printf("chlid: pid==[%d],fpid==[%d]\n",getpid(),getppid());sleep(10);return 9;}return 0; }
守护进程
基本概念
后台服务进程,通常独立于控制终端,并周期性地执行任务。
不能通过终端进行交互。
不受用户登入退出影响。
一般以d结尾。
…
基于Ubuntu 多进程基础知识笔记相关推荐
- access2013数据库实验笔记_医学科研实验基础知识笔记(十):甲基化
往期回顾 医学科研实验基础知识笔记(一):细胞增殖 医学科研实验基础知识笔记(二):细胞凋亡检测 医学科研实验基础知识笔记(三):细胞周期检测 医学科研实验基础知识笔记(四):细胞自噬研究策略 医学科 ...
- Java基础知识笔记-11_2-Swing用户界面组件
Java基础知识笔记-11_2-Swing用户界面组件 这章教程两个版本,一个语法是非lambda表达式版本,另一个是lambda表达式版本 非lambda表达式版本 1 Java Swing概述 J ...
- 6-DoF问题相关基础知识笔记
6-DoF问题相关基础知识笔记 一.什么是6-DoF,即6个自由度是什么? 二.PnP算法 三.BOP挑战与官方数据集简介 BOP数据集 BOP toolkit BOP挑战的介绍页面 四.相关论文 C ...
- b站唐老师人工智能基础知识笔记
b站唐老师人工智能基础知识笔记 0.机器学习(常用科学计算库的使用)基础定位.目标定位 1.机器学习概述 1.1.人工智能概述 1.2.人工智能发展历程 1.3.人工智能主要分支 1.4.机器学习工作 ...
- HTML基础知识笔记(0基础入门)
HTML&CSS基础知识笔记 HTML 一.HTML介绍 二.实体 三.meta标签 四.语义化标签(一) 五.语义化标签(二) 六.语义化标签(三) 七.列表 八.超链接 九.图片标签 十. ...
- 二代测序之SNV基础知识笔记总结
二代测序之SNV基础知识笔记总结 文章目录 二代测序之SNV基础知识笔记总结 SNV基础知识 SNVs Mutation vs. Variant[变异和突变] 不同层次的突变 DNA: 1.编码DNA ...
- python详细基础知识笔记
详细基础知识笔记 注: ·第一章 学习准备 1.1高级语言.机器语言.汇编语言 1.2 汇编.解释 1.3 静态语言.脚本语言 1.4 Python的历史 1.5 Python语言的优点.缺点 1.6 ...
- Unity3D基础知识笔记
Unity3D基础知识笔记 一.Unity简介 1)Unity3D概念 2)Unity3D的特点 二.Unity3D的发展历史 三.软件安装 一.Unity简介 1)Unity3D概念 Unity是由 ...
- Python基础知识笔记
文章目录 Python基础知识 教程:https://www.liaoxuefeng.com/wiki/1016959663602400 内置函数:https://docs.python.org/3/ ...
最新文章
- 1082 射击比赛 (20 分)
- NILMTK——因子隐马尔可夫之隐马尔可夫
- ISSN和EAN原理及转换【转载】
- java dao层的泛型get方法_dao层的泛型实现(2种方法)
- 关于职业规划,如何自我实现?
- Ubuntu12.04增加屏幕分辨率选项
- protues元件库中英文对照表,对初学者找不到元件的很有用
- 2015年4月21日---开始写自己的专业博客啦
- 随着计算机科学技术和互联网,计算机科学与技术发展趋势的几点思考
- 怎样把pdf转换成jpg文件
- 微信小程序获取的微信头像模糊或者无法显示
- 【智能制造】“OEE智能盒子”-智能制造时代企业制造能力的评测与改进工具
- 车厢调度(信息学奥赛一本通 - T1357)
- 每日一课 | SQL模糊查找
- html5:制作一份邀请函
- ASP.NET缓存 之 Web服务器缓存
- java判断张三_从程序片断:student zhangsan(“张三”,“M”,22); zhangsan.id(“2005131000”);可判断id是一个()...
- 如何解决医院网站商务通无轨迹来源路径的问题
- 【操作系统】效率-高可用技术HA与一致性
- 高屋建瓴之WebMail攻与防