1,虚拟内存
电脑中所运行的程序均需经过内存执行,若执行的程序占用的内存很大很多,则会导致内存消耗殆尽,
为解决该问题,WINDOWS运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,这部分空间即称为虚拟内存。
每个进程运行
每个进程运行的时候都会拿到4G的虚拟内存.其中3G是交给用户的,然后剩下的1G内存存储内核的东西了.
一个进程在执行时并没有将所有的数据都加载到内存中,而是将要使用的数据放入内存中,暂时不使用的部分放在外存中,
如果需要外存中的数据就从外存中拿取,并将内存中不使用的部分置换到外存中。这样在程序看来自己是独享内存空间的。
说明一个问题:
为什么fork一个子进程后,在子进程中改变父子进程都有的一个变量,
得到的父子进程中该变量的地址相同,但是对应的值却是不一样的。
这是因为这里取到的地址并不是物理内存地址,而是虚拟地址空间中的地址,
虚拟地址空间中的地址全部都是相对于虚拟地址空间首行(全0)的偏移量,
由于父子进程的变量位于各自地址空间的相同位置,所以偏移量是相同的,
但是,形同的偏移量通过页表映射的物理内存是不一样的。
优点:可以弥补物理内存大小的不足;一定程度的提高反映速度;减少对物理内存的读取从而保护内存延长内存使用寿命;
缺点:占用一定的物理硬盘空间;加大了对硬盘的读写;设置不得当会影响整机稳定性与速度。
2,页表
页表是一种数组结构,这个数组的每一个元素分为两部分,
第一部分为1,则表示可以在物理内存中找到,那么第二部分就存放着物理内存地址。
第一部分为0,则表示不存在物理内存的映射,该情况叫做缺页异常。第二部分就是空值。
缺页异常的处理方法:将进程需要的数据从磁盘上拷贝到物理内存中,如果物理内存已经满了,那么就需要覆盖一部分
物理内存,当然如果被覆盖的数据被修改就需要将其更新到磁盘上,
总结来说:虚拟地址空间拥有进程需要的物理内存数据地址,和磁盘中数据的地址。然后通过页表元素的第一部分判断
需要的数据在哪里存放,在物理内存中就直接使用,在磁盘中就先拷贝到物理内存中再使用。
3,pcb
进程在操作系统中都有一个户口,用于表示这个进程。这个户口操作系统被称为PCB(进程控制块),在linux中具体实现是 task_struct数据结构,它记录了一下几个类型的信息:
1,标识符pid:可以理解为这个进程的身份证号
2,状态:任务状态 退出代码 退出信号
3,优先级:相对于其他进程的优先级
4,程序计数器:程序接下来要执行的指令的地址
5,内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享内存块的指针
6,上下文数据:进程执行时处理器的寄存器中的数据
7,I/O状态信息:包括分配给进程的I/O设备和被进程使用的文件列表。
4,进程的状态
1,R运行状态:并不意味者一定正在运行,也可能是在运行队列中等待
2,S睡眠状态:正在等待事件的完成,是可中断的睡眠
3,D磁盘休眠的状态:通常是在等待I/O事件的结束,是不可中断的睡眠。
4,T停止状态:发送SIGSTOP信号来停止一个状态,发送一个SIGCONT信号来开始停止的进程。
5,X表示死亡状态:不能像其他状态一样使用命令查询,只是一个返回状态。
6,Z僵尸进程:
当子进程退出,父进程还在运行,并且没有读取子进程的状态,子进程就进入僵尸状态。
僵尸进程会导致内存资源的大量泄漏,所以必须避免僵尸进程。
读取子进程状态的过程叫做进程等待,
1,wait(int * status)输出型参数,表示进程的退出状态,不关心可以填NULL;返回成功等待的进程pid
2,waitpid(pid_t pid , int * status ,int option)
pid == - 1 表示等待任意子进程,pid>0表示等待指定的子进程。
status 输出型参数,等于0表示正常退出
option,表示阻塞等待还是非阻塞等待
7,孤儿进程:
如果父进程先于子进程退出,那么子进程就被称为孤儿进程。
孤儿进程将会被1号进程收养,并由1号进程回收。