Jarayonlar o’zaro bog’liqlik shabloni (paradigma): ishlab chiquvchi - iste’molchi Jarayonlarning o'zaro ta'sirini amalga oshirish dasturlashning o'nlab yillar davomida rivojlangan klassik paradigmalaridan (shablonlaridan) biriga asoslanishi mumkin. Ushbu bo’limda jarayonlarning o’zaro ta’sir paradigmalaridan eng ko’p tarqalganlaridan biri – ishlab chiquvchi – iste’molchi shabloni bilan tanishib chiqamiz. Ishlab chiquvchi-jarayon (producer) iste’molchi-jarayonlar (consumer) foydalanadigan ba’zi ma’lumotlar buferini yaratadi.
Ushbu paradigmani amalga oshirishda ikkita jarayonni bog’lash uchun cheklanmagan va cheklangan buferdan foydalanishi mumkin.
· Cheklanmagan bufer (unlimited buffer) sxemasida foydalaniladigan bufer o’lchamida nazariy jihatdan chegara yo’qligi taxmin qilinadi.
· Cheklangan bufer (bounded buffer) sxemasida esa aniq cheklangan bufer o’lchamidan foydalaniladi, masalan, BUFFER_SIZE konstantasidan.
Cheklangan buferli sxemani amalga oshirayotganda, ishonchli va xavfsiz hisoblash (trustworthy computing) tamoyillari nuqtai nazaridan buferning “to’lib ketishi” (buffer overrun) hujumi xavfini - xato yoki qasddan qilingan o'ta katta o'lchamni hisobga olish kerak. Ushbu zaiflikni oldini olish uchun buferni to'ldirishda bufer hajmini tekshirish kerak bo’ladi.
Cheklangan bufer sxemasini quyidagicha amalga oshiramiz. Ma’lumot massivda ikkita ko’rsatkich bilan saqlanadi: in - iste'molchi jarayoni tomonidan keyingi ma'lumotni o'qish va undan foydalanish uchun va out - ishlab chiquvchi jarayonning keyingi hosil bo'lgan ma'lumot elementini yozib olish uchun. Buferdan navbatdagi elementni o’qish vaqtida u o’chiriladi va in ko’rsatkichi mos ravishda siljiydi. Buferga yozish vaqtida out ko’rsatkichi siljiydi. Qulaylik uchun bufer tsikl bilan o’qiladi, ya’ni uni keyingi to’lidruvchi element bilan to’ldirayotganda nolga teng bo’ladi (agar u bo’shatilgan bo’lsa), undan keyin navbatdagi – birinchi va boshq. Shunday qilib, ishlab chiqaruvchi jarayoni buferga indeksni (out+1)%BUFFER_SIZE formulasidan foydalanib, keyingi yoziladigan elementni buferda hisoblashi kerak, bu yerda "%" bo’lish qoldig’ini olish amali. Xuddi shunday, iste’molchi-jarayon buferga keyingi elementning indeksini (in+1)%BUFFER_SIZE formulasi bo’yicha hisoblashi shart. Bunda ikkita mumkin bo’lgan vaziyat ham hisobga olinadi: buferning to’lib ketishi (ishlab chiqaruvchi bufer uzunligidan ko’p bo’lgan elementlarni yaratganda) va buferning tugashi (agar iste’molchi buferdan ayni vaqtda yaratilgan elementni olgan bo’lsa). Bufer chegarasidan chiqib ketmaslik uchun, bufer toshib ketganda, ishlab chiqaruvchi buferda kamida bitta element bo'shatilguncha kutishi va bufer tugaganda, iste'molchi kamida bitta yangi element paydo bo'lguncha kutishi kerak bo'ladi.
Buferni taqdim etish Si dasturlash tilida quyidagicha ko’rinishda bo’lishi mumkin:
#define BUFFER_SIZE 1000 /* yoki boshqa aniq qiymat ko’rsatilishi mumkin*/
typedef struct {
. . .
} item;
item buffer [BUFFER_SIZE];
int in = 0;
int out = 0;
Ishlab chiqaruvchi algoritmi sxemasi:
item nextProduced; /* keyingi yaratiladigan element */
while (1) { /* cheksiz tsikl */
while (((in + 1) % BUFFER_SIZE) == out)
; /* bufer to’lguncha kutish*/
buffer[in] = nextProduced; /* elementni yaratish */
in = (in + 1) % BUFFER_SIZE;
}
Mos ravishda iste’molchi-jarayonni amalga oshirish:
item nextConsumed; /* keyingi foydalaniladigan element */
while (1) { /* cheksiz tsikl */
while (in == out)
; /* bufer bo’shaguncha kutish*/
nextConsumed = buffer[out]; /* elementdan foydalanish */
out = (out + 1) % BUFFER_SIZE;
}
Ushbu kodlardan ixtiyoriy tizimda ishlab chiquvchi – iste’molchi sxemasini amalga oshirish uchun shablon (pattern) sifatida qo’llash mumkin.