谈谈你对进程的理解。
1.首先进程的概念:进程是一个程序的执行过程,一个进程被加载到内存空间,并获取资源,就成为进程;同时也是资源分配的最小单位;
2.进程和程序的区别:
(1)程序是有序代码的集合,而进程是程序的执行过程;进程有创建,调度和消亡的过程;
(2)组成不同,进程包含程序,由程序,数据和进程控制块组成;
(3)对应关系,一个程序可被多次执行,行程多个进程;一个进程也可以包含多个程序;
3.Linux进程创建与退出:
(1) 创建:
a .fork()函数创建子进程,子进程继承父进程整个地址空间,包括进程上下文,代码段,进程堆栈,打开的文件描述符,优 先 级等,子进程独有的是自己的进程号,资源使用和计时器等;
b .vfork() 作为fork()的改进,创建的子进程先执行,并且在修改数据ian,父子进程共享数据段和代码段,节约资源;
c .用system() 库函数创建子进程,并加载程序到子进程空间运行;
(2)终止:exit() 和 _exit():在进程中exit() 属正常退出,为库函数,调用时刷新所有缓冲区;而_exit() 是Linux提供的API,调用时不刷新缓冲区,仅是关闭进程;因此父进程中一般使用exit(),子进程中一般使用_exit(); 如果一个进程仅使用_exit()而不使用ext()刷新缓冲区,会造成数据的丢失;
4.进程的特点:并行性,互不干扰,每个进程都有自己独立的虚拟地址空间(4G)
(1)进程创建时,系统为其分配虚拟地址空间;
(2)子进程完全拷贝父进程,包括代码;
(3)操作系统进行调度,父子进程的运行不受用户控制;
5.进程运行中可能产生的问题:孤儿进程和僵尸进程
(1)父进程结束负责回收子进程,出错带来的问题:
(2)父进程没有回收子进程,子进程就消亡; 子进程的PCB需要父进程释放,而父进程没有,子进程就成为僵尸进程;
僵尸进程几乎放弃所有的内存空间,没有任何可执行代码,也不能被调度;
父进程结束,僵尸进程由init进程接管,被清除;但是如果父进程是一个循环,那么僵尸进程会一直存在,耗费系统资源;(用ps -a 查看进程号,用kill手动杀死进程)
(3)父进程先于子进程消亡,子进程成为孤儿进程;孤儿进程由init进程(1号进程)收养,并由init进程完成对他们的状态收集工作;故孤儿进程不会像僵尸进程那样占用系统资源,影响系统运行;
6如何避免:进程等待 wait()和wait_pid()
7.进程调度:操作系统的核心是任务管理,任务管理的核心是进程调度;
(1) 为什么要进行进程调度:最大化处理效率,让多个进程同时运行,实现并发性,互不影响;
(2)协同式和抢占式:
协同式:非抢占,进程运行过程中不能被其他进程抢占,除非自己运行完成或发生等待事件或者运行时间片到;
抢占式:根据进程设置的优先级,当时间片到或有更高优先级的近曾到来时,抢占CPU;
(3)在调度层面,进程分为:处理器消耗型和I/O消耗型,前者一般采用协同式,后者一般采用抢占式;
8.进程调度使进程运行状态发生改变:进程3态:执行态,就绪态和等待态
进程为何要分成三态:防止多个进程同时抢占CPU资源,避免死锁;提高CPU的执行效率,使进程就像流水线一样,有序执行;
9.进程的同步与互斥:
(1)进程是并发执行的,多个进程同时访问CPU资源,产生竞态
(2)并发进程进程为了合作完成同一任务而形成的一种制约关系,两个进程相互制约,一次访问,操作系统中经典问题:生产者消费者问题,哲学家就餐问题;
(3)互斥进程:某一进程正在访问一资源,其他进程要使用需等待,直到该资源释放(信号量和PV操作)
(4)临界资源:系统中将一次只允许一个进程访问的资源成为临界资源;