进程的相关概念

基本概念

  • 资源分配和拥有的基本单位
  • 进程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 多进程基础知识笔记相关推荐

  1. access2013数据库实验笔记_医学科研实验基础知识笔记(十):甲基化

    往期回顾 医学科研实验基础知识笔记(一):细胞增殖 医学科研实验基础知识笔记(二):细胞凋亡检测 医学科研实验基础知识笔记(三):细胞周期检测 医学科研实验基础知识笔记(四):细胞自噬研究策略 医学科 ...

  2. Java基础知识笔记-11_2-Swing用户界面组件

    Java基础知识笔记-11_2-Swing用户界面组件 这章教程两个版本,一个语法是非lambda表达式版本,另一个是lambda表达式版本 非lambda表达式版本 1 Java Swing概述 J ...

  3. 6-DoF问题相关基础知识笔记

    6-DoF问题相关基础知识笔记 一.什么是6-DoF,即6个自由度是什么? 二.PnP算法 三.BOP挑战与官方数据集简介 BOP数据集 BOP toolkit BOP挑战的介绍页面 四.相关论文 C ...

  4. b站唐老师人工智能基础知识笔记

    b站唐老师人工智能基础知识笔记 0.机器学习(常用科学计算库的使用)基础定位.目标定位 1.机器学习概述 1.1.人工智能概述 1.2.人工智能发展历程 1.3.人工智能主要分支 1.4.机器学习工作 ...

  5. HTML基础知识笔记(0基础入门)

    HTML&CSS基础知识笔记 HTML 一.HTML介绍 二.实体 三.meta标签 四.语义化标签(一) 五.语义化标签(二) 六.语义化标签(三) 七.列表 八.超链接 九.图片标签 十. ...

  6. 二代测序之SNV基础知识笔记总结

    二代测序之SNV基础知识笔记总结 文章目录 二代测序之SNV基础知识笔记总结 SNV基础知识 SNVs Mutation vs. Variant[变异和突变] 不同层次的突变 DNA: 1.编码DNA ...

  7. python详细基础知识笔记

    详细基础知识笔记 注: ·第一章 学习准备 1.1高级语言.机器语言.汇编语言 1.2 汇编.解释 1.3 静态语言.脚本语言 1.4 Python的历史 1.5 Python语言的优点.缺点 1.6 ...

  8. Unity3D基础知识笔记

    Unity3D基础知识笔记 一.Unity简介 1)Unity3D概念 2)Unity3D的特点 二.Unity3D的发展历史 三.软件安装 一.Unity简介 1)Unity3D概念 Unity是由 ...

  9. Python基础知识笔记

    文章目录 Python基础知识 教程:https://www.liaoxuefeng.com/wiki/1016959663602400 内置函数:https://docs.python.org/3/ ...

最新文章

  1. 1082 射击比赛 (20 分)
  2. NILMTK——因子隐马尔可夫之隐马尔可夫
  3. ISSN和EAN原理及转换【转载】
  4. java dao层的泛型get方法_dao层的泛型实现(2种方法)
  5. 关于职业规划,如何自我实现?
  6. Ubuntu12.04增加屏幕分辨率选项
  7. protues元件库中英文对照表,对初学者找不到元件的很有用
  8. 2015年4月21日---开始写自己的专业博客啦
  9. 随着计算机科学技术和互联网,计算机科学与技术发展趋势的几点思考
  10. 怎样把pdf转换成jpg文件
  11. 微信小程序获取的微信头像模糊或者无法显示
  12. 【智能制造】“OEE智能盒子”-智能制造时代企业制造能力的评测与改进工具
  13. 车厢调度(信息学奥赛一本通 - T1357)
  14. 每日一课 | SQL模糊查找
  15. html5:制作一份邀请函
  16. ASP.NET缓存 之 Web服务器缓存
  17. java判断张三_从程序片断:student zhangsan(“张三”,“M”,22); zhangsan.id(“2005131000”);可判断id是一个()...
  18. 如何解决医院网站商务通无轨迹来源路径的问题
  19. 【操作系统】效率-高可用技术HA与一致性
  20. 高屋建瓴之WebMail攻与防

热门文章

  1. windows 系统密码破解工具(适合各种版本windows)
  2. Excel-VBA 快速上手(十一、字符串常用操作)
  3. @Transactional又双叒叕失效了?
  4. linux哪个系统好
  5. 局域网聊天工具都有哪些?
  6. 人脸识别在线上金融业务中的应用风险
  7. 影视后期制作需要用到哪些软件?
  8. keystone对接ldap
  9. 如何查看计算机网络密码是什么意思,如何查看电脑用户名_如何查看电脑网络密码...
  10. 动量策略——yyds