一、基本概念
- 进程有以下几个定义:
a).正在执行的程序
b).正在计算机上执行的程序实例
c).能分配给处理器并由处理器执行的实体
b).具有以下特征的活动单元:一组指令序列的执行、一个当前状态和相关的系统资源集。
也可以把进程当成由一组元素组成的实体,进程的两个基本的元素是程序代码(可能被执行相同程序的其他进程共享)和代码相关联的数据集。假设处理器开始执行这个程序代码,且我们把这个执行实体叫做进程。
二、task_struct结构体
在进程执行时,任意给定一个时间,进程都可以唯一地被表征为以下元素:
a).标识符:跟这个进程相关的唯一标识符,用来区别其他进程
b).状态:如果进程正在执行,那么进程处在运行状态
c).优先级:相对于其他进程的优先级
d).程序计数器:程序中即将被执行的下一条指令的地址
e).内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享内存块的指针
f).上下文数据:进程执行时处理器的寄存器中的数据
g).I/O状态信息:包括显式的I/O请求、分配给进程的I/O设备(例如磁带驱动器)和被进程使用的文件列表等
h).记账信息:可能包括处理器时间总和、使用的时钟数总和、时间限制、记账号等
三、进程的调度算法
在OS中调度的实质是一种资源分配,因而调度算法是指:根据系统的资源分配策略所规定的的资源分配算法。
对于不同的系统和系统目标,通常采用不同的调度算法:
1. 先来先服务调度算法
先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可以用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将他们调入内存,为他们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度都是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。
2. 短作业(进程)优先调度算法
短作业(进程)优先调度算法SJ(P)F,是指对短作业或者短进程优先调度的算法,可以分别用于作业调度的进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将他们调入内存运行。而短进程优先(SPF)调度算法是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时在重新调度。
缺点:
<1>.该算法对长作业不利,如果有一长作业(进程)进入系统的后备队列(就绪队列),由于调度程序总是优先调度那些(即使是后进来的)短作业(进程),将导致长作业(进程)长期不被调度
<2>.该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。
<3>.由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户有可能会有意或无意地缩短其作业的估计时间,致使该算法不一定能真正做到短作业优先调度。
四、僵尸进程和孤儿进程
1、基本概念
孤儿进程:一个父进程退出,而他的一个或者多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵尸进程。
2.危害
如果进程不调用wait或waitpid的话,那么保留的那段信息就不会被释放,其进程号就会一直被占用着,但是 系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此为僵尸进程的危害,应当避免。因孤儿进程会被init进程回收,所以孤儿进程并不会有什么危害
3.孤儿进程和僵尸进程代码测试
<1>.孤儿进程代码测试
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int main(){
pid_t pid;
//创建一个进程
pid = fork();
if(pid < 0){//进程创建失败
perror("fork error\n");
exit(1);
}
if(pid == 0){//子进程
printf("I am child process\n");
printf("pid:%d ,ppid:%d\n",getpid(),getppid());
//睡眠5秒保证父进程先退出
sleep(5);
printf("pid:%d ,ppid:%d\n",getpid(),getppid());
printf("child process is exited\n");
}
else{//父进程
printf("I am father process\n");
//睡眠一秒保证子进程输出进程id
sleep(1);
printf("father process exit\n");
}
return 0;
}
结果如下:
<2>.僵尸进程测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
int main(){
pid_t pid;
if(fork() < 0){
perror("fork error\n");
exit(1);
}else if(fork() == 0){
//子进程
printf("I am child process,I am exiting\n");
exit(1);
}
printf("I am father process\n");
//让子进程退出
sleep(2);
system("ps -o pid,ppid,state,tty,command");
printf("father is exiting\n");
return 0;
}
结果如下: