进程管理

一、进程与线程

1、进程

进程是资源分配的基本单位。进程是一段程序执行的过程。

  • 进程是一个实体。每个进程都有它自己的地址空间。
  • 进程是一个“执行中的程序”。

程序:程序是指令和数据的有序集合。本身没有运行的含义,是一个静态的概念。

2、线程

线程是独立调度的基本单位

一个进程中可以有很多个线程,它们共享进程资源。

QQ和浏览器是两个进程,浏览器进程有很多线程,例如HTTP请求线程,事件响应线程,渲染线程等。线程的并发执行使得浏览器点击一个新链接从而发起HTTP请求,浏览器还可以响应用户的其他事件。

3、区别

  • 拥有资源:进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
  • 调度:线程是独立调度的基本单位,再同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
  • 系统开销:由于创建或者撤销进程,系统都要为之分配或回收资源,如内存空间、I/O设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,再进行线程切换时,涉及当前执行进程CPU环境的保存及新调度进程CPU环境的设置,而线程切换只需要保存和设置少量寄存器内容,开销很小。
  • 通信:线程间可以通过直接读写同一进程中地数据进行通信,但是进程通信需要截出IPC。
  • 资源管理方式:进程有独立地地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程只是一个进程地不同执行路径。线程有自己地堆栈和局部变量,但是没有单独地地址空间。一个线程死掉等于整个进程死掉

主线程和子线程都有各自独立的pcb。
主线程(由进程退化而来)和子线程

共享:.text .bss .data 堆 动态库加载区 环境变量 命令行参数

通信:全局变量、堆

不共享:栈(如果一共5个线程,栈区被平均分为5份)

线程不要传递局部变量的地址,因为每个线程的栈区都是不稳定的,经常会改变。

4、优缺点

线程执行开销小,但不利于资源的管理和保护;进程正相反。

多线程的优点

  • 无需跨进程边界;
  • 程序逻辑和控制方式简单;
  • 所有线程可以直接共享内存和变量等;
  • 线程方式消耗的总资源比进程方式好

多线程的缺点

  • 每个线程与主线程共用地址空间,受限于2GB地址空间;
  • 线程之间的同步与加所控制比较麻烦;
  • 一个线程崩溃可能影响整个程序的稳定性
  • 到达一定线程数的程度后,即使再增加CPU也无法提高性能。
  • 线程能够提高的总性能有限,而且线程多了,其本身调度也颇为麻烦,需要消耗比较多的CPU

多进程的优点

  • 每个进程相互独立,不影响主程序的稳定性,子进程崩溃不会影响其他子进程。
  • 通过增加CPU,就可以容易的扩充性能。
  • 可以尽量减少线程加锁/解锁的影响,极大提高性能,就算是线程运行的模块算法效率低也没关系。
  • 每个子进程都有2GB地址空间个相关资源,总体能达到的性能上限非常大

多进程的缺点

  • 逻辑控制复杂,需要和主程序交互;
  • 需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算
  • 多进程调度开销比较大

5、通信方式

进程
  • 管道(pipe):半双工,单向流动,只能在具有亲缘关系的进程使用
  • 有名管道(namepipe):半双工,允许无亲缘关系进程通信
  • 信号量(semphore):控制多个进程对共享资源的访问,常作为锁机制
  • 消息队列(messagequeue):消息队列。克服了信号传递信息少,管道只能承载无格式字节流和缓冲区大小受限
  • 信号(signal):用于通知接收进程某个事件已经发生
  • 共享内存(shared memory):映射一段能够被其他进程访问的内存
  • 套接字(socket):可用于不同及其间的进程通信
线程
  • 锁机制:包括互斥锁、条件变量、读写锁
    • 互斥锁提供了以排他方式防止数据结构被并发修改的方法
    • 读写锁允许多个线程同时读共享数据,但对写操作是互斥的
    • 条件变量可以以原子的方式阻塞进程,直到某个特定条件为真。与互斥锁一起使用,对条件的测试是在互斥锁的保护下进行的。
  • 信号量机制(Semaphore)
  • 信号机制(Signal)

二、进程状态的切换

在这里插入图片描述
在这里插入图片描述


三、进程调度算法

1、先来先服务和端作业有限调度算法

  • 先来先服务 first-come first-served(FCFS)
    适用场景:比较利于长作业,因为长作业会长时间占据处理机。有利于CPU繁忙的作业,而不利于I/O繁忙的作业

  • 短作业优先 shortest job first(SJF)主要不足之处式长作业的运行得不到保证

  • 最短剩余时间优先 shorted remaining time next (SRTN)

2、高优先权优先调度算法

  • 优先级调度(避免低优先级永远等不到调度,可随时间推一增加等待进程的优先级)
    • 非抢占式优先权算法:一旦处理机分配给就绪队列优先权最高的进程,便会一直执行直至完成(主要用于批处理系统,也可用于对实时性要求不高的实时系统中)
    • 抢占式优先权算法:若出现优先权更高的进程,进程调度程序立即停止当前进程,重新分配给优先权最高的进程。(常用于要求严格的实时系统中,以及对性能要求较高的批处理和分时系统中)
  • 高响应比有限调度算法:引入动态优先权,优先级随时间增加而以速率a提高。

2、基于时间片的轮转调度算法

  • 时间片轮转(FCFS原则排成队列,每次分配时间片给队首,队首进程完了送到末尾)
    优点式兼顾长短作业;缺点是平均等待时间较长,上下文切换费时,适用于分时系统。
  • 多级反馈队列(FCFS和时间片轮转的结合)

3、实时系统

硬实时:满足绝对的截止时间
软实时:可容忍一定的超时


三、进程同步问题

1、生产者和消费者问题

问题描述:一组生产者进程和一组消费者进程共享一块初始为空,大小确定的缓冲区,只有当缓冲区不为满时,生产者进程才可以把信息放入缓冲区,否则就要等待;只有缓存区不为空时,消费者进程才能从中取出消息,否则就要等待。缓冲区一次只能一个进程访问(临界资源)。

问题分析:生产者与消费者进程对缓冲区的访问是互斥关系,而生产者与消费者本身又存在同步关系,即必须生成之后才能消费。因而对于缓冲区的访问设置一个互斥量,再设置两个信号量一个记录空闲缓冲区单元,一个记录满缓冲区单元来实现生产者与消费者的同步。

伪代码

semaphore mutex=1;
semaphore full=0;         //满缓冲区单元
semaphore empty=N;    //空闲缓冲区单元

prodecer()
{
    while(1)
    {
          P(empty);          
          P(mutex);
          add_source++;
          V(mutex);
          V(full);      
    }    
}        

consumer()
{
    while(1)
   {
         P(full);
         P(mutex);
         add_source--;
         V(mutex);
         V(empty);     
    }    
}

2、读者和写者问题

问题描述:有读者与写者两个并发进程共享一个数据,两个或以上的读进程可以访问数据,但是一个写者进程访问数据与其他进程都互斥。

问题分析:读者与写者是互斥关系,写者与写者是互斥关系,读者与读者是同步关系。因而需要一个互斥量实现读与写和写与写互斥,一个读者的访问计数和实现对计数的互斥。

问题解决:三种伪代码实现

1、读者优先

读者优先,只要有读者源源不断,写者就得不到资源。容易造成写者饥饿。

//读者优先

int count=0;
semaphore mutex=1;    //读者计数锁
semaphore rw=1;        //资源访问锁
//写者
writer()
{
    while(1)
    {
        P(rw);
        writing sth;
        V(rw);
    }
}
//读者
reader()
{
    while(1)
    {
        P(mutex);
        if(count==0)
            P(rw);
        count++;//读者计数
        V(mutex);
        reading sth;
        P(mutex);
        count--;
        if(count==0)
            V(rw);
        V(mutex)}
}

2、读写公平

读者与写者公平抢占资源,但是只要之前已经排队的读者,就算写者获取到资源,也要等待所有等待的读者进程结束。

//读写公平
int count=0;
semaphore mutex=1;    //读者计数锁
semaphore rw=1;        //资源访问锁
semaphore w=1;        //读写公平抢占锁
writer()
{
    while(1)
    {
        P(w);
        P(rw);
        writing sth;
        V(rw);
        V(w);
    }
}

reader()
{
    while(1)
    {
        P(w);
        P(mutex);
        if(count==0)
            P(rw);
        count++;
        V(mutex);
        V(w);
        reading sth;
        P(mutex);
        count--;
        if(count==0)
            V(rw);
        V(mutex);        
    }
}

3、写者优先

写者优先,只要写者源源不断,读者就得不到资源,但是在这之前已经排队的的读者进程依然可以优先获得资源,在这之后则等待所有写者进程的结束。这种也易造成读者饥饿。

//写者优先
int write_count=0;         //写计数
int count=0;               //读计数
semaphore w_mutex=1;     //读计数时锁
semaphore r_mutex=1;    //写计数时锁
semaphore rw=1;            //写优先锁
semaphore source=1;        //资源访问锁

writer()
{
    while(1)
    {
        P(w_mutux);
        if(write_count==0)
            P(rw);        //获得则只要有写进程进来就不释放
        write_count++;
        V(w_mutux)
    
        P(resouce);        //写时互斥必须加资源独占的锁
        writing sth;
        V(resouce);
        
        P(w_mutux);
        write_count--;
        if(write_count==0)
            V(rw);
        V(w_mutux);
    }
}

reader()
{
    while(1)
    {
        P(rw);            //使用了立即释放
        P(r_mutex);
        if(count==0)
            P(resouce);
        count++;
        V(r_mutex);
        V(rw);
    
        reading sth;
        
        P(r_mutex);
        count--;
        if(count==0)
            V(resouce);
        V(r_mutex);        
    }
}

2、哲学家就餐问题

问题描述:一张圆桌上坐着五名哲学家,每两名哲学家之间的桌子摆一根筷子,哲学家只有同时拿起左右两根筷子时才可以用餐,用餐完了筷子放回原处。

问题分析:这里五名哲学家就是五个进程,五根筷子是需要获取的资源。可以定义互斥数组用于表示五根筷子的互斥访问,为了防止哲学家个取一根筷子出现死锁,需要添加一定的限制条件。一种方法是限制仅当哲学家左右筷子均可以用时,才拿起筷子,这里需要一个互斥量来限制获取筷子不会出现竞争。

问题解决:一次仅能一个哲学家拿起筷子,效率比较低。

semaphore chopstick[5]={1,1,1,1,1};
semaphore mutex=1;
pi()
{
    while(1)
    {
        P(mutex);
        P(chopstick[i]);
        P(chopstick[(i+1)%5]);
        V(mutex);
        
        eating;
        
        V(chopstick[i]);
        V(chopstick[(i+1)%5]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值