展示如何仅使用二进制信号量和普通机器指令来实现计数信号量?

时间:2013-02-27 16:27:15

标签: operating-system semaphore

我正在学习期中考试,这是一个练习题:展示如何使用二进制信号量和普通机器指令来实现计数信号量(即可以保持任意值的信号量)?

我甚至不确定从哪里开始。我在网上找到了这个;

P(s) { Pb(mutex_s); s = s-1; if(s < 0) {Vb(mutex_s); Pb(delay_s);} Vb(mutex_s); }
V(s) { Pb(mutex_s); s = s+1; if(s <= 0) Vb(delay_s); else Vb(mutex_s); }

不幸的是,我真的不明白答案告诉我的是什么。任何人都可以向我解释这个答案,或者用伪代码告诉我如何回答?

5 个答案:

答案 0 :(得分:5)

我在Prahbat's回答中建立了以下直觉:

我们想要复制的内容:

  • 计算信号量意味着最多允许N个线程访问资源

我们可以使用二进制信号量来做到这一点:

  • 如果其关键部分中已有N个进程,则计数信号量会锁定对线程关键部分的访问
    • =&GT;我们需要一个二进制信号量 sectionLock 来告诉等待线程他们是否可以访问他们的关键部分( sectionLock = 1 )或者他们不能( sectionLock = 0
  • 我们必须跟踪在其关键部分中访问资源的线程数。设这个计数器是一个整数 count
    • count 在进入临界区的线程上递减(即该资源中的一个线程减少一个点),并在退出临界区的线程上递增(即为该资源中的一个线程释放一个点)< / LI>
    • =&GT; count 是一个共享资源,一次只能由一个线程访问
    • =&GT;我们需要一个二进制信号量 countLock ,用于 count
  • 如果 count&lt; = 0 ,那么我们就不能允许任何线程进入关键部分,并且必须等待 sectionLock 由现有线程释放

因此,以下伪代码表明了自己

P_counting( int count )
   P( countLock )        // Acquire lock to count: countLock <- 0
   count--
   if( count <= 0 )      // If no more threads allowed into critical section
      P( sectionLock )   // Resource full => Acquire section lock: sectionLock <- 0
      V( countLock )     // Release lock to count: countLock <- 1
   else
      V( countLock)

V_counting( int count )
   P( countLock )
   count++
   if( count > 0)        // Release sectionLock if resource is freed up
      V(sectionLock)     // countLock released after sectionLock so that waiting
      V(countLock)       // threads do not jump in when before resource is available
   else
      V(countLock)

如果我出错了,请告诉我。

答案 1 :(得分:2)

  

设x,y为二进制信号量。我们将通过它实现计数信号量S.P代表等待操作,V代表信号。   由于我们采用S = 4,因此只有4个过程可以进入关键部分。

S = 4, x = 1, y = 0;

/*---P(S)---*/
{P(x);S--;if(s<=0){V(x);P(y);}else V(x); }

/*--CRITICAL SECTION--*/

/*--V(S) ---*/
  { P(x); S++;IF(S>0){ V(y);V(x); }else V(x);} 
  

注意:P(x)将x的值减小1,而V(x)增加1,y的值相同。 y被称为悬挂信号量,因为P(y)表示所有这些    如果S&lt;队列中的进程0.

答案 2 :(得分:2)

CSem(K) cs { // counting semaphore initialized to K
    int val ← K; // the value of csem
    BSem gate(min(1,val)); // 1 if val > 0; 0 if val = 0
    BSem mutex(1); // protects val

    Pc(cs) {
        P(gate)
        a1: P(mutex);
        val ← val − 1;
        if val > 0
        V(gate);
        V(mutex);
    }

    Vc(cs) {
        P(mutex);
        val ← val + 1;
        if val = 1
        V(gate);
        V(mutex);
    }
}

来源:http://www.cs.umd.edu/~shankar/412-Notes/10x-countingSemUsingBinarySem.pdf

答案 3 :(得分:0)

想出来:

int s = N;
semaphore mutex_s = 1;
semaphore delay_s = 0;

p(s) = down
  down(mutex_x);
  s--;

  if (s< n)
    up(mutex_s)
    down(delay_s)
  up(mutex_s)

V(s) = up
  down(mutex_s)
  s++
  if (s<=0)
    up(delay_s)
  up(mutex_s)

答案 4 :(得分:0)

我有一个类似的问题,我认为会有相同的答案,即“如何使用互斥锁实现计数信号量”。

请注意,二进制信号量可以被认为是互斥量。实际上,在不提供互斥锁的系统上,可以使用二进制信号量来提供互斥。

Mutex counting_mutex;    // used for accessing the shared variable count
Integer count = n;       // number of resource instances
Mutex mutex;             // the counting semaphore as mutex/binary semaphore
List waiting_list = [];  // list of waiting processes

/* ... */

// Entry Section
acquire(counting_mutex);
count--;
release(counting_mutex);

if (count < 0)
    add this process to waiting_list and have it sleep()

acquire(mutex);
/* ... Critical Section ... */
release(mutex);

// Exit Section
acquire(counting_mutex);
count++;
release(counting_mutex);

if (count <= 0)
    pull a process from waiting_list and call wakeup()