进程状态: 运行, 就绪, 阻塞
Linux下进程状态,运行, 可中断休眠状态, 停止, 僵尸
僵尸状态: 描述的是一个已经退出了但没有完全释放资源的进程的一种状态,这种进程状态称为僵尸状态
产生的原因:子进程先于父进程退出向父进程发送SIGCHLD信号,但是SIGCHLD信号默认的处理方式是忽略处理 ,因此父进程无法直接获知子进程状态
进程僵尸状态危害:资源泄漏;
解决方案: 避免僵尸进程的产生,在父进程创建子进程之后进行进程等待,等待子进程退出,获取返回值,释放子进程资源
程序地址空间: 进程虚拟地址空间
虚拟地址空间的本质: 操作系统通过mm_struct 结构体描述的虚拟空间
虚拟地址空间的优点: 0.每个进程都有虚拟地址空间,提高进程独立性;1.通过页表映射虚拟与物理地址,实现离散式存储,提高内存利用率2.内存访问控制
页表如何实现虚拟地址和物理地址映射:映射关系随着内存管理方式而不同
分段式: 将地址空间分为多个段(正文段, 数据段, 堆, 栈…), 便于地址管理
分段式: 将地址空间分为大量的内存页,进程使用大块连续的虚拟地址,通过页表映射能够实现数据存放在不同的物理内存块上,提高内存利用率
段页式: 先对地址进行分段,在每个分段中进行分页管理
分页式实现:虚拟地址的组+页表
虚拟地址的组成: 页号–对应内存页的编号+ 页内偏移 – 对应数据在页中的偏移量
页表的关键信息: 页号,物理地址…
通过一个虚拟地址中的页号,找到对应的页表中的页表项,进而获取到页表项中对应的物理地址,物理地址加上页内偏移量
进程间通信: 操作系统为用户提供进程间通信方式
操作系统为进程间提供通信的原因: -进程之间具有独立性,每个进程都有自己的虚拟地址空间,访问的都是自己的虚拟地址空间,互补影响,为了让平行进程之间有个交叉点,操作系统为进程之间提供通信方式
进程间通信方式: 管道, 共享内存, 消息队列, 信号量
-
管道:用于实现进程间的数据进程传输
本质是内核中的一块缓冲区
匿名管道: 只能用于具有亲缘关系的进程间通信,子进程复制父进程的方式获取句柄
int pipe(int pipefd[2])管道的操作句柄通过参数返回
int pipefd[2] = {-1};//pipefd[0]读端 pipefd[1]写端 int ret = pipe(pipefd); if(ret < 0){ perror("pipe error"); return -1; } pid_t pid = fork(); if(pid == 0){//fork()返回值为0--子进程 .... } else if(pid > 0){//父进程得到子进程的pid号 ... }
管道的特性:
1.半双工通信–单方向上的通信
2.管道自带同步与互斥:
互斥:通过同一时间的唯一访问,保证本次访问的安全
管道每次操作,操作大小不超过PIPE_BUF大小,保证操作的原子性
同步:按照某种秩序进行访问,保证访问的合理性
管道的数据满了的时候继续write就会阻塞进程;管道中没有数据继续read就会阻塞
互斥保证同一时间唯一访问,确保访问安全,同步按照秩序进行访问,确保访问合理
3.管道提供字节流服务
提供有序定的, 安全的, 基于连接的, 可靠的以字节为单位的传输方式
连接的:管道的所有读端被关闭了,则write就会触发异常,进程退出; 所有写端被关闭,则read读取完管道中的所有的数据后就会退出,不会阻塞而是返回0
4.管道的生命周期随进程
命名管道:int mkfifo(char *filename, mode_t mode)
命名管道的本质也是内核中一块缓冲区,这块缓冲区有标识就是一个可见于文件系统的管道文件
多个进程打开同一个管道文件,访问的是同一块内核中的缓冲区,进而实现通信
-
共享内存:
本质原理: 开辟一块共享内存(一块物理内存, 并且在内核中进行了各种描述–名字–标识符)多个进程通过相同的标识符,找到相同的一块物理内存,将其映射到自己的虚拟地址空间中,通过自己的虚拟地址空间进行访问,最终实现通信
操作流程:
1.创建/打开共享内存 int shmget(key_t key,int size,int flag);//key-标识符;size-大小;flag-权限
2.与共享内建立映射关系 int shmat(int shmid,void *addr,int flag)//shmid共享内存id
3.内存操作(mecopy之类的内存操作)
4.解除映射关系int shmdt(void *addr)//解除映射关系不代表删除共享内存
5.删除共性内存int shmctl(int shmid,int cmd,struct shmid_ds *buf);通常是将共享内存删除,最后的buf置为空
共享内存的特性:
1.最快的进程间通信方式(相较于其他的方式少了两步用户态到内核态的数据拷贝的操作)
2.共享内存的生命周期随内核
注意事项: 共享内存的操作并非是安全的,当前一个进程写入,第二个进程在进行写入时就会造成数据写入的冲突 -
消息队列: 本质是内核中的一个优先级队列,多个进程通过相同的标识符访问同一个队列
特性: 生命周期随内核,自带同步与互斥 -
信号量: 实现进程间的同步与互斥
本质原理是一个计数器,统计资源的数量,在有资源的情况下才能够进行访问,实现资源访问的合理性(通过资源计数来进行判断: 有资源的时候才能获取,没有资源的时候就等着)
信号量的操作:P/V操作
P操作:计数-1,判断是否小于0,小于0,表示没有资源,则进程等待
V操作:计数+1,判断有没有进程等待,如果有等待的进程,则唤醒一个
信号量实现互斥: 同一时间对资源的唯一访问
信号量实现互斥的原理: 保证资源数只有一个,这时只有一个进程能够进行访问,访问完毕之后计数还原
信号量实现同步:信号量的主要目的是用来实现同步的,通过计数进行资源获取的合理性判断(计数大于0能访问,计数小于0不能访问,这就是合理的访问秩序)
进程通信是什么?
为什么要进行进程间通信?
因为每个进程是具有独立性,无法直接进行通信,所以操作系统为程序员提供的进程间通信方式,以针对不同的应用场景;
方式分类:管道,共享内存,消息队列,信号量
不同方式的本质以及提供的功能:
内核中的缓冲区
一块共享的物理内存
内核中的一个优先级队列
一个对资源的计数器