Skip to content

2.15 信号量定义

Giovanna

About 949 wordsAbout 3 min

2024-08-31

一、整型信号量

最初由Dijkstra把整型信号量定义为一个整型量,除初始化外,仅能通过两个标准的原子操作(Atomic Operation)wait(S)和signal(S)来访问。这两个操作一直被分别称为P、V操作。wait和signal操作可描述为:

P(S): while(S<=0);
      S=S-1;

V(S): S=S+1;

面临的问题:只要是信号量S<=0,就会不断地测试。因此,该机制并未遵循"让权等待"的准则。

二、记录型信号量

  • 一个用于代表资源数目的整型变量value

  • 一个进程链表L,用于链接所有等待进程

typedef struct semaphore
{
    int value;
    List_of_Process L;
}
semaphore S;

P(S):

S.value=S.value-1;
if(S.value<0)
    block(S.L);

V(S):

S.value=S.value+1;
if(S.value<=0)
    wakeup(S.L);

S.value的初值表示系统中某类资源的数目,因而又称为资源信号量,对它的每次wait操作,意味着进程请求一个单位的该类资源,因此描述为S.value=S.value-1;。当S.value<0时,表示该类资源已分配完毕,因此进程应调用block原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。可见,该机制遵循了“让权等待”准则。此时S.value的绝对值表示在该信号量链表中已阻塞进程的数目。

对信号量的每次signal操作,表示执行进程释放一个单位资源,故S.value=S.value+1操作表示资源数目加1。若加1后仍是S.value<=0,则表示在该信号量链表中,仍有等待该资源的进程被阻塞,故还应调用wakeup原语,将S.L链表中的第一个等待进程唤醒。 如果S.value的初值为1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量

三、AND信号量

AND同步机制的基本思想是:将进程在整个运行过程中需要的所有资源,一次性全部地分配给进程,待进程使用完后再一起释放。只要尚有一个资源未能分配给进程,其它所有可能为之分配的资源,也不分配给他。亦即,对若干个临界资源的分配,采取原子操作方式:要么全部分配到进程,要么一个也不分配。

信号量集

  • 思考:记录型信号量有何不便之处?

    • 当一次需要多个资源时,需要进行多次P操作
    • 同理,要进行多次释放V操作
  • 如何改进:

// t为下限值,d为需求值

Swait(S[1],t[1],d[1],...,S[n],t[n],d[n])
    if(S[1]>=t[1] and ... and S[n]>=t[n])
        for(i=1;i<=n;i++)
            S[i]=S[i]-d[i];
    else
        Place the executing process in the waiting queue ofthe first S[i] with S[i]<t[i] and set its program counter to the beginning of the Swait Operation.

signal(S[1],d[1],...,S[n],d[n])
    for
    {
        S[i]=S[i]+d[i];
        Remove all the process waiting in the queue associated with S[i] into the ready queue.
    }

一般“信号量集”的几种特殊情况

  1. Swait(S, d, d):此时在信号量集中只有一个信号量S,但允许它每次申请d个资源,当现有资源数少于d时,不予分配。

  2. Swait(S, 1, 1):此时的信号量集已退化为一般的记录型信号量(S>1时)或互斥信号量(S=1时)。

  3. Swait(S, 1, 0):这是一种很特殊且很有用的信号量操作。当S≥1时,允许多个进程进入某特定区;当S变为0后,将阻止任何进程进入特定区。换言之,它相当于一个可控开关。