进程间通信

来源:互联网 发布:电脑硬件温度监控软件 编辑:程序博客网 时间:2024/06/11 09:58

1,进程中的两种关系

  进程同步与进程互斥

  1,顺序程序特征(顺序性,封闭性,确定性,可再现性)

  2,并发程序的特征(共享性,并发性,随机性)

  互斥:由于进程间要求资源共享,而且有些资源需要互斥使用,因此各进程竞争使用这些资源。。。

     这种关系称为进程的互斥(排它)

     系统中的某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源

     在程序中,涉及到互斥资源的程序段叫做临界区。。。(航空售票系统)

  同步:多个进程需要相互配合,共同完成一项任务。。

     

     P1进程启动车辆必须的等到P2进程售票员关门之后才可以执行;

     P2进程开门也同样必须等到p1进程司机到站停车之后才可以。

     

  我们区分多个进程是同步还是互斥,从逻辑上看是相互协作还是应该独占资源

  通常情况下,我们将这两种关系统称为同步。。。。

2,进程间通信的目的

  1,数据传输:一个进程需要将它的进程发送给另外一个进程

  2,资源共享:多个进程之间共享同样的资源

  3,通知事件:一个进程需要向另外一个或一组进程发送消息,,通知它们发生了某种事件。

    如:子进程终止时需要通知父进程,如上汽车售票(司机和售票员)

  4,进程控制:有些进程希望完全控制另一个进程的执行,如(debug进程),此时:

    控制进程希望能拦截另外一个进程的所有异常和陷入,并能够直到状态的随时改变。。

3,进程间通信发展

  1,管道,是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系

       的进程间使用。进程间的亲缘关系通常指父子进程关系。。。

    有名管道:可以用于不相关的进程间进行通信。。。也是半双工的通信方式。。。

  2,System V进程间的通信

  3,POSIX标准下的进程间通信

4,进程间通信分类

  1,文件(可以将传输的数据放置在文件中,通过文件来传输)

  2,文件锁(互斥与同步,,其中形成了文件锁)

    当一个进程对文件写的时候,不允许其它进程对文件读,跟不允许对文件写

    当一个进程对文件读的时候,其它进程对文件可以读

  3,管道(pipe)和有名管道(FIFO),用于进程间传输数据

  4,signal(信号),通过信号:一个进程可以向另一个进程发送通知事件

  5,消息队列:用于进程与进程间传递数据的

  6,共享内存:进程与进程间共享数据

  7,信号量:用于进程间的同步访问或者互斥访问

   

  System V和POSIX都具有各自的消息队列,共享内存,信号量(编程接口)

  8,互斥量

  9,条件变量

  10,读写锁

  (POSIX中存在的:互斥量,条件变量,读写锁;System V中并没有)

  也就是说:System V中要实现互斥量的话,可以通过信号量来实现

  11,套接字(Socket)

  

5,进程间共享信息的三种方式

  

   unix进程间通信的三种方式

6,IPC对象的持续性

  IPC其实就是进程间通信

  1,随进程持续:一直存在,直到打开的最后一个进程结束(如:pipe和FIFO)

  2,随内核持续:进程结束之后,也不会消亡

    一直存在直到内核自举(机器重启),或者显示删除

    (如:System V消息队列,共享内存,信号量)

  3,随文件系统持续:一直存在,直到显示删除,即使内核自举还是存在

    (如:POSIX下使用映射文件来实现,消息队列,共享内存,信号量



7,死锁

  1,互斥  矛盾   多个小孩争抢凳子

  2,同步  协作   司机与售票员的协同工作

  3,死锁:多个进程相互等待对方所占有的资源,而在得到对方的资源之前又不释

    放自己所占有的资源,这样的话,就有可能造成一种循环等待的现象,如果所

    有的进程都在等待一个不可能发生的事件,那么就会产生进程死锁。。。。。

    1,死锁产生的必要条件

      1,互斥条件

        进程对资源需要进行排它性使用,即在一段时间内,资源仅仅为某一个

        进程所占有

      2,请求和保持条件

        当进程因请求资源而阻塞时,对已经获得的资源保持不放。

      3,不可剥夺条件

        进程已获得资源未使用完之前,不能被剥夺,只能在使用完之后自己释放

      4,环路等待条件

        各个进程组成封闭的环形链,每个进程都等待下一个进程所占有的资源

      如上,就是死锁产生的四个条件,缺一不可。。。。

      所以,我们需要防止死锁的产生(破坏这些条件,当然:互斥条件是不能被破

      坏的,所以,我们应该尽可能的破坏后三个条件)

      资源一次性分配(破坏请求和保持条件):一个进程要占有资源,那么需要的资源必须都要得到满足,

             才能占有,而不能占有一半的资源,

      可剥夺资源(破坏不可剥夺条件)

      资源有序分配法(破坏循环等待条件)


    2,如上:预防死锁的策略中,会严重的损害系统的性能,

      (资源一次性分配原则,需要在所有的资源都得到满足的时候才能够占有资源,因而降低了一定的并发

      性),所以在避免死锁的时候,我们应该施加比较弱的限制,才会获得更加满意的系统性能


      由于死锁的避免策略中,允许进程动态的申请资源(而不需要在所有的资源都满足的情况下再去申请)

      ,但是动态的申请资源也有一定的限制,(分配的资源不会导致系统进入不安全的状态,才允许分配

      资源。。。不然,进程继续等待)

      其中:最具代表性的算法是银行家算法。。。。。。。。。。。。。。。。。。。。。。。。。。。。


      银行家算法:

      1,为保证资金的安全,银行家规定:

        1,当一个顾客对资金的最大需求量不超过银行家现有的资源时,就接纳该顾客

        2,顾客可以分期贷款,但是贷款的总数不能超过最大需求量

        3,当银行家现有的资金不能满足顾客尚需贷款的数额时,那么对于顾客的贷款可以

          推迟支付。。。但是,总能使得顾客在有限的时间里得到贷款

        4,当顾客得到所需的全部资金之后,一定能在有限的时间里归还所有的资金


      产生死锁的一个经典的例子:

      哲学家就餐的问题:

      1,五个哲学家围在一个圆桌就餐,每个人都必须拿起两把叉子才能用餐

        

         然后,所有的哲学家都做这样的事情

   

while(1){        思考;        if(饿)        {                拿左叉子;                拿右叉子;                用餐;                放下左叉子;                放下右叉子;        }}

    当一个特殊的情况出现时,所有的哲学家都拿起了左边的叉子,那么就造成了死锁。。。。

    那么如何解决哲学家就餐问题呢???

    1,服务生解法

      也就是说:哲学家拿叉子之前需要征求服务生的同意。服务生相当于一个管理者,

      在统一的分配刀叉。。。在判定当前的资源是不是处于一个安全的状态。。。。。

      如果处于安全的状态,那么服务生就允许哲学家将叉子拿起。。。不然,需要等待

    2,最多四个哲学家(不是一个好的方案,把题目都改了,4个哲学家5把叉子,那么

      一定会有一个哲学家2把叉子)

    3,仅当一个哲学家两边的筷子都可以用的时候,才允许他拿起筷子(破坏请求与保存条件)

    4,给所有的哲学家编号,奇数号的哲学家首先必须先拿左边的筷子,偶数号拿右边的筷子

      (破坏回路)

      

  信号量与PV原语

  1,信号量和P、V原语实际上由Dijkstra(迪杰斯特拉)(程序设计:goto语句是有害的,操作系统:信号

    量,pv原语的提出,最早解决来哲学家就餐的问题,网络:最短路径算法)提出的。。。。

    主要用来解决进程的同步和互斥问题。。。

    在计算机操作系统中,PV操作是进程管理中的难点。

    首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进

    行操作,具体定义如下:
   

    P(S):①将信号量S的值减1,即S=S-1;
           ②如果S>0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
       V(S):①将信号量S的值加1,即S=S+1;
           ②如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。

   PV操作的意义:我们用信号量及PV操作来实现进程的同步和互斥。PV操作属于进程的低级通信。

   信号量:P,V操作在同一进程中(互斥)       P,V操作不在同一进程(同步)

   

   

struct semaphore{        int value;        pointer_PCB queue;}

P原语:

P(s){        s.value = s.value--;        if(s.value < 0)        {                该进程状态置为等待状态                将该进程的PCB插入相应的等待队列s.queue末尾        }}
V原语:

V(s){        s.value = s.value++;        if(s.value <= 0)        {                唤醒相应等待队列s.queue中等待的一个进程                改变其状态为就绪状态                并将其插入就绪队列        }}


如上:代码是原子操作的,也就是不能被打断。。。。。。。

pv操作,主要用来解决进程的同步和互斥问题。。。。。。

  2,

  用PV原语解决司机与售票员的问题

  

  同一个信号量的pv操作不在一个进程中,协同

  用PV原语解决民航售票的问题

  

  用PV原语解决汽车租赁的问题 

  有一汽车租赁公司有两辆车可以出租,假定同时来了四个顾客都要租车,那么肯定会有两个人租不到。。。

  

  (如果我们不曾相遇,你有会在哪里)

  

0 0
原创粉丝点击