一、信號量的定義:linux
struct semaphore { spinlock_t lock; unsigned int count; struct list_head wait_list; };
在linux中,信號量用上述結構體表示,咱們能夠經過該結構體定義一個信號量。數組
二、信號量的初始化:併發
可用void sema_init(struct semaphore *sem, int val);直接建立,其中val爲信號量初值。也能夠用兩個宏來定義和初始化信號量的值爲1或0:函數
DECLARE_MUTEX(name) : 定義信號量name並初始化爲1 DECLARE_MUTEX_LOCKED(name) : 定義信號量name並初始化爲0
還能夠用下面的函數初始化:code
void init_MUTEX(struct semaphore *sem); //初始化信號量的值爲1 void init_MUTEX_LOCKED(struct semaphore *sem); //初始化信號量的值爲0
三、信號量的原子操做:隊列
p操做:進程
v操做:ci
四、經典同步問題的解決方案:資源
a、單緩衝區問題描述:生產者向消費者提供產品,它們共享一個有界緩衝區,生產者向其中投放產品,消費者從中取得產品。同時,每一個進程都互斥的佔用CPU。假定生產者和消費者是互相等效的,只要緩衝區未滿,生產者就能夠把產品送入緩衝區,相似的,只要緩衝區未空,消費者即可以從緩衝區中取走產品並消費它。生產者—消費者的同步關係將禁止生產者向已滿的緩衝區中放入產品,也禁止消費者從空的緩衝區中獲取產品get
問題分析: 須要定義兩個信號量,一個用於互斥訪問緩衝區,另外一個用於生產者與消費者之間的同步。s1=1; s2=0;
僞代碼:
生產者進程 while(1) { printf(「I'm producing!\n」); down_interruptible(&s1); printf(「I'm putting a product into the buffer\n」); up(&s1); up(&s2); }
消費者進程
while(1) { down_interruptible(&s2); down_interruptible(&s1); printf(「I'm getting a product\n」); up(&s1); printf(「I'm consuming a product\n」); }
b、多生產者、多消費者、n個緩衝區
問題描述:有一羣生產者進程在生產產品,並將這些產品提供給消費者進程去消費。爲使生產者進程與消費者進程併發執行,在二者之間設置了n個緩衝區,生產者將產品放入一個緩衝區中,消費者能夠從一個緩衝區中取走產品去消費。要求生產者進程與消費者進程必須保持同步,即不容許生產者進程向一個滿的緩衝區放產品,也不容許消費者從一個空的緩衝區取產品。
問題分析:該問題貌似比a問題複雜的多,首先咱們定義一個數組buffer[n],來表示n個緩衝區,還須要定義兩個變量:in 表示要存入的緩衝區的下標,out表示要取產品的緩衝區的下標。定義三個信號量:s1用於實現對緩衝池的互斥操做,empty表示空緩衝區的個數,full表示滿緩衝區的個數。初值:in=out=0; s1=1; full=0; empty=n;
僞代碼以下:
生產者進程 while(1) { printf(「I'm producing!\n」); down_interruptible(&empty); down_interruptible(&s1); printf(「I'm putting a product into the buffer[in]\n」); in = (in+1)%n; up(&s1); up(&full); }
消費者進程
哲學家進餐問題
while(1) { down_interruptible(&full); down_interruptible(&s1); printf(「I'm getting a product from buffer[out]\n」); out = (out+1)%n; up(&empty); printf(「I'm consuming a product\n」); }
問題描述:五個哲學家共用一個圓桌,分別坐在周圍的五張椅子上,在圓桌上有五隻碗和五隻筷子,他們交替進行思考和進餐。哲學家飢餓時便試圖取最靠近他的兩隻筷子,當同時得到兩隻筷子時即可用餐,用餐完畢後放下筷子。
問題分析: 五隻筷子爲臨界資源,定義包含五個元素的信號量數組來實現對筷子的互斥使用。chopstick[5],五個信號量的初值都爲1。
僞代碼:
第i(i=0,1,2,3,4)個哲學家進程:
while(1) { down_interruptible(&chopstick[i]); down_interruptible(&chopstick[(i+1)%5]); printf(「I'm eating!\n」); up(&chopstick[i]); up(&chopstick[(i+1)%5); }
問題描述:一個文件可被多個進程共享,reader進程讀取該文件,而writer進程負責寫文件,容許多個reader進程同時讀取文件,但不容許一個writer進程和其餘reader進程或writer進程同時訪問文件。
問題分析:進程對文件互斥訪問的實現可藉助一個信號量就能夠搞定,可是咱們須要引入一個count變量來記錄reader進程的個數,對這個變量的訪問也是互斥的,因此也須要引入一個信號量。定義信號量rs實現對count的互斥訪問,定義ws實現對文件的互斥訪問。兩信號量初值都爲1
僞代碼:
reader進程 { down_interruptible(&rs); count++; up(&rs); printf(「I'm reading!\n」); down_interruptible(&rs); count--; if(count == 0){ up(&ws); } up(&rs); } writer進程 { down_interruptible(&ws); if (count == 0){ printf(「I'm writing!\n」); down_interruptible(&ws); } up(&ws); }