Operating System: Semaphore

The main reference herein "computer operating system (fourth edition)" (Xi'an University of Electronic Science and Technology Publishing House) and Tsinghua operating system open class (to Yong, Yu Chen), finishing the basic concepts of the operating system for their own review inspection.

Semaphore mechanism

Process control is the most important part is to coordinate the process of concurrency, synchronization control process, the most concrete manifestation of the critical processing resources. Semaphore mechanism will be widely used in critical resource processing.

Classification and development of the semaphore

Semaphore original definition is a resource number .

Integer semaphore

As the name implies, the amount of such signal is represented by a number of critical resource amount by an integer s. At initialization, the initialization of the s number of resources, and limit the operation only by atomic the wait (s) and the Signal (s) to access, these two operations are also commonly referred to as P , V operation. Code can be expressed as follows:

wait(s) {
    while(s <= 0);
    --s;
}

signal(s) {
    ++s;
}

Recording semaphore

It can be seen in the integer semaphore, as long as resources are not eligible, will continue to debug, does not meet the "Let's wait for the right" principle (that is, let the process is in a "busy wait" state), and you can record Semaphore solve this problem.

In the recording semaphore, a simple extension of the integer s is saved as a table pointer recording process type structure, which additionally, to link all the waiting process.

struct ProcessControlBlock;

using PCB = ProcessControlBlock;
struct Semaphore {
    int value; // 资源数目
    PCB* processList;
};

wait(Semaphore *s) {
    if(--s->value < 0) {
        // 资源已被分配给其他进程,当前进程自我阻塞
        // 并把其插入等待队列
        block(s->processList);
    }
}

signal(Semaphore *s) {
    if(++s->value <= 0) {
        // 条件为真说明有进程在等待队列中,唤醒队列的第一个进程
        wakeup(s->processList);
    }
}

It can be seen in the application process will be less resources for self-blocking, so that also in line with the principle of the right to wait. Special, in the initial amount of resources for the moment will be transformed into mutex.

AND Semaphore

Mutual exclusion only share a critical resource situation for multiple processes. In some cases, a process required to obtain more than one task can be performed after the shared resource. In this case the process is prone to deadlock . Such as: If two processes need to apply critical resources consistent with the order but inconsistent and alternate application, then they are not all the required critical resources, namely deadlock.

To address this issue, AND Semaphore solution is: the process throughout the run required all one-time allocation of all resources to the process, to be released together and then finished using the process.

Swait(s1, s2, ..., sn) {
    while(true) {
        if(s1 >= 1 && s2 >= 1 && ... && sn >= 1) {
            --s1; --s2; ...; --sn;
            break;
        } else {
            wait();
        }
    }
}

Ssignal(s1, s2, ..., sn) {
    while(true) {
        ++s1; ++s2; ...; ++sn;
    }
}

Semaphore set

Since P, V operation amount plus only a signal and a subtraction operation, when the primary unit requires n is clearly inefficient, but more likely to cause dispensing unit by a deadlock. For system security, in some cases we need to control the resources, that is not allocated specifically when the requested number of resources below the lower limit t d corresponding.

To address this problem, the solution semaphore set: the need to know the process of demand and the lower limit of the resource during the corresponding resource P, V operation, and thus determines the allocation of resources.

Swait(s1, t1, d1, ..., sn, tn, dn);
Ssignal(s1, d1, ..., sn, dn);

Three special amount signal set:

  1. Swait(s, 0, 0): Semaphore semaphore only one focus, and the lower limit value of the number of applications and allow the same;
  2. Swait(s, 1, 1): This signal sets the amount of degradation of the recording semaphore;
  3. Swait(s, 1, 0): When s> 0, allows multiple processes to enter a particular area, becomes 0 when s blocking area, acts like a switch.

Semaphore application

Achieve mutual exclusion

To achieve mutually exclusive access to a resource, the resource is provided only a mutex semaphore for mutex and set the initial value of 1, combined with P, V can operate.

Semaphore mutex = 1;

// a进程P资源
Pa() {
    while(true) {
        wait(mutex);
        // 临界区
        signal(mutex);
        // 剩余区
    }
}

Achieve predecessor relationship

Predecessor graph is increasingly describing the relationship between the former process directed acyclic graph .

Use semaphores can be described as the process of becoming relations between the former. There predecessor graph below:

M08tun.png

Then the following code can be described in the framework of this relationship:

Semaphore a, b, c, d, e, f, g;

p1() { s1; signal(a); signal(b); }
p2() { wait(a); s2; signal(c); signal(d); }
p3() { wait(b); s3; signal(e); }
p4() { wait(c); s4; signal(f); }
p5() { wait(d); s5; signal(g); }
p6() { wait(e); wait(f); wait(g); s6; }

main() {
    a.value = b.value = c.value = d.value = 0;
    e.value = f.value = g.value = 0;
    cobegin
        p1(); p2(); p3(); p4(); p5(); p6();
    coend
}

Classical synchronization problems

Producer - consumer issues

A group of producers in the production process of products, processes and products available to consumers consumption. In order to producers and consumers can execute concurrently, disposed therebetween having a buffer pool buffer n. This also implies two constraints: the consumer can not take the product to an empty buffer; producers can not deliver the product to a full buffer.

Using the recording semaphore can solve this problem. Here two signals need to set the amount of: emptyand fullshowing two critical state buffer use the code as follows:

int in = 0, out = 0;
Product pool[n]; // 环形缓冲池
Semaphore mutex = 1, empty = n, full = 0;

void Producer() {
    while(true) {
        Produce(); // 生产产品
        wait(empty); // 需要一个空的缓冲区容纳新产品
        wait(mutex); // 请求锁
        pool[in] = nextp; // 存放新产品
        in = (in + 1) % n; // 偏移指针指向下一个可存放区域
        signal(mutex); // 释放锁
        signal(full); // 增加一个满缓冲区
    }
}

void Consumer() {
    while(true) {
        wait(full); // 需要一个满缓冲区来取其中的产品
        wait(mutex); // 请求锁
        nextc = pool[out]; // 取出产品
        out = (out + 1) % n; // 偏移指针指向下一个可取出区域
        signal(mutex); // 释放锁
        signal(empty); // 增加一个空缓冲区
        Consume(); // 消费取出的产品
    }
}

void main() {
    cobegin
        Producer();
        Consumer();
    coend
}

It should be noted that the application for mutual exclusion semaphores must occur after the filing of the semaphore resources, or it may cause a deadlock. Obviously, this problem can also be used AND Semaphore resolved.

int in = 0, out = 0;
Product pool[n];
Semaphore mutex = 1, empty = n, full = 0;

void Producer() {
    while(true) {
        Produce();
        Swait(empty, mutex); // 要同时申请到空缓冲区和互斥信号量
        pool[in] = nextp;
        in = (in + 1) % n;
        Ssignal(mutex, full); // 同时释放满缓冲区和互斥信号量
    }
}

void Consumer() {
    while(true) {
        Swait(full, mutex);
        nextc = pool[out];
        out = (out + 1) % n;
        Ssignal(mutex, empty);
        Consumer();
    }
}

Dining Philosophers

There are five philosophers share a round table, the table stood five bowl and five chopsticks, philosopher only do two things: thinking, meal. A philosopher always thinking, hunger can only take two chopsticks closest to him, in order to get the meal. Continue to think before the end of the meal.

Using the recording semaphore can solve this problem.

Semaphore chopstick[5] = {1, 1, 1, 1, 1};

while(true) {
    Think();
    wait(chopstick[i]);
    wait(chopstick[(i + 1) % 5]);
    Eat();
    signal(chopstick[i]);
    signal(chopstick[(i + 1) % 5]);
}

But above approach will have a question: If the five philosophers are hungry, they will first get their own chopsticks left hand side, causing a deadlock. Some rules could be developed to solve the deadlock. And with AND semaphore is not considered deadlock.

Semaphore chopstick[5] = {1, 1, 1, 1, 1};

while(true) {
    Think();
    Swait(chopstick[i], chopstick[(i + 1) % 5]);
    Eat();
    Ssignal(chopstick[i], chopstick[(i + 1) % 5]);
}

Readers - writers problem

A data file that can be shared by multiple processes, but do read the file operation called Reader process, other processes called Writer process. Reading process can read multiple files at once, but the process has write access to the file, other processes (either a read process or write process) can not access the file. This problem often used to test new synchronization primitives.

Using the recording semaphore can solve this problem.

Semaphore rMutex = 1, wMutex = 1;
int readerCount = 0;

void Reader() {
    while(true) {
        wait(rMutex); // 申请读锁
        if(readerCount == 0) wait(wRmutex); // 如果当前没有读者,那就需要锁写入
        ++readerCount;
        signal(rMutex); // 由于读取可以同时进行,所以现在就释放读锁
        Read();
        wait(rMutex);
        --readerCount;
        if(readerCount == 0) signal(wMutex); // 没有读者才释放写锁
        signal(rMutex);
    }
}

void Writer() {
    while(true) {
        wait(wMutex);
        Write();
        signal(wMutex);
    }
}

void main() {
    cobegin
        Reader();
        Writer();
    coend
}

If the file can be accessed RN requires up to a reading process, then use semaphore sets to solve the problem is more convenient.

int RN;
Semaphore L = RN, mutex = 1;

void Reader() {
    while(true) {
        Swait(L, 1, 1);
        Swait(mutex, 1, 0);
        Read();
        Ssignal(L, 1);
    }
}

void Writer() {
    while(true) {
        Swait(mutex, 1, 1,  L, RN, 0);
        Write();
        Ssignal(mutex, 1);
    }
}

void main() {
    cobegin
        Reader();
        Writer();
    coend
}

Guess you like

Origin www.cnblogs.com/Li-F/p/11876214.html