操作系统--进程

2022/2/7 7:14:02

本文主要是介绍操作系统--进程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

线程和进程

1. 进程

1.1 什么是进程

  • 运行中的程序

1.2为什么要有进程呢?

  • 为了任务能够交替执行。所以才有了进程的概念。

  • 进程是怎样让任务交替执行的?

    • 一个程序的用完一个时间片 进程会把程序的执行现场环境(各个cpu寄存器的值 以及PC)保存在进程的PCB中 。下次就可以接着上次的地方继续执行 所以任务就可以交替执行。
  • 进程是什么 执行序列和资源+现场环境

1.3 进程是怎样被交替执行

1.4 进程的构成

1.5 进程之间之怎样被切换的

       启动磁盘读写 
  // 设置当前进程状态为阻塞态
  pCur.state='W'
 将pCur放到DiskWaitQueue
  schedule()
  
 //  一 :schedule 函数
schedule(){
// 从就绪队列中选出下一个准备运行的进程
pNew=getNext(ReadyQueud);
// 切换到下一个进程
switch_to(pCur,pNew)
}
 
// 二:switch_to函数
switch_to(pCur,pNew){

// 保存上一个进程的执行进度
pCur.ax = CPU.ax;
pCur.bx = CPU.bx;
...
		// 代码段基地址
pCur.cs = CPU.cs;
		// pc: 指向下一条待执行的指令
pCur.retpc = CPU.pc;
  
// 恢复待执行进程的执行进度
CPU.ax = pNew.ax;
CPU.bx = pNew.bx;
...
CPU.cs = pNew.cs;
CPU.retpc = pNew.pc;
}

2. 线程

2.1 为什么要有线程呢?

  • 进程切换效率低。怎么保证并发的优势 又能高效的切换 所以有了线程。
  • 现场不切换资源(内存) 只切换指令序列

2.2 用户线程是怎么切换的呢?

  • 核心是栈的切换

void Yield(){
  TCB1.esp=esp;
  esp=TCB2.esp;

}

2.3 用户线程的优缺点?

  • 处理器竞争:单纯的用户线程是建立在用户空间,其对内核是透明的,因此其所属进程单独参与处理器的竞争,而进程的所有线程参与竞争该进程的资源。所以还无法利用对核的优势 并且只要有一个线程堵塞 OS会认为整个进程都会被堵塞。
  • 使用资源:与所属进程共享进程地址空间和系统资源。
  • 调度:由在用户空间实现的线程库,在所属进程内进行调度

2.4 内核线程

2.4.1 为什么要有内核线程
  • 为了能够利用多核优势,所以才有了内核线程
2.4.2 用户线程和核心线程是什么关系呢?常用的是一对一
  • 用户线程和进程的关系
2.4.3 内核线程的特点
  • 内核线程创建和撤销都是操作系统干的事 所以操作系统可感知到线程的存在 ,可以利用多核的优势

  • 内核态线程,创建成本高 通常我们会在内核中预先创建一些线程,并反复利用这些线程

2.5 内核线程是怎么实现的呢?(后续待完善)

  • 程序
main()
{
A();
B();
}
A();
{
//fork是系统调用,引会引起中断
  // fork 不仅可以引起切换 也可以引起切换
fork();
}

  • _system_call : 初始化时将各种中断处理设置好
_system_call:
 // 各种压栈 注意是压的是用户寄存器的值
push %ds..%fs
pushl %edx...
call sys_fork
pushl %eax
movl _current,%eax
  // 判断当前线程是否阻塞
cmpl $0,state(%eax)
  // 切换
jne reschedule
  // 判断当前线程是否时间片用完
cmpl $0,counter(%eax)
    // 切换
je reschedule
ret_from_sys_call:
// 进程切换函数
void schedule(void){ 
  // 根据调度算法选择一个合适的线程
  next=i;
  // 切换到下个进程
switch_to(next); }

// 系统调用返回
ret_from_sys_call:
popl %eax // 回值popl %ebx ...
pop %fs ...
iret//  返回到int 0x80后面执行  mov res,%eax res=?
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,long ebx,long ecx,long edx, long
fs,long es,long ds,long eip,long cs,long eflags,long esp,long ss)
 
copy_process:
// 申请TCB 
p=(struct task_struct *)get_free_page();
//创建内核栈
p->tss.esp0 = PAGE_SIZE + (long) p;
p->tss.ss0 = 0x10;
// 创建用户栈(和父进程共用的用户栈)
p->tss.ss = ss & 0xffff;
p->tss.esp = esp;

3. 进程调度(CPU调度算法)

3.1 什么是cpu调度算法

  • 在就绪队列中选择哪个线程执行

3.2 一款很合理的调度算法 应该考虑什么?

  • 短时间内让cpu执行更多的任务

3.3 基本的调度算法

  • 先来先服务
    • 特点:这似乎很公平 但是当一个长作业先运行了 ,那么后面的短作业等待的时间就会很长 不利短作业
  • 短作业优先
    • 特点:会有优先选择运行时间最短的进程来运行 这有助提高系统吞吐量 但是对长作业不利 很容易造成一种极端的现象 比如一个长作业在就绪队列等待运行 假如这个就绪队列有很多短作业 导致长作业不短往后排 导致长作业一直不会被运行
  • 时间片轮转
    • 特点 每个进程分配一个时间片 轮流执行 如果进程在时间片结束前提前结束活着阻塞 ,切换到其他进程上。但是用户更希望调度有优先级 每次调度优先级高的
  • 高优先级优先
    • 特点:每次选择优先级高的运行 如果优先级不能动态调整 那么将导致优先级低的一直被推后

3.4 Linux 0.11 的调度算法

  • 时间片+动态调整优先级算法

  • 作用counter:优先级 和 时间片

void Schedule(void) 
  //在kernel/sched.c中
{ while(1) 
	{ 
  c=-1; next=0;
  i=NR_TASKS;
  // NR_TASKS 队列的length
  p=&task[NR_TASKS];
while(--i){ 
  // 1.从就绪队列中找出最大的counter运行
  if((*p->state == TASK_RUNNING && (*p)->counter>c)
  c=(*p)->counter, next=i; 
     }
if(c) break; //找到了最大的counter 
   // 动态调整优先级所有任务的的优先级  优先级=1/2*counter + priority(时间片) 
   // 如果任务被调度过那么 counter=0 即 优先级=1/2*0 + priority(时间片)  所有动态调整后 没运行的优先级会被调高
for(p=&LAST_TASK;p>&FIRST_TASK;--p)    
(*p)->counter=((*p)->counter>>1)
+(*p)->priority; }
  // 切换到下一个进程运行   
switch_to(next);}

4. 进程的同步

4.1 什么是进程的同步

  • 多个进程间走走停停 按照一定的顺序向前推进

4.2 怎么保证进程间走走停停—信号量

  • 信号量:记录一些信息的量 并根据这信息来决定这个进程是唤醒还是睡眠

4.3 信号量的实现

  • struct semaphore
    {
      int value;// 记录资源的个数
      PCB *queue; //记录等待在该信号量上的进程
    } 
    p(semaphore s) // 消费资源
    v(semaphore s) // 生产资源
    
    P(semaphore s){
      s.value--;
      if(s.value<0){
        sleep(s.quenue);
      }
    }
    
    V(semaphore s){
      s.value++;
      if(s.value<=0){
        wakeup(s.quenue);
      }  
    }
    

4.4 信号量的解决生产者和消费者的问题

5. 信号量临界区保护

5.1 为什么要保护信号量

  • 假如多个生产着 ,对信号量i进行修改 如果不保护可能导致最终信号量的值是错误的,所以就要互斥进入,如果一个进程在临界区中执行 则其他进程不允许进入

5.2 好的临界区保护原则

  • 互斥进入

  • 有空让进

  • 有限等待

5.3 两个进程怎么利用代码实现临界资源的保护

5.4 多个进程怎么利用代码实现

  • 面包店算法

5.5 硬件实现



这篇关于操作系统--进程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程