操作系统学习

来源:互联网 发布:linux系统版本查看命令 编辑:程序博客网 时间:2024/05/14 12:18

转自:http://blog.csdn.net/ingwfj/article/details/52332615

再次拿起《现代操作系统》这本书,精心仔细阅读,又有了几点体会记录一下。

操作系统的功能或者说职责:向下管理资源,向上提供服务接口。OS作为中间层软件。操作系统涉及到的主要内容有进程和线程、文件系统、死锁、内存管理、I/O管理等。

进程和线程涉及到概念、区别、类别等,进程是存在输入输出和状态的一段正在执行的程序,是动态的而非仅仅是静态的程序。进程就涉及到其运行、阻塞和就绪的生命周期,其实程序方面很多都存在生命周期,例如Java的诸多框架中例如spring中存在对象的生命周期,structs中请求存在生命周期等。进程中重要的概念是进程表,存储在内存中,其单位是进程表项即entry,看到entry就想起了java中集合类中的entry内部类,java的内部类被很多人推崇而同时又被另外一些人所诟病,其实进程表是所有在内存中的和不再内存中的进程的reference,其内保存了进程的状态数据,说实话表看来真的很给力,在很多地方会看到表的广泛应用和巨大威力,例如数据库的基层就是表当然是关系型数据库,新的NoSQL类型打破了一些传统,例如在网络中表格也起着格式存储数据的作用,现实生活中表格也是重要的。对于线程,有两点很让我感兴趣的方面,一个是用户空间中的线程模型和内核空间中的线程模型,不同的模型应用到了不同的实际操作系统中。另一个是进程之间的通信和同步互斥机制,涉及到中断机制、忙等待、原语、生产者-消费者模型、PV操作、互斥量、管程、屏障等概念。还有进程需要调度算法来进行调度的,因为内存资源有限而且为了最大地提高运行效率最大的利用CPU而导致诸多调度算法,例如先来先服务算法、最短作业优先、最短剩余时间优先、彩票调度等。哲学家就餐问题和读者-写者问题资料也很多。还有进程的互斥和同步、阻塞和非阻塞、同步和异步之间的区别我找了半天才明白。

进程阻塞和非阻塞的区别:http://www.zhihu.com/question/19732473

进程的互斥和同步:http://blog.chinaunix.net/uid-26748613-id-3201137.html

进程的同步与异步:http://blog.sina.com.cn/s/blog_8c0c9acd0101cp3u.html

内存管理方面,涉及到虚拟内存机制、MMU、TLB、分页和分段机制、页面置换算法等问题。我从这章深切体会到两点:一,问题是充满矛盾的,经常是没有最终确定的答案,最重要的分析的过程,提出一种方案分析其涉及的方面,他的优点和缺点,有很多解决方法但是没有完美方案,就像没有银弹一样。哲学中矛盾是一大核心,也是其一些理论支撑的基础,现实中矛盾是无时无刻不有的;第二,在操作系统中,进程/线程是对实际CPU的抽象,地址空间是对物理内存的抽象,文件是对物理内存的抽象,I/O流是对硬件输入输出设备的抽象。而抽象和模拟一直是我对计算机、网络、操作系统、语言等方面的核心认识,而在抽象之后就需要增删改查、管理、优化算法等方面,整个操作系统就是讲这些东西。

文件系统中涉及到磁盘、磁盘管理、文件系统存储模式、高速缓存等。文件系统就联系到数据结构中学到B树、B+树、B*树等数据结构知识。

I/O处理方面,包括中断处理系统、设备驱动程序、与设备无关的I/O软件、用户级I/O软件等软件方面内容和I/O硬件例如DMA、设备驱动、设备控制等。一大感受是DMA控制器中有地址寄存器、计数寄存器、控制寄存器,DMA可以进行独立访问总线,可以进行存储,可以进行控制,不能进行计算,这不就相当于缩减版的CPU吗?他确实分担了部分CPU的工作使得CPU可以做其他工作以提高其利用率。这其中中断起着关键作用,中断控制器属于计算机系统结构方面知识,可是他起着中断接受、排队、屏蔽等作用。

死锁应该是最激动人心的方面,因为诸多算法在其中啊。为了避免死锁,设置安全状态和非安全状态,使用多维度轨迹路线算法,使用银行家算法,并且创建了打破死锁状况的方法,当然书中坦言没办法避免死锁,因为进程是动态,所需资源无法预计,资源是否能用不确定。我比较喜欢算法研究,所以激动人心啊。


总之,操作系统是一种管理软件,他特别像公司,公司的员工是硬件资源,而公司的制度便是这个系统,然而制度是为了做什么的?为了有效配置人员,为了提高效率啊。操作系统也是啊,为了管理资源,为了最大的提高效率,为了给应用软件提供接口。他是一个平台,是软件的根基,是一种先进的理念。

----------------------------------------------------------------------------------------------------------------------------------------------

转自:http://blog.chinaunix.net/uid-26748613-id-3201137.html

进程同步的几种机制  转自:http://www.cnblogs.com/sonic4x/archive/2011/07/05/2098036.html

多进程的系统中避免不了进程间的相互关系。本讲将介绍进程间的两种主要关系——同步与互斥,然后着重讲解解决进程同步的几种机制。 
      进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。通常的情况是两个或两个以上的进程需要同时访问某个共享变量。我们一般将发生能够问共享变量的程序段称为临界区。两个进程不能同时进入临界区,否则就会导致数据的不一致,产生与时间有关的错误。解决互斥问题应该满足互斥和公平两个原则,即任意时刻只能允许一个进程处于同一共享变量的临界区,而且不能让任一进程无限期地等待。互斥问题可以用硬件方法解决,我们不作展开;也可以用软件方法,这将会在本讲详细介绍。 
      进程同步是进程之间直接的相互作用,是合作进程间有意识的行为,典型的例子是公共汽车上司机与售票员的合作。只有当售票员关门之后司机才能启动车辆,只有司机停车之后售票员才能开车门。司机和售票员的行动需要一定的协调。同样地,两个进程之间有时也有这样的依赖关系,因此我们也要有一定的同步机制保证它们的执行次序。 
本讲主要介绍以下四种同步和互斥机制:信号量、管程、会合、分布式系统。

一,信号量

参考自http://blog.csdn.net/leves1989/article/details/3305609

理解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操作属于进程的低级通信。

什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
     一般来说,信号量S?0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S?0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。

利用信号量和PV操作实现进程互斥的一般模型是:
进程P1              进程P2           ……          进程Pn
……                  ……                           ……
P(S);              P(S);                         P(S);
临界区;             临界区;                        临界区;
V(S);              V(S);                        V(S);
……                  ……            ……           ……

    其中信号量S用于互斥,初值为1。
    使用PV操作实现进程互斥时应该注意的是:
    (1)每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。
    (2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
   (3)互斥信号量的初值一般为1。

利用信号量和PV操作实现进程同步
PV操作是典型的同步机制之一。用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;当信号量的值非0时,表示期望的消息已经存在。用PV操作实现进程同步时,调用P操作测试消息是否到达,调用V操作发送消息。
    使用PV操作实现进程同步时应该注意的是:

    (1)分析进程间的制约关系,确定信号量种类。在保持进程间有正确的同步关系情况下,哪个进程先执行,哪些进程后执行,彼此间通过什么资源(信号量)进行协调,从而明确要设置哪些信号量。
    (2)信号量的初值与相应资源的数量有关,也与P、V操作在程序代码中出现的位置有关。
    (3)同一信号量的P、V操作要成对出现,但它们分别在不同的进程代码中。

【例1】生产者-消费者问题
在多道程序环境下,进程同步是一个十分重要又令人感兴趣的问题,而生产者-消费者问题是其中一个有代表性的进程同步问题。下面我们给出了各种情况下的生产者-消费者问题,深入地分析和透彻地理解这个例子,对于全面解决操作系统内的同步、互斥问题将有很大帮助。

(1)一个生产者,一个消费者,公用一个缓冲区。
定义两个同步信号量:
empty——表示缓冲区是否为空,初值为1。
   full——表示缓冲区中是否为满,初值为0。
生产者进程
while(TRUE){
生产一个产品;
     P(empty);
     产品送往Buffer;
     V(full);
}
消费者进程
while(True){
P(full);
   从Buffer取出一个产品;
   V(empty);
   消费该产品;
   }
(2)一个生产者,一个消费者,公用n个环形缓冲区。
定义两个同步信号量:
empty——表示缓冲区是否为空,初值为n。
full——表示缓冲区中是否为满,初值为0。

    设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指
,指向下一个可用的缓冲区。
生产者进程
while(TRUE){
     生产一个产品;
     P(empty);
     产品送往buffer(in);
     in=(in+1)mod n;
     V(full);
}
消费者进程
while(TRUE){
 P(full);
   从buffer(out)中取出产品;
   out=(out+1)mod n;
   V(empty);
   消费该产品;
   }
(3)一组生产者,一组消费者,公用n个环形缓冲区
    在这个问题中,不仅生产者与消费者之间要同步,而且各个生产者之间、各个消费者之间还必须互斥地访问缓冲区。
定义四个信号量:
empty——表示缓冲区是否为空,初值为n。
full——表示缓冲区中是否为满,初值为0。
mutex1——生产者之间的互斥信号量,初值为1。
mutex2——消费者之间的互斥信号量,初值为1。

    设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指针,指向下一个可用的缓冲区。
生产者进程
while(TRUE){
     生产一个产品;
     P(empty);
     P(mutex1);
     产品送往buffer(in);
     in=(in+1)mod n;
     V(mutex1);
     V(full);
}
消费者进程
while(TRUE){
 P(full)
   P(mutex2);
   从buffer(out)中取出产品;
   out=(out+1)mod n;
   V(mutex2);
   V(empty);
   消费该产品;
   }
  需要注意的是无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒。应先执行同步信号量的P操作,然后再执行互斥信号量的P操作,否则可能造成进程死锁。

【例2】桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。

分析 在本题中,爸爸、儿子、女儿共用一个盘子,盘中一次只能放一个水果。当盘子为空时,爸爸可将一个水果放入果盘中。若放入果盘中的是桔子,则允许儿子吃,女儿必须等待;若放入果盘中的是苹果,则允许女儿吃,儿子必须等待。本题实际上是生产者-消费者问题的一种变形。这里,生产者放入缓冲区的产品有两类,消费者也有两类,每类消费者只消费其中固定的一类产品。

    解:在本题中,应设置三个信号量S、So、Sa,信号量S表示盘子是否为空,其初值为l;信号量So表示盘中是否有桔子,其初值为0;信号量Sa表示盘中是否有苹果,其初值为0。同步描述如下:
int S=1;
int Sa=0;
int So=0;
      main()
      {
        cobegin
            father();      /*父亲进程*/
            son();        /*儿子进程*/
            daughter();    /*女儿进程*/
        coend
    }
    father()
    {
        while(1)
          {
            P(S);
            将水果放入盘中;
            if(放入的是桔子)V(So);
            else  V(Sa);
           }
     }
    son()
    {
        while(1)
          {
             P(So);
             从盘中取出桔子;
             V(S);
             吃桔子;
            }
    }
    daughter()
    {
         while(1)
            {
              P(Sa);
              从盘中取出苹果;
              V(S);
              吃苹果;
            }

 
思考题:

四个进程A、B、C、D都要读一个共享文件F,系统允许多个进程同时读文件F。但限制是进程A和进程C不能同时读文件F,进程B和进程D也不能同时读文件F。为了使这四个进程并发执行时能按系统要求使用文件,现用PV操作进行管理,请回答下面的问题:
    (1)应定义的信号量及初值:                    。
    (2)在下列的程序中填上适当的P、V操作,以保证它们能正确并发工作:
     A()                B()                  C()                 D()
      {                 {                    {                  {
      [1];                [3];                  [5];                 [7];
      read F;             read F;                read F;              read F;
     [2];                [4];                  [6];                 [8];
      }                  }                    }                  } 

    思考题解答:
(1)定义二个信号量S1、S2,初值均为1,即:S1=1,S2=1。其中进程A和C使用信号量S1,进程B和D使用信号量S2。
(2)从[1]到[8]分别为:P(S1) V(S1) P(S2) V(S2) P(S1) V(S1) P(S2) V(S2)

 

 

二,管程:参考自http://hi.baidu.com/zucenaa/blog/item/e63d22277c9d9c09918f9de2.html

信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。

管程作为一个模块,它的类型定义如下: 
monitor_name = MoNITOR; 
共享变量说明; 
define 本管程内部定义、外部可调用的函数名表; 
use 本管程外部定义、内部可调用的函数名表; 
内部定义的函数说明和函数体 

共享变量初始化语句; 
}

 

从语言的角度看,管程主要有以下特性: 
(1)模块化。管程是一个基本程序单位,可以单独编译; 
(2)抽象数据类型。管程是中不仅有数据,而且有对数据的操作; 
(3)信息掩蔽。管程外可以调用管程内部定义的一些函数,但函数的具体实现外部不可见; 
对于管程中定义的共享变量的所有操作都局限在管程中,外部只能通过调用管程的某些函数来间接访问这些变量。因此管程有很好的封装性。 
为了保证共享变量的数据一致性,管程应互斥使用。 管程通常是用于管理资源的,因此管程中有进程等待队列和相应的等待和唤醒操作。在管程入口有一个等待队列,称为入口等待队列。当一个已进入管程的进程等待时,就释放管程的互斥使用权;当已进入管程的一个进程唤醒另一个进程时,两者必须有一个退出或停止使用管程。在管程内部,由于执行唤醒操作,可能存在多个等待进程(等待使用管程),称为紧急等待队列,它的优先级高于入口等待队列。 
因此,一个进程进入管程之前要先申请,一般由管程提供一个enter过程;离开时释放使用权,如果紧急等待队列不空,则唤醒第一个等待者,一般也由管程提供外部过程leave。 
管程内部有自己的等待机制。管程可以说明一种特殊的条件型变量:var c:condition;实际上是一个指针,指向一个等待该条件的PCB队列。对条件型变量可执行wait和signal操作:(联系P和V; take和give) 
wait(c):若紧急等待队列不空,唤醒第一个等待者,否则释放管程使用权。执行本操作的进程进入C队列尾部; 
signal(c):若C队列为空,继续原进程,否则唤醒队列第一个等待者,自己进入紧急等待队列尾部。

 

【示例】

生产者-消费者问题(有buffer)

问题描述:(一个仓库可以存放K件物品。生产者每生产一件产品,将产品放入仓库,仓库满了就停止生产。消费者每次从仓库中去一件物品,然后进行消费,仓库空时就停止消费。 
解答: 
管程:buffer=MODULE; 
(假设已实现一基本管程monitor,提供enter,leave,signal,wait等操作)

  notfull,notempty:condition; // notfull控制缓冲区不满,notempty控制缓冲区不空; 
count,in,out: integer;     // count记录共有几件物品,in记录第一个空缓冲区,out记录第一个不空的缓冲区 
buf:array [0..k-1] of item_type; 
define deposit,fetch; 
use monitor.enter,monitor.leave,monitor.wait,monitor.signal;


procedure deposit(item); 

  if(count=k) monitor.wait(notfull); 
  buf[in]=item; 
  in:=(in+1) mod k; 
  count++; 
  monitor.signal(notempty); 

procedure fetch:Item_type; 

  if(count=0) monitor.wait(notempty); 
  item=buf[out]; 
  in:=(in+1) mod k; 
  count--; 
  monitor.signal(notfull); 
  return(item); 


count=0; 
in=0; 
out=0; 

进程:producer,consumer; 
producer(生产者进程): 
Item_Type item; 

  while (true) 
  { 
    produce(&item); 
    buffer.enter(); 
    buffer.deposit(item); 
    buffer.leave(); 
  } 

consumer(消费者进程): 
Item_Type item; 

  while (true) 
  { 
    buffer.enter(); 
    item=buffer.fetch(); 
    buffer.leave(); 
    consume(&item); 
  } 
}

【附】有关wait和signal的语言表示

信号量结构使用C语言表示如下:


typedef struct { 
    int value;//记录了这个信号量的值  
    struct process *list;//储存正在等待这个信号量的进程  
} semaphore; 

wait()信号量部分代码如下:


wait(semaphore *S) { 
    S->value--; 
    if(S->value < 0) { 
        add this process to S->list; 
        block(); 
    } 

signal()信号量部分代码如下:


signal(semaphore *S) { 
    S->value++; 
    if(S->value <= 0) { 
        remove a process P from S->list; 
        wakeup(P); 
    } 

一、The Bounded-Buffer Problem:

full初始化为0,empty初始化为n,mutex为1


do{ 
    wait(full); 
    wait(mutex); 
    ... 
    //remove an item from buffer to nextc 
    ... 
    signal(mutex); 
    signal(empty); 
    ... 
    //consume the item in nextc 
    ... 
} while(TRUE); 

二、The Readers-Writers Problem:

wrt初始化为1,readcount初始化为0,mutex为1

写者操作: 

 


do{ 
    wait(wrt); 
    ... 
    //writing is performed  
    ... 
    signal(wrt); 
} while(TRUE); 

 

读者操作:


do{ 
    wait(mutex);//确保与signal(mutex)之间的操作不会被其他读者打断 
    readcount++; 
    if(readcount == 1) 
        wait(wrt); 
    signal(mutex); 
    ... 
    //reading is performed 
    ... 
    wait(mutex); 
    readcount--; 
    if(readcount == 0) 
        signal(wrt); 
    signal(mutex); 
} while(TRUE); 


三、The Dining-Philosophers Problem:

所有的chopstick[5]全部初始化为1


do{
    wait(chopstick[i]);
    wait(chopstick[(i+1)%5]);
    ...
    //eating 
    ...
    signal(chopstick[i]);
    signal(chopstick[(i+1)%5]);
    ...
    //thinking 
    ...
} while(TRUE);

但是这个解决方案的最大问题在于它会出现死锁。所以我认为应该增加一个信号量mutex,并初始化为1:


do{
    wait(mutex);
    wait(chopstick[i]);
    wait(chopstick[(i+1)%5]);
    signal(mutex);
    ...
    //eating   
    ...
    wait(mutex);
    signal(chopstick[i]);
    signal(chopstick[(i+1)%5]);
    signal(mutex);
    ...
    //thinking   
    ...
} while(TRUE);

这样由于确保了一位哲学家在拿起两只筷子的时间内其他哲学家不可以拿起任何一支筷子,从而破坏了死锁出现需要的四个特征中的Hold And Wait特征,从而避免了死锁的发生。

--------------------------------------------------------------------------------------------------------------------------------

转载于http://blog.csdn.net/zevin/article/details/8779009
  操作系统发展到今天已经十分精巧,线程就是其中一个杰作。操作系统把 CPU 处理时间划分成许多短暂时间片,在时间 T1 执行一个线程的指令,到时间 T2又执行下一线程的指令,各线程轮流执行,结果好象是所有线程在并肩前进。这样,编程时可以创建多个线程,在同一期间执行,各线程可以“并行”完成不同的任务。
在单线程方式下,计算机是一台严格意义上的冯·诺依曼式机器,一段代码调用另一段代码时,只能采用同步调用,必须等待这段代码执行完返回结果后,调用方才能继续往下执行。有了多线程的支持,可以采用异步调用,调用方和被调方可以属于两个不同的线程,调用方启动被调方线程后,不等对方返回结果就继续执行后续代码。被调方执行完毕后,通过某种手段通知调用方:结果已经出来,请酌情处理。
计算机中有些处理比较耗时。调用这种处理代码时,调用方如果站在那里苦苦等待,会严重影响程序性能。例如,某个程序启动后如果需要打开文件读出其中的数 据,再根据这些数据进行一系列初始化处理,程序主窗口将迟迟不能显示,让用户感到这个程序怎么等半天也不出来,太差劲了。借助异步调用可以把问题轻松化 解:把整个初始化处理放进一个单独线程,主线程启 动此线程后接着往下走,让主窗口瞬间显示出来。等用户盯着窗口犯呆时,初始化处理就在背后悄悄完成了。程序开始稳定运行以后,还可以继续使用这种技巧改善 人机交互的瞬时反应。用户点击鼠标时,所激发的操作如果较费时,再点击鼠标将不会立即反应,整个程序显得很沉重。借助异步调用处理费时的操作,让主线程随时恭候下一条消息,用户点击鼠标时感到轻松快捷,肯定会对软件产生好感。

From http://en.wikipedia.org/wiki/Thread_(computing)

In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by an operating system scheduler. A thread is a light-weight process. The implementation of threads and processes differs from one operating system to another, but in most cases, a thread is contained inside a process. Multiple threads can exist within the same process and share resources such as memory, while different processes do not share these resources. In particular, the threads of a process share the latter's instructions (its code) and its context (the values that its variables reference at any given moment).

On a single processor, multithreading generally occurs by time-division multiplexing (as inmultitasking): the processor switches between different threads. This context switching generally happens frequently enough that the user perceives the threads or tasks as running at the same time. On amultiprocessor or multi-core system, threads can be truly concurrent, with every processor or core executing a separate thread simultaneously.

Many modern operating systems directly support both time-sliced and multiprocessor threading with a process scheduler. The kernel of an operating system allows programmers to manipulate threads via thesystem call interface. Some implementations are called a kernel thread, whereas a lightweight process(LWP) is a specific type of kernel thread that shares the same state and information.


转载于http://blog.csdn.net/a_snail/article/details/1491790

同步

所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事.就像早上起床 后,先洗涮,然后才能吃饭,不能在洗涮没有完成时,就开始吃饭.按照这个定义,其实绝大多数函数都是同步调用(例如sin,isdigit等)。但是一般 而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是
SendMessage。该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回。当对方处理完毕以后,该函数才把消息处理函数所返回的
LRESULT值返回给调用者。

异步

异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
以CAsycSocket类为例(注意,CSocket从CAsyncSocket派生,但是起功能已经由异步转化为同步),当一个客户端通过调用
Connect函数发出一个连接请求后,调用者线程立刻可以朝下运行。当连接真正建立起来以后,socket底层会发送一个消息通知该对象。
这里
提到执行部件和调用者通过三种途径返回结果:状态、通知和回调。可以使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。


转载于http://blog.csdn.net/lizhiguo0532/article/details/6117818

进程并发运行的环境中,多个进程之间存在如下竞争和合作的关系:

-          进程中的资源争用(间接作用)

当并发进程竞争使用同一个资源时,它们之间就会发生冲突。为了避免冲突,当一个进程获得资源时,另一个进程必须等待。这种情况需要通过互斥机制来解决。

-          进程间通过共享的合作(间接作用)

一个进程等待另一个进程的执行,并以另一个进程的执行结果作为本进程的执行条件,就形成了同步机制

-          进程间通过通信的合作(直接作用)

进程间还可以通过通信进行合作,同性提供了同步和协调各种活动的方法。如操作系统提供的通信功能。

 

进程间通过共享的竞争:

特点:

1.       每个进程不知道其他进程的存在

2.       两个或者和更多的进程在各自的执行过程中需要访问相同的资源(IO设备、存储器、CPU)

3.       进程之间没有信息交互

相互间产生的影响:

       执行结果不会受影响

       执行时间会受影响

竞争引发的控制问题:

       互斥、死锁、饥饿

 

与并发相关的术语:

临界资源:一次只能允许一个进程访问的资源

临界区:访问和操作临界资源的代码段

互斥:多个进程需要访问一个临界资源时,任何时刻只能有一个进程正在访问;通俗点,资

源需要排它使用,防止出现竞争冲突(不同时使用,但无先后次序)

同步:指两个事件的发生存在着某种时序上的先后关系。

死锁:一组进程中,每个进程都无限等待改组进程中另一进程所占有的临界资源

饥饿:一组进程中,某个或者某些进程无限等待改组中其他进程所占有的临界资源

--------------------------------------------------------------------------------------------------------------------------------

作者:严肃
链接:https://www.zhihu.com/question/19732473/answer/20851256
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

“阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答。
1.同步与异步
同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)
所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。
换句话说,就是由*调用者*主动等待这个*调用*的结果。

而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

典型的异步编程模型比如Node.js

举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

2. 阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。


0 0
原创粉丝点击