|
Tizimli dasturlash
|
bet | 38/64 | Sana | 13.05.2024 | Hajmi | 183,36 Kb. | | #230077 |
Bog'liq Системное программирование, практикаNazorat savollari:
Ko'p vazifa nima va u nima uchun kerak?
Ilova yaratishda ko'p vazifalilik muammosini qanday hal qilish mumkin?
qanday amalga oshiriladi?
Tavsiya etilgan o'qish: 1.3.
10-son LABORATORIYA ISHI
Mavzu: Mavzularni sinxronlashtirish uchun yadro obyektlaridan foydalanish
Ishning maqsadi : iplarni sinxronlashtiradigan ilovalarni yaratish ko'nikmalarini rivojlantirish.
Ishlash vaqti 4 soat
Nazariy material
WaitForMultipleObjects funksiyasi ipni kutish holatiga qo'yadi va sinxronizatsiyani tashkil qilish uchun maxsus mo'ljallangan.
DWORD WaitForMultipleObjects(
DWORD nCount, // raqam ob'ektlar V lpHandles massivi
CONST TUTAQ *lpHandles, // yadro obyekti deskriptorlari massiviga ko'rsatgich
BOOL bWaitAll, // barcha ob'ektlarni kutish kerakmi yoki bittasi kifoya qiladimi yoki yo'qligini ko'rsatadigan bayroq
DWORD dwMillisoniyalar // taym-aut; turib qolish; tanaffus
);
Ushbu funktsiyaning asosiy parametri yadro ob'ekti tutqichlari massiviga ko'rsatgichdir. Quyida ushbu ob'ektlar nima ekanligi haqida gaplashamiz. Hozircha biz uchun bu ob'ektlarning har biri ikkita holatdan birida bo'lishi mumkinligini bilish muhimdir: neytral yoki "signal" (signalli holat). Agar bWaitAll bayrog'i FALSE bo'lsa, ob'ektlardan kamida bittasi signal berishi bilan funksiya boshqaruvni qaytaradi. Va agar bayroq TRUE bo'lsa, bu barcha ob'ektlar bir vaqtning o'zida signal berishni boshlaganda sodir bo'ladi (ko'rib turganimizdek, bu funktsiyaning eng muhim xususiyatidir). Birinchi holda, qaytish qiymati bo'yicha siz ob'ektlardan qaysi biri signal yuborganligini bilib olishingiz mumkin. Undan doimiyni ayirishimiz kerak WAIT_OBJECT_0 va bu lpHandles massivida indeksga olib keladi. Agar kutish vaqti oxirgi parametrda ko'rsatilgan vaqtdan oshsa, funktsiya kutishni to'xtatadi va qiymatni qaytaradi WAIT_TIMEOUT . Vaqt tugashi sifatida doimiyni belgilashingiz mumkin INFINITE , so'ngra funktsiya "butun yo'lda" kutadi yoki aksincha, 0, keyin esa ip umuman to'xtatilmaydi. Ikkinchi holda, funktsiya darhol boshqaruvni qaytaradi, ammo uning natijasi bo'yicha ob'ektlarning holatini bilish mumkin bo'ladi. Oxirgi texnika juda tez-tez ishlatiladi. Ko'rib turganingizdek, bu funktsiya boy imkoniyatlarga ega. Yana bir nechtasi bor XXX kuting funktsiyalar, lekin ularning barchasi asosiy mavzudagi o'zgarishlardir. Ayniqsa, WaitForSingleObject - bu shunchaki soddalashtirilgan versiyasi. Qolganlarning har biri o'ziga xos qo'shimcha funktsiyalarga ega, lekin odatda kamroq ishlatiladi. Masalan, ular nafaqat yadro obyektlarining signallariga, balki ip navbatiga yangi oyna xabarlarining kelishiga ham javob berish imkonini beradi. Ularning tavsifi, shuningdek, haqida batafsil ma'lumot WaitForMultipleObjects , siz odatdagidek MSDN-da topasiz.
Keling, bu sirli "yadro ob'ektlari" nima ekanligi haqida gapiraylik. Keling, bularga iplar va jarayonlarning o'zlari kiradi, deb boshlaylik. Ular tugagandan so'ng darhol signal holatiga o'tadilar. Bu juda muhim xususiyat, chunki ko'pincha ip yoki jarayon tugashini kuzatish kerak bo'ladi. Masalan, ishchi iplar to'plamiga ega bo'lgan server dasturimiz tugatilishi kerak. Bunday holda, boshqaruv chizig'i qandaydir tarzda ishchi iplarni ishni tugatish vaqti kelganligi to'g'risida xabardor qilishi kerak (masalan, global bayroqni o'rnatish orqali) va keyin to'g'ri bajarish uchun barcha kerakli harakatlarni bajarib, barcha oqimlar tugaguncha kutib turing: resurslarni bo'shatish. , mijozlarni o'chirish, tarmoq ulanishlarini yopish va hokazolar haqida xabardor qilish.
Ishni tugatgandan so'ng, iplar signalni yoqishi, ipni tugatish bilan sinxronizatsiya muammosini hal qilishni juda osonlashtiradi:
// Oddiylik uchun faqat bitta ishchi ipga ega bo'laylik. Keling, ishga tushamiz uning :
HANDLE hWorkerThread = ::CreateThread( ... );
...
...
// Ishni yakunlashdan oldin, biz qandaydir tarzda ishchi mavzuni yuklab olish vaqti kelganligi haqida xabar berishimiz kerak.
// kutamiz yakunlash oqim :
DWORD dwWaitResult = ::WaitForSingleObject( hWorkerThread, CHEKSIZ );
agar( dwWaitResult != WAIT_OBJECT_0 ) { /* davolash xatolar */ }
// Ipning " dastasi " mumkin yopish :
TASHIRISH( ::CloseHandle( hWorkerThread );
/* Agar CloseHandle bajarilmasa va FALSE qiymatini qaytarsa, men istisno qilmayman. Birinchidan, agar bu tizim xatosi tufayli sodir bo'lgan bo'lsa ham, bu bizning dasturimiz uchun to'g'ridan-to'g'ri oqibatlarga olib kelmaydi, chunki biz tutqichni yopganimiz sababli, u bilan boshqa ish kutilmaydi. Aslida, CloseHandle ishlamay qolishi faqat dasturingizdagi xatolikni anglatishi mumkin. Shuning uchun, dasturni disk raskadrovka bosqichida o'tkazib yubormaslik uchun biz VERIFY makrosini bu erga joylashtiramiz. */
Jarayon tugashini kutayotgan kod o'xshash ko'rinadi.
Agar tizimda bunday xususiyat mavjud bo'lmasa, ishchi ipning o'zi qandaydir tarzda uning tugallanganligi haqidagi ma'lumotni asosiy ipga uzatishi kerak edi. Agar u buni oxirgi narsa sifatida bajargan bo'lsa ham, asosiy mavzu ishchida kamida bir nechta montaj ko'rsatmalari qolmaganligiga ishonch hosil qila olmaydi. Muayyan holatlarda (masalan, agar ipning kodi DLL-da bo'lsa, u tugashi bilan uni olib tashlash kerak), bu halokatli oqibatlarga olib kelishi mumkin.
Ip (yoki jarayon) tugatilgandan keyin ham, uning tutqichlari funktsiya tomonidan aniq yopilmaguncha o'z kuchida qoladi. CloseHandle . (Aytgancha, buni qilishni unutmang!) Bu faqat istalgan vaqtda ipning holatini tekshirishingiz uchun amalga oshiriladi.
|
| |