码迷,mamicode.com
首页 > 其他好文 > 详细

[Modern OS] InterProcess Communication[1]

时间:2019-09-09 22:56:14      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:condition   processes   ant   action   ==   similar   ace   mic   防止   

InterProcess Communication


2.3.1 Race Conditions

2.3.2 Critical Regions

避免 race condition 的关键是防止多个进程同时读写共享资源。

换句话说,需要一个互斥锁mutual exclusion

对共享资源进行访问的部分程序被称为临界区critical section

2.3.3 Mutual Exclusion with Busy Waiting

Disabling Interrupts

缺点:

  1. 给用户进程关闭中断的权限是不明智的;
  2. 如果系统是多处理器系统,那么关闭中断只会影响执行了disable指令的CPU,运行在其他CPU上的进程依然可以访问共享内存。

Disabling interrupts is often a useful technique within the operating system itself but is not appropriate as a general mutual exclusion mechanism for user processes.

Lock Variables

Strict Alternation

Continuous testing a variable until some value appears is called busy waiting. A lock that uses busy waiting is called a spin lock.

缺点:

  1. 持续检测变量浪费CPU
  2. 要求严格有序,否则效率低下

Peterson‘s Solution

#define FALSE 0
#define TRUE 1
#define N 2 /* number of processes */

int turn; /* whose turn is it? */
int interested[N]; /* all values initially 0 (FALSE) */

void enter region(int process) /* process is 0 or 1 */
{
    int other; /* number of the other process */
    other = 1 ?process; /* the opposite of process */   
    interested[process] = TRUE; /* show that you are interested */
    turn =process; /* set flag */
    while (turn == process && interested[other] == TRUE) /* null statement */ ;
}

void leave region(int process) /* process: who is leaving */
{
    interested[process] = FALSE; /* indicate departure from critical region */
}

起初没有进程进入临界区。
进程 0 调用enter_region。它在interested数组中的对应元素被设置为 1,然后ture为 0。由于进程 1 还没有调用过enter_region,所以enter_region会立刻返回,进程 0 进入临界区。如果此时进程 1 调用了enter_region,那么在interested[0]变为FALSE之前,它都会等待。

如果两个进程几乎同时调用了enter_region。那么turn将会是后一个完成赋值操作的进程的号码。假设此时turn为 1。两个进程同时到达while语句,进程 0 将会直接退出,然后进入临界区。进程 1 将会等待,直到进程 0 从临界区退出。

本质上也是一个busy waiting

The TSL Instruction

TSL Test and Set Lock

2.3.4 Sleep and Wakeup

上述方法都需要busy waiting。实际上,本质都是:当有进程需要进入临界区时,首先检查是否能够进入,如果不能进入,那么就会执行一个循环一直进行检测,直到能够进入临界区。

busy waiting不光消耗CPU时间,同时还会有一些bug。比如当发生优先级反转时,已经进入临界区的进程无法释放 lock,导致高优先级的进程永远无法进入临界区。

The Producer-Consumer Problem

也叫做有限缓冲区问题( bounded-buffer problem)。

两个进程共享一个公共的、固定大小的缓冲区。其中一个,生产者,将信息放入buffer,另一个,消费者,从buffer中取出消息。

Trouble arises when the producer wants to put a new item in the buffer, but it is already full. The solution is for the producer to go to sleep, to be awakened when the consumer has removed one or more items. Similarly, if the consumer wants to remove an item from the buffer and sees that the buffer is empty, it goes to sleep until the producer puts something in the buffer and wakes it up.

为了追踪缓冲区中物体的数量,我们需要一个变量count

#define N 100 /* number of slots in the buffer */
int count = 0; /* number of items in the buffer */
void producer(void)
{
    int item;
    while (TRUE) { /* repeat forever */
        item = produce item( ); /* generate next item */
        if (count == N) sleep( ); /* if buffer is full, go to sleep */
        inser t item(item); /* put item in buffer */
        count = count + 1; /* increment count of items in buffer */
        if (count == 1) wakeup(consumer); /* was buffer empty? */
    }
}

void consumer(void)
{
    int item;

    while (TRUE) { /* repeat forever */
        if (count == 0) sleep( ); /* if buffer is empty, got to sleep */
        item = remove item( ); /* take item out of buffer */
    count = count ?1; /* decrement count of items in buffer */
    if (count == N ? 1) wakeup(producer); /* was buffer full? */
    consume item(item); /* pr int item */
    }
}

然而对count的访问可能会出问题。当对count的访问不做限制时,就会出现rece condition。缓冲区已经空了,消费者读入count来测试它是否为0。在此时,调度器决定将消费者暂停,然后执行生产者。生产者增加了buffer中物体的数量,增加了count,ok那么现在count应该为1。根据生产者的代码,消费者此时会给消费者发出一个wakeup的消息,然而事实上,由于消费者之前被暂停,所以此时它在逻辑上并没有sleep,所以这个消息将会丢失。

当消费者再次执行时,它根据自己之前读到的count==0,将自己转入sleep。不久之后缓冲区满,生产者也进入sleep,这时,消费者和生产者两者都将永远sleep。

这个问题的本质是:wakeup消息被发送给了一个还没有真正sleep的进程。

2.3.5 Semaphores

1965年,Dijkstra提出使用信号量Semaphore。Semaphore是一个整数变量,当它为0时,表示没有保存任何wakeup信号,当它为其他正整数时,表示一个或者多个wakeup were pending。

Dijkstra提出了两个对信号量的操作,down 和 up。对一个信号量的 down 操作检查信号量的值是否为 0,如果不是 0,那么就减 1。如果是 0,那么进程就会sleep,而且暂时不会将 down 操作执行完。检查值的大小、改变值的大小、以及可能的go to sleep,这些行为都是单个的不可分的 原子操作(atomic action)。一旦对信号量的操作被进行,那么所有其他进程都无法访问该信号量,直到操作完成或者该进程阻塞。

up 操作将信号量的值增加1。如果有多个进程sleeping on that semaphore, unable to complete an earlier down operation, 那么系统将会随机选择一个进程完成它的 down operation。Thus, after an up on a semaphore with processes sleeping on it, the semaphore will still be 0, but there will be one fewer process sleeping on it.

Solving the Producer-Consumer Problem Using Semaphores

信号量的作用是为了解决前文提出的wakeup信号丢失的问题(lost-wakeup)。

#define N 100 /* number of slots in the buffer */
typedef int semaphore; /* semaphores are a special kind of int */
semaphore mutex = 1; /* controls access to critical region */
semaphore empty = N; /* counts empty buffer slots */
semaphore full = 0; /* counts full buffer slots */
void producer(void)
{
    int item;
    while (TRUE) { /* TRUE is the constant 1 */
        item = produce item( ); /* generate something to put in buffer */
        down(&empty); /* decrement empty count */
        down(&mutex); /* enter critical region */
        inser t item(item); /* put new item in buffer */
        up(&mutex); /* leave critical region */
        up(&full); /* increment count of full slots */
    }
}

void consumer(void)
{
    int item;
    while (TRUE) { /* infinite loop */
        down(&full); /* decrement full count */
        down(&mutex); /* enter critical region */
        item = remove item( ); /* take item from buffer */
        up(&mutex); /* leave critical region */
        up(&empty); /* increment count of empty slots */
        consume item(item); /* do something with the item */
    }
}

This solution uses three semaphores: one called full for counting the number of slots that are full, one called empty for counting the number of slots that are empty, and one called mutex to make sure the producer and consumer do not access the buffer at the same time.

初始值为 1 并且被多个进程使用的信号量,保证了同时只有一个进程可以进入临界区,这种信号量被称为二值信号量(binary semaphores)。

[Modern OS] InterProcess Communication[1]

标签:condition   processes   ant   action   ==   similar   ace   mic   防止   

原文地址:https://www.cnblogs.com/hezhiqiangTS/p/11494590.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!