1. 调研进程的调度算法.
初步了解一下进程
进程概念:(1)从用户角度看,进程是程序的一次动态的执行过程(放在内存中的)
(2)从内核角度
进程是分配CPU,内存等系统资源的基本单位
从每个进程都有自己独立的虚拟地址空间(4G)和运行状态
进程是系统分配资源的最小单位
进程是程序的一次动态执行过程,需要对进程的现场信息进行维护,就需要相应的数据结构
对应着C语言的结构体。这个结构体叫PCB
进程创建的一般过程
1.给新进程分配一个标识符。在内核中分配一个PCB
2.复制父进程的环境 PCB
3.分配资源(程序 数据 栈等)内存资源
4.复制父进程的地址空间的内容
5.将进程置成就绪状态,放入就绪队列
进程的调度算法:
1、先来先服务调度算法(FCFS,first come first served):谁第一个排队,谁就先被执行,在它执行过程中,不会中断它;
2、短作业优先调度算法(SJF,shortest job first):对预计执行时间短的进程有限分配处理机,通常后来的短进程不会抢先正在执行的进程;对长进程非常不利,可能长时间得不到执行。
3、最高响应比优先法(HRRN,highest response radio next):对于FCFS和SJF的平衡,FCFS方式只考虑每个作业的等待时间而未考虑执行时间的长短,而SJF只考虑了执行时间而未考虑等待时间的长短,因此两种算法在某种极端的情况下会带来某些不便。HRRN通过综合这两种情况算出响应比R,根据响应比完成调度。优点:长作业也有机会投入运行,缺点:每次调度前要计算响应比。
4、时间片轮转法(RR,Round-Robin):采用剥夺方式,每个进程被分配一个时间段,按照在队列中的顺序交替执行;不利于处理紧急作业。
5、多级反馈队列(multilevel feedback queue): UNIX使用这种调度算法;进程在进入待调度的队列等待时,首先进入优先级最高的Q1中等待;首先调度优先级高的队列中的进程。若高优先级队列中已经没有调度的进程,则调度次优先级队列的进程;同一队列中的各个进程按照时间片轮转调度;在低优先级队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业(剥夺)。
2. 调研task_struct结构体, 理解结构体中的各个字段的含义.
task_struct结构:
1.进程状态,将记录进程在等待,运行或死锁。
2.调度信息,由哪个调度函数调度,怎样调度等。
3.进程的通讯情况
4.因为要插入进程树,必须有联系父子兄弟的指针,当然是task_struct型
5.时间信息,比如计算好执行的时间,以便cpu分配。
6.标号,决定改进进程归属
7.可以读写打开文件的一些信息
8.进程上下文和内核上下文
9.处理器上下文
10.内存信息
因为每一个PCB都是这样的,只有这些结构,才能满足一个进程的所有要求
3. 使用代码模拟实现僵尸进程, 孤儿进程的场景.
如果子进程先死,子进程就会变成僵尸进程(清理僵尸,结束父进程)
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- int main(void)
- {
- pid_t pid=fork();
- if(pid>0){
- printf("This is parent!\n");}
- else if(pid==0){
- printf("This is child!\n");
- sleep(3);
- exit(EXIT_SUCCESS);}
- }
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- int main(void)
- {
- pid_t pid=fork();
- if(pid>0){
- printf("This is parent!\n");
- sleep(3);
- exit(0);}
- else if(pid==0){
- printf("This is child!\n");
- sleep(3);}
- }
设置环境变量 putenv(“name=value”) 函数
取值 getenv(“环境变量名”)
环境变量:本进程和子进程都能使用 export 变量名
如果子进程先死,子进程就会变成僵尸进程(清理僵尸,结束父进程)