当前位置: 首页 > news >正文

day25 进程

概念

是程序的一次执行过程,是调度和资源分配的独立单元,是资源分配的最小单位

进程和程序的区别

进程:是动态的,在内存上,包含创建、调度和消亡

程序:是静态的,在硬盘上

CPU的调度机制

时间片轮转机制:cpu以ms级速度在多个进程之间来回切换

进程的五态图

 阻塞态不能直接回到运行态!!!

 进程的标识

一个终端打开时,会有一个会话id,其包含一个前台进程组,多个后台进程组,一个进程组包含多个进程

pid: process id 进程id

ppid: parent process id 父进程id

pgid: process group id 进程组id

SID:session id 会话id

三个特殊进程号

0:indel进程,操作系统的引导进程

1:init进程,初始化进程,收养孤儿进程

2:kthread进程,用户进程线程之间调度

shell指令

ps -ef          查看每个进程

ps -aux       查看进程的内存的使用情况

ps -ajx        打印进程树

ps -ajx | grep a.out        查找a.out进程,进程树的形式输出

|:  管道符,上一个指令的输出作为下一个指令的输入

grep a.out:  查找a.out进程

pidof 进程名    查看指定进程id号

进程的状态

               D    不可中断的休眠态(usually IO)R    运行态(on run queue)S    可中断的休眠T    挂起态t    bug调制状态W    分页X    死亡态 (should never be seen)Z    僵尸For BSD formats and when the stat keyword is used,additional characters may be displayed:<    高优先级 (对其他用户不友好)N   第优先级(对其他用户友好)L    将页面锁定在内存s    会话领导者l    多线程+    运行在前端

进程的内存

操作系统指针虚拟内存大小
324字节2^32--->4G
638字节2^48--->256TB        虚拟内存没那么多,取48位

内核与用户空间划分3:1

 堆和栈的区别

0.申请和释放 存放内容 地址方向 空间大小 碎片化程度

1.堆区空间用户申请和释放,栈区空间计算机自动申请和释放

2.堆区存放malloc申请的空间,栈区存储局部变量

3.地址方向不同:堆区从低到高,栈从高到低

4.堆区空间2G-3G,栈区空间8M

5.堆区碎片化严重,栈区基本没有碎片化

堆栈溢出

空间不足,递归层数较多时,计算机不断申请栈区空间,此时可能会空间不足

内存泄漏

堆区申请的空间已经不使用了,但是未释放

进程相关函数

frok

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

功能:创建子进程,子进程拷贝父进程的用户空间

参数:无

返回值:成功进程返回子进程的pid

              进程返回0

              失败返回-1,更新errno

用户空间:堆区,栈区,静态区,缓冲区,文件描述符

内核空间共享(光标:打开文件一次,子进程拷贝父进程,光标共享)

n次fork后:2^n个进程

父子进程执行顺序不固定,sleep()放弃cpu资源

写实拷贝

子进程拷贝父进程的用户空间

不发生数据改变时,父子进程共享同一物理内存页

当一个进程发生数据改变时,内核会触发缺页异常,此时才会分配新的物理页,复制内容,解除写保护,此后,父子进程才各自拥有独立的副本。

作用:高效性,节省资源

getpid | getppid

#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);

功能:顾名思义,获取调用者pid或ppid

参数:无

返回值:成功返回调用者的pid或ppid  不会失败

 exit

#include <stdlib.h>

void exit(int status);

功能:退出进程,并把退出状态值返回给父进程

库函数调用,刷新缓冲区

参数:int status  退出状态值,人为规定0表示正常退出,一般写0

返回值:无

status        退出状态值,一般正常退出为0,异常退出为非0

_exit

#include <unistd.h>

       void _exit(int status);

功能:退出进程,并把退出状态值返回给父进程

系统调用,不刷新缓冲区

参数:int status  退出状态值,人为规定0表示正常退出,一般写0

返回值:无

wait

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *wstatus);

功能:阻塞函数,等待任意子进程退出,回收子进程资源(回收僵尸资源)接收exit的退出状态值

参数:int *wstatus  该指针指向内存中存储exit的退出状态值

                NULL       不接收exit的退出状态值

返回值:

                成功返回接收子进程的pid,失败返回-1,更新errno

WEXITSTATUS(wstatus) 计算退出状态值的 (status&0xff00)>>8

waitpid

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

功能:阻塞函数(可非阻塞),等待任意子进程退出,回收子进程资源(回收僵尸资源)接收exit的退出状态值

参数:

          pid_t  pid

                

<-1等待进程组id等于pid绝对值的进程组下的任意子进程
-1等待当前进程的任意子进程结束  等价于wait
0等待当前进程的任意子进程结束
>0等待回收指定子进程

          int *wstatus  该指针指向内存中存储exit的退出状态值

                NULL       不接收exit的退出状态值

          int options     0:阻塞

                                WNOHANG:设置为非阻塞

返回值:

                成功返回接收子进程的pid,失败返回-1,更新errno

#include <25061head.h>
int main(int argc, const char *argv[])
{		pid_t pid=fork();if(pid>0){int status; //定于退出状态值pid_t ret=wait(&status); //ret接收返回值printf("%d pid::%d ret::%d  status=%d\n",__LINE__,getpid(),ret,WEXITSTATUS(status));	//status为0是因为此处为信号中断,低八位为0,宏函数返回值为0if(WIFEXITED(status))  //是否为异常退出{printf("正常退出\n");}else{printf("异常退出\n");printf("%d\n",status); //139printf("%d\n",WEXITSTATUS(status));  //0}int sig;sig=WTERMSIG(status);printf("%d\n",sig);if(sig=WTERMSIG(status))  //是否为信号中断printf("%d信号中断\n",sig);}else if(pid==0){printf("%d pid::%d \n",__LINE__,getpid());kill(getpid(), SIGSEGV); int *p=NULL;*p=100;exit(7);}else{ERR_MSG("FORK ERROR");}return 0;
}

vfork

同fork 区别子进程共享父进程的地址空间  子进程先运行,父进程阻塞

宏函数

WIFEXITED(wstatus)       

判断是否是异常退出的,如果正常退出则返回真,否则返回假

WEXITSTATUS(wstatus)计算退出状态值的 (status&0xff00)>>8

WTERMSIG(wstatus)

判断是否是信号中断的, 如果是信号中断则返回真(信号编号)

进程扇

#include <25061head.h>
void pid_create(int n)
{for(int i=1;i<=n;i++){pid_t pid =fork();if(pid==0) //子进程{   sleep(i); //确保顺序输出printf("子进程%d pid=%d ppid=%d\n",i,getpid(),getppid());//关闭子进程sleep(n-i+1); //统一时间关闭exit(0);}}
}
int main(int argc, const char *argv[])
{		int n;printf("需要创建几个子进程\n");scanf("%d",&n);pid_create(n);//回收子进程pid_t pid2;while((pid2=wait(NULL))!=-1)printf("pid=%d子进程回收\n",pid2);	printf("父进程 pid=%d\n",getpid());return 0;
}

 进程链

#include <25061head.h>
void pid_create(int n)
{static int i=1;pid_t pid =fork();if(n==1&&pid==0)  //递归出口{printf("子进程%d代 pid=%d 父进程ppid=%d\n",i,getpid(),getppid());exit(0);return ;}if(pid==0) //子进程{   printf("子进程%d代 pid=%d 父进程ppid=%d\n",i++,getpid(),getppid());pid_create(n-1);_exit(0);}else  //父进程wait(NULL);//回收子进程			}
int main(int argc, const char *argv[])
{		int n;printf("需要创建几个子进程\n");scanf("%d",&n);printf("父进程 pid=%d\n",getpid());pid_create(n);printf("父进程 pid=%d结束\n",getpid());return 0;
}
http://www.lryc.cn/news/611246.html

相关文章:

  • FastAPI快速入门P2:与SpringBoot比较
  • 【数据结构初阶】--排序(三):冒泡排序,快速排序
  • add_key系统调用及示例
  • 《C++》继承完全指南:从入门到精通
  • 【Day 16】Linux-性能查看
  • 计算机基础:操作系统学习的基石
  • 分布式微服务--Nacos 集群部署
  • RabbitMQ延时队列的两种实现方式
  • 磁悬浮转子的“静音术”:深度解析无接触抑制旋转幽灵的奥秘
  • 基于华为开发者空间的Open WebUI数据分析与可视化实战
  • 【Linux系统编程】线程概念与控制
  • MATLAB实现菲涅尔法全息成像仿真
  • Spring Boot 整合 Web 开发全攻略
  • Java面试宝典:深入解析JVM运行时数据区
  • Linux 内存管理之 Rmap 反向映射(二)
  • EP01:【DL 第二弹】张量(Tensor)的创建和常用方法
  • BloodHound 8.0 首次亮相,在攻击路径管理方面进行了重大升级
  • IPD研发管理——决策评审DCP指南
  • Java从入门到精通 - 集合框架(一)
  • MySQL主从延迟到崩溃:Binlog格式、半同步复制与GTID的博弈
  • 视频转二维码在教育场景中的深度应用
  • 结合opencv解释图像处理中的结构元素(Structuring Element)
  • 【Java企业级开发】(七)Spring框架
  • 区块链:重构信任的价值互联网革命​
  • 场外个股期权的额度为何受限?
  • 浮动IP(Floating IP)的删除通常需要满足什么条件
  • 基于ZYNQ ARM+FPGA的声呐数据采集系统设计
  • uniapp转app时,cover-view的坑
  • 什么情况下浮动IP(Floating IP)会“漂移”(Drift)
  • OneCode 3.0 前端架构全面研究