
- •Мустафина б.М., Сейдахметова г.Е., Әлібиева ж.М.
- •Пәндік оқу - әдістемелік кешені
- •Алматы 2012
- •1. Пәннің оқу бағдарламасы – syllabus
- •Оқытушылар туралы мәліметтер:
- •1.2 Пән туралы мәліметтер:
- •Оқу жоспарының көшірмесі
- •1.3 Пререквизиттер
- •1.6 Тапсырмалардың тізімі мен түрлері және оларды орындау кестесі
- •1.7 Әдебиеттер тізімі
- •1.8 Білімді бақылау және бағалау.
- •1 Модуль бойынша бақылау жүргізуге арналған сұрақтар (1-7 бөлімдер)
- •2 Модуль бойынша бақылау жүргізуге арналған сұрақтар:
- •1.9 Қойылатын талаптар
- •2 Негізгі таратылатын материалдар мазмұны
- •2.1 Курстың тематикалық жоспары
- •2.2 Лекциялық сабақ конспектілері
- •1.1 Windows ож құрылымы Жүйе құрылымының жалпы бейнелеуі
- •2.2. Ағындарды диспетчерлеу және жоспарлау
- •2.3 Ағынды анықтау
- •2.4 Ағындармен жұмыс істеуге арналған api функциясы
- •2.5 Ағындардың приоритеті
- •3.1 Процесстерді басқару
- •3.2 Windows операциялық жүйесіндегі процесстер мен ағындар
- •3.3 Процесстермен жұмыс істеуге арнлаған api функциялар
- •4.2 Ағындарды синхрондау объектілері
- •Мьютекстер
- •5.1 Оқиғалар
- •5.2 Бұғатталған қосымша функциялар
- •7.1. Үймелер
- •7.2 Үйме жадысын басқару
- •8.1 Файлдар мен каталогтарды басқару Файлдарды құру және ашу
- •8.2 Каталогтарды басқару
- •8.3 Файлдар мен каталогтар атрибуттарын алудың басқа әдістері
- •9.1 Файлдарды бұғаттау
- •9.2 Реестр
- •Экспорттелетін идентификаторды анық қосу
- •12.1 Стандартты құрылғылар және консольді енгізу- шығару
- •12.2 Асинхронды енгізу- шығару және аяқталу порттары
- •2.3 Лабораториялық сабақтардың жоспары
- •2.4 Оқытушының басқаруымен студенттің өзіндік жұмысы бойынша оқу жоспары (соөж) (45 сағат)
- •2.5 Студенттің өзіндік жұмысының сабақ жоспары (сөж) (45 сағат)
- •2.6 Өзін өзі тексеру үшін кілтпен көрсетілген тестік жаттығулар
- •2.7 Курс бойынша емтихан сұрақтары
- •Глоссарий
- •Жүйелік программалау
12.2 Асинхронды енгізу- шығару және аяқталу порттары
Егізу- шақыру аяқталғанын ағын күтетін болса, бұл енгізу- шығару операциялары ағынмен бірге синхронды болып табылады. Ал асинхронды енгізу- шығару жағдайында, ағын өз орындалуын енгізу- шығару операциясының аяқталғанын күтпей, жалғастыра береді
Win32- де асинхронды енгізу- шығаруды орындаудың үш әдісі бар:
Көп ағынды енгізу- шығару. Әрбір үрдістегі ағын немесе үрдістер жиынтығы, өзге ағындар өз жұмысын жалғастыруы кезінде, қарапайым енгізу- шығаруды орындайды.
Өзіндік асинхронды енгізу- шығару (немесе жауып қоюмен енгізу- шығару). Оқу, жазу немесе өзге енгізу- шығару операцияларын бастаған соң, ағын өз жұмысын жалғастыра береді. Егер ағынға жұмысын жалғастыру үшін енгізу- шығарудың нәтижесі керек болса, ол дескриптор сигналын немесе көрсетілген уақиғаны күтеді.
Аяқталу процедурасы (немесе кеңейтілген енгізу- шығару). Енгізу- шығару операциясы аяқталған кезде, ағында көрсетілген аяқталу процедурасы жүйеде шақырылада.
Жабық күйдегі енгізу- шығару
Асинхронды жабық күйдегі немесе кеңейтілген енгізу- шығаруда ең алдымен жабық күйдегі файл дескрипторының атын немесе басқа объектінің атрибутын орналастыру керек. Ол үшін CreateFile шақыруында немесе файл, атауланған объект, басқа дескриптор құратын, FILE_FLAG_OVERLAPPED жалаушасы көрсетіледі.
LockFileEx функциясында жабық күйдегі құрылымды жабық күйдегі енгізу- шығаруда қолдануға болады. Бұл құрылымдар- операция аяқталғанда, потенциалды бұғаттай алатын, енгізу- шығарудың төрт функциясының (ReadFile, WriteFile, TransactNamedPipe, ConnectNamedPipe), басты емес өлшемдері.
fdwAttrsAndFlags (CreateFile үшін) немесе fdwOpenMode (CreateNamedPipe үшін) құрылымында FILE_FLAG_OVERLAPPED-ті көрсетіп кетсек, канал немесе файл тек асинхронды режимде қолдануы керек. Жабық күйдегі енгізу- шығару анонимді каналдарға қолданылмайды.
Жабық күй құрылымы
Жабық күй құрылымы (мыс: ReadFile функциясының lpOverlapped өлшемінде көрсетілген) келесі мәліметтерді сақтайды:
Оқу немесе жазу басталатын файл позициясын (64-разрядті);
Операция соңында генерацияланатын уақиғаны.
Жабық күй құрылымы келесідегідей көрсетіледі:
typedef struct_OVERLAPPED {DWORD Internal;
DWORD InternalHigh; DWORD Offset;
DWORD OffsetHigh; HANDLE hEvent;
} OVERLAPPED
Файлдағы позиция (көрсеткіш) екі элементті алады— offset и OffsetHigh, үлкен бөлігі әдетте нөлге тең. Internal және InternalHigh элементтері жүйе үшін резервтелген және қолданылмауы керек.
hEvent — уақиға дескрипторы (CreateEvent функциясымен құрылған). Уақиға атауланған немесе атауланбаған болуы мүмкін, бірақ әруақытта қолдық сбросқа ие болуы керек. hEvent NULL- ге тең болуы мүмкін; бұл жағдайда программа синхрондау объектісі болып табылатын файл дескрипторының сигналын күтуі мүмкін. hEvent NULL-ге тең болғанда, файл дескрипторы арқылы жүйе жұмыстың аяқталғанын хабарлайды, бұл дегеніміз, файл дескрипторы синхрондау объектісі болып табылады.
Программа енгізу- шығару операциясын шақырғанда, бұл құрылым жүйемен алып тасталынады (пассивті күйге өтеді). Енгізу- шақыру операциясы аяқталғанда, уақиға активті болады.
Жабық күйдегі енгізу- шығару операциясын болдырмау
Логикалық мән қайтаратын CancelIO функциясы көрсетілген дескрипторда (бұл функция тек бір өлшемге ие) аяқталмаған асинхронды енгізу- шығару операциясын қайтарады. Осы дескрипторда шақырылған ағын бастаған операциялар болдырылмайды. Өзге ағындармен басталған операцияларға бұл әсер етпейді. Болдырылмаған операциялардың қателік коды— ERROR_OPERATION_ABORTED.
Кеңейтілген енгізу- шығару аяқталу процедурасымен
Ағынды уақиғадан немесе дескриптордан аяқталу сигналын күттіргенше, жүйе енгізу- шығару операциясы аяқталғанда, қолданушымен көрсетілген аяқталу процедурасын шақыра алады. Бұл аяқталу процедурасы келесі енгізу- шығару операциясын жіберіп, кез келген басқа әрекеттерді жасай алады.
Программа қалай аяқталу процедурасын бере алады? Ех суффиксімен ерекшелінетін, кеңейтілген енгізу- шығару функциясының тобы бар. Олар аяқталу прцедурасы адресіне арналған қосымша өлшемге ие. Оқу және жазудың кеңейтілген функциялары— ReadFileEx и WriteFileEx. Бұдан басқа, бес хабарлау функциясын қолдану керек.
WaitForSingleObjectEx
WaitForMultipleObjectsEx
SleepEx
SignalObjectAndWait
MsgWaitForMultipleObjectsEx
Кеңейтілген енгізу- шығару кейде хабарламалы енгізу- шығару деп аталады.
Енгізу- шығарудың аяқталу порттары
Енгізу- шығарудың аяқталу порттары жабық күйдегі енгізу- шығарудың және тәуелсіз ағындардың қасиеттерін біріктіреді және серверлі программаларда пайдалырақ.
Енгізу- шығарудың аяқталу порттары атауланған каналдар (немесе сокеттер) дескрипторының саны өте көп болғанда, ағындар тобында шектелген сервер ағындарын құруға септігін тигізеді. Дескрипторлар бөлек ағындармен- жұмысшы серверлермен- байланысты емес, бірақ сервер ағыны олар қатынасқан кез келген дескриптордан мәліметтерді өңдей алады.
Егізу- шығарудың аяқталу порты жабық күйдегі дескрипторлардың жиынтығы болып табылады, ал ағындар порт сигналын күтеді. Дескриптордың біреуінде оқу немесе жазу аяқталғанда, бір ағын активті қалыпқа өтіп, енгізу- шығару операциясының мәліметтерін және нәтижесін алады. Осыдан кейін ол мәліметтерді өңдеп, қайтадан порт сигналын күтеді.
Басты тапсырма- енгізу- шығарудың аяқталуын құрып, оған жабық дескрипторларды енгізу болып табылады.
Енгізу-шығарудың аяқталу порттарын басқару
CreateIoCompletionPort функциясы портты құруға және дескрипторларды қосуға арналған. Ол екі тапсырманы орындауы керек болғандықтан, оны қолдану өлшемінің реті қиын.
HANDLE CreateIoCompletionPort ( HANDLE FileHandle,
HANDLE ExistingCompletionPort, DWORD CompletionKey,
DWORD NumberOfConcurrentThreads);
Параметрлер
Енгізу-шығаруды аяқтау порты — бұл OVERLAPPED режиміндегі ашық файлдар дескрипторларының ұқсастығы. FileHandle параметрі — бұл портқа қосылатын асинхронды дескриптор. Егер осы параметрде INVALID_HANDLE_VALUE мәнін көрсететін болсақ, функция енгізу-шығаруды аяқтайтын жаңа порт құрады және қайтарылатын мән ретінде қайтарады. Келесі параметр, ExistingCompletionPort бұл жағдайда NULL мәнін қабылдауы тиіс.
ExistingCompletionPort — бірінші шақыру кезінде құрылған және бірінші параметрден алынған дескриптор қосылатын порт. Егер қосу сәтті өтсе, функция порт дескрипторын қайтарады, ал сәтсіз болған жағдайда NULL қайтарады.
CompletionKey- FileHandle үшін аяқтау пакетіне кіретін кілтті тағайындайды. Бұл кілт әдетте операция типін, дескриптор және мәліметтер буферіне көрсеткішті сақтайтын мәліметтер структураларының массив индексі болып табылады.
NumberOfConcurrentThreads бір уақытта жұмыс істей алатын ағындардың максималды санын көрсетеді. Порт сигналын күтетін, бұл шектен тыс барлық ағындар бұғаттаулы күйде қалады. Егер бұл параметр нөлге тең болса, шек жүйедегі процессорлар саны болады.
Енгізу-шығару аяқтау портымен асинхронды дескрипторлардың шектеусіз санымен байланыстыруға болады. CreateIoCompletionPort-ты алғашқы шақырған кезде порт құрылады және ағындардың максимал саны анықталады. Портпен байланысуы қажет әрбір дескриптор үшін бұл функцияны қайтадан шақыру қажет. Өкінішке орай, аяқтау портынан дескрипторды жою әдісі жоқ.
Портпен байланысқан дескрипторлар ReadFileEx немесе WriteFileEx функцияларында қолданылмауы тиіс. Microsoft құжаттарында басқа ашық дескрипторлары арқылы файлдар мен өзге объекттерді бірге қолдану ұсынылмайды.
Негізгі әдебиет: 1 [165 - 234] , 2 [46 - 52 , 359 – 386 ]
Бақылау сұрақтары:
1. Стандартты құрылғылар әдетте қандай құрылғыларға тағайындалады?
2. Консолды енгізу-шығарудың арнайы функциялары
3. Асинхронды енгізу-шығаруды іске асырудың тәсілдері
Дәріс 13. Жеке жағдайлардың құрылымдық өңделуі
Win32-дағы жеке жағдайлардың құрылымдық өңделуі(Structured Exception Handling — SEH) қосымшалардың адресация кезіндегі жеке жағдайлар, арифметикалық операцияларды орындау кезіндегі өшулер және жүйелік қателіктер сияқты күтпеген оқиғаларға жауап беруіне мүмкіндік беретін сенімді механизм болып табылады. Сонымен қатар, SEH код бұғатының кез-келген нүктесінен бағдарламаның аяқталуын мүмкін қылады, және қателік кезінде программист көрсеткен іс-әрекетті және орнатуды автоматты түрде орындайды.
SEH бағдарламаның не бағдарламаға байланысты, не күтпеген жеке жағдай үшін бұғаттау, ағын немесе үрдіс аяқталғанға дейін тазарту бойынша басқа іс-әрекеттерді орындауына және ресурстарды босата алатындығына кепілдік береді. Сонымен қатар, SHE-ті бар кодқа оңай қосуға болады, ал бұл бағдарлама логикасын жиі жеңілдетеді.
Жеке жағдайлар және олардың өңдеушілері
Егер бағдарламада қандай да бір жеке жағдай өңдеушісі болмаса, алдын-ала ойластырылмаған жеке жағдай, мысалы, нолдік көрсеткіштің өзгеруі немесе нолге бөлу, бағдарламаның жедел түрде тоқтатылуына әкеліп соқтырады. Бұл проблема шақыруы мүмкін, мысалы, егер бағдарлама жұмыстың аяқталуы алдында өшірілуі керек уақытша файл құрса. SEH жеке жағдай болған кезде уақытша файлды өшіре алатын жеке жағдай өңдеушісін беруге мүмкіндік береді.
Try және Except бұғаттары
Біріншіден, кодтың қандай бұғаттауларын басқару керектігін анықтайық, және оларды жеке жағдай өңдеушілерімен қамтамасыз етейік. Функцияны түгелдей басқаруға немесе әртүрлі код бұғаттаулары мен функциялар үшін жеке жағдай өңдеушілеріне ие болуға болады.
Код бұғаты жеке жағдайлар өңдеушісіне төменде айтылған жағдайларды сәтті орын бола алады.
Жүйелік шақырулар қателіктерімен бірге байқалатын қателер шығады, және бағдарламаны аяқтау емес, қатені жөндеу керек.
Көрсеткіштер кең қолданылады, сондықтан дұрыс түрде инициализацияланбаған көрсеткіштердің өзгеру ықтималдығы болады.
Массивтермен көп іс-әрекеттер орындалады, және массив элементтері рұқсат етілген шектерден шығып кетуі мүмкін.
Жылжымалы үтірмен арифметикалық операциялар орындалады, және нолге бөлу, нақты емес нәтижелер және аса толу проблемалары бар.
Кодта не алдын-ала, не тексерістің жетіспеушілігінен жеке жағдай тудыратын функция шақырылады.
Осы бөлімдегі, сол сияқты бүкіл кітаптағы мысалдарда код бұғаттауын басқаруды орнату үшін келесідей try және except бұғаттаулары құрылады.:
try { /* Басқарылатын кодтың бұғаты */ }
except {фильтр_өрнектелуі) { /* Жеке жағдайды өңдеудің бұғаты */ }
Байқаңыз, try және except —компиллятормен танылатын кілттік сөздер.
try бұғаты қосымшаның жай кодының бөлігі болып табылады. Егер бұғаттауда жеке жағдай болса, операциялық жүйе басқаруды жеке жағдай өңдеушісіне— except кілттік сөзімен байланысқан код бұғатына өткізеді. Келесі іс-әрекеттер фильтр_өрнектелуі мәнімен анықталады.
Байқау қажет, try бұғатына ендірілген бұғатында да жеке жағдай болуы мүмкін; бұл жағдайда орындау уақытын ұстау стекті ашады, жеке жағдай өңдеушісін табады және оған басқарманы береді. Осы жағдай try бұғатында шақырылатын функцияның ішінде жеке жағдай пайда болған кезде қайталанады.
Фильтр өрнектері және оның мәндері
Фильтр өрнегі except операторында жеке жағдай болған кезде тез арада табылады. Әдетте бұл литералды константа, фильтр функциясы немесе шартты өрнек. Барлық жағдайларда өрнек үш мәннің біреуін қайтаруы тиіс.
EXCEPTION_EXECUTE_HANDLER — жүйе except бұғатын орындайды. Бұл кәдімгі жағдай.
EXCEPTION_CONTINUE_SEARCH — жүйе жеке жағдай өңдеушісін елемейді және оны таппағанша, ендірілген бұғаттардан іздейді.
EXCEPTION_CONTINUE_EXECUTION — жүйе басқаруды жеке жағдай өткен нүктеге тез арада жібереді. Бірнеше жеке жағдайлардан кейін жалғастыру мүмкін емес, және егер бағдарлама жұмысты жалғастыруға талпынса, жедел түрде басқа жеке жағдай генерацияланады.
Жеке жағдайлар кода
Еxcept блогы немесе фильтр өрнегі DWORD GetExceptionCode (VOID) функция көмегі арқылы нақты жеке жағдайды анықтай алады.
Жеке жағдай коды жеке жағдайдан кейін тез арада алынуы тиіс. Сондықтан, фильтр функциясының өзі GetExceptionCode (бұл шектеу компилляторда орнатылған) шақыра алмайды. Әдетте бұл функция жеке жағдай коды болып пайдаланушы белгілеген фильтр функциясының параметрі қызмет ететін фильтр өрнегіне шақырылады.
except (MyFilter (GetExceptionCode ())) { }
Бұл жағдайда фильтр функциясы жоғарыда айтылып кеткен үш мәннің бірі болуы тиіс фильтр өрнегінің мәнін анықтайды және қайтарады. Функция өзінің қайтаратын мәнін жеке жағдай коды негізінде анықтай алады; мысалы, фильтр жылжымалы үтірмен жасалатын операциялар негізінде жеке жағдайларды сыртқы өңдеушіге (EXCEPTION_CONTINUE_SEARCH қайтару арқылы) бере алады, ал жадыға қатынас құруды бұзуды берілген өңдеуіште дұрыстай (EXCEPTION_EXECUTE_HANDLER қайтару арқылы) алады.
GetExceptionCode жеке жағдай кодтарының көптеген әртүрлі мәндерін қайтарып бере алады. Барлық бұл кодтар бірнеше категорияға бөлінеді.
• Программалық бұзылулар, мысалы:
- EXCEPTION_ACCESS_VIOLATION — процесстің рұқсаты жоқ виртуалды мекенжайымен оқу немесе жазып алу мүмкіндігі;
- EXCEPTION_DATATYPE_MISALIGNMENTNMENT — процессорлардың көптеген түрлері, мысалы, DWORD типті деректер 4-байттық шектермен тегістелгенін талап етеді;
- EXCEPTION_NONCONTINUABLE — фильтрдің айтылу мәні exception_continue_executio болған, бірақ берілген жеке жағдайдан кейін жалғастыру мүмкін емес.
HEAP_GENERATE_EXCEPTIONS жалаушалары қолданылатын HeapAlloc және HeapСreate жады білу функцияларымен шақырылатын жеке жағдайлар. Код мәні STATUS_NO_MEMORY немесе EXCEPTION_ACCESS_VIOLATION болады.
Төменде Exception функциясымен генерацияланатын пайдаланушы анықтаған жеке жағдайлар коды қарастырылады.
Арифметикалық операциялар бойынша әртүрлі кодтар жиыны, мысалы:
EXCEPTION_INT_DIVIDE_BY_ZERO және EXCEPTION_FLT_OVERFLOW.
• өңдеушілер қолданатын жеке жағдайлар, мысалы EXCEPTION_BREAKPOINT және EXCEPTION_SINGLE_STEP.
Сонымен қатар қосымша (сонымен қатар процессор типіне тәуелді) ақпаратты қайтаратын тек фильтр көрінісінен шақырылатын альтернативті функция бар:
LPEXCEPTION_POINTERS GetExceptionInformation (VOID)
EXCEPTION_POINTERS құрылымы басқа екі құрылымдарда топталған процессорге тәуелсіз және тәуелді ақпаратты сақтайды:
typedef struct _EXCEPTION_POINTERS { PEXCEPTION_RECORD ExceptionRecord; PCONTEXT ContextRecord;
} EXCEPTION_POINTERS;
EXCEPTION_RECORD GetExceptionCode функциясымен қайтарылатын бірдей мәндер жиыны бар ExceptionCode үшін элементті сақтайды. Тағы бір элемент EXCEPTION_RECORD - ExceptionFlags - 0 мәнін немесе фильтр функциясына орындауды жалғастыру керек екендігін анықтауға мүмкіндік беретін EXCEPTION_NONCONTINUABLE мәнін қабылдайды. Басқа элементтер ExceptionAddress виртуалды жадының адресін және ExceptionInformation параметрлерінің массивін сақтайды. EXCEPTION_ACCESS_VIOLATION жағдайында бірінші элемент жазу немесе оқу кезінде бұзулар болған, ал екінші элемент виртуалды жадының адресін көрсетеді.
Екінші элемент EXCEPTION_POINTERS - ContextRecord - процессорге тәуелді ақпаратты сақтайды. Әрбір процессор типі үшін әртүрлі құрылымдар бар; бұл туралы ақпаратты <winnt.h> табуға болады.
Қателер және жеке жағдайлар
Қателікті кейбір кезде белгілі жерде пайда бола алатын жағдай ретінде санауға болады. Жүйелік шақырулар негізіндегі қателер, мысалға лезде код логикасымен табылу керек және де олар туралы хабарлама шығу керек. Ол үшін программисттер әдетте сәтсіздікпен өткенін білу үшін ашық тексеріс қояды, мысалы файлдан оқу операциясының.
Басқа жағынан, жеке жағдай көбінесе кез келген жерде пайда бола алады және де жеке жағдайға тексеріс жасау ыңғайсыз немесе мүмкін емес. Мысалдар — нөлге бөлу және жадыға қатынас құрудың бұзылуы.
Сонда да кей кездерде қателер мен жеке жағдайлар арасындағы айырмашылық өшіріледі. Егер жады көлемі жеткіліксіз болса, онда Win32 НеарАllос және HeapCreate функцияларының көмегімен жадыны резервтеу барысында жеке жағдайларды генерациялай алады. Программалар сонымен қатар программистпен аяқталған кодтармен бірге өзіндік жеке жағдайларын RaiseException функция көмегімен шақыра алады.
Жеке жағдай өңдегіштері ішкі блоктардан немесе программа логикасының функциясынан (goto немесе longjmp басқаруларын көшіруге жүгінбей-ақ) шығуға рұқсат береді. Егер код блогы ашық файлдар, жады немесе синхрондау объектісі сияқты ресурстарға байланыс құрса, бұл мүмкіндік әсіресе қымбат, сонымен қатар өңдеуші бұл ресурстарды босата алады; жеке жағдай өңдеушісінен кейін программа орындалуын аяқтамай, оны жалғастыра алады. Және де программа жүйенің жағдайын блоктан шығу кезінде қайта орната алады.
Қолданушы генерациялайтын жеке жағдайлар
Программаның орындалу барысында RaiseException функциясының көмегімен жеке жағдайды кез келген нүктеде шақыруға болады. Осылайша программа қатені тауып, оны жеке жағдай ретінде өңдеуі мүмкін.
VOID RaiseException ( DWORD dwExceptionCode,
DWORD dwExceptionFlags, DWORD cArguments, LPDWORD lArguments)
Параметрлер
dwExceptionCode — пайдаланушымен анықталатын код. Жүйе үшін резервтелген 28 битті қолданбаңыз. Қателер коды 27-0 биттерінде орындалады (яғни он алтылық санның үлкенінен басқаларының барлыығына) 29 бит “тапсырыс” жеке жағдайын (Microsoft емес) бейнелеу үшін орнатылады. 31-30 биттер жеке жағдайлардың қатаңдығын көрсетеді. Төменде бұның қалай орындалатындығы көрсетілген. Сонымен қатар бастапқы он алтылық сан коды 29 бит орнатылған жағдай үшін келтірілген.
0 — Жетістік (бастапқы сан 2).
1 — Информациялық (бастапқы сан 6).
2 — Ескерту (бастапқы сан А).
3 — Қате (бастапқы сан Е).
dwExceptionFIags өлшемі әдетте 0-ге орнатылады, бірақ EXCEPTION_NONCONTINUABLE орнатылуының мәні фильтр бейнесі EXCEPTION_CONTINUE_EXECUTION генерацияламайтындығына көрсетеді; егер осы жағдай орындалса, EXCEPTION_NONCONTINUABLE жеке жағдайы лезде орындалады.
Егер lpArguments өлшемі NULL мәнін иеленбесе, ол фильтр өрнегіне берілетін 32-разрядты мән сақтайтын cArguments (үшінші өлшем) өлшем массивіне сілтейді. EXCEPTION_MAXIMUM_PARAMETERS параметрінің рұқсат етілген саны қазіргі уақытта 15-ке тең. Бұл құрылымға GetExceptionInformation арқылы қатынас құрамыз.
Аяқтау өңдеушілері
Аяқтау өңдеушісінің мақсаты жеке жағдай өңдеушісінің мақстаы сияқты, бірақ ағын блоктан программаның кәдімгі жүріс кезіндегі және де жеке жағдайдың түсуі кезіндегі шығу уақытында орындалады. Одан басқа, аяқтау өңдеушісі жеке жағдайды шығара алмайды.
Аяқтау өңдеушісі try-finally операторындағы __finally кілттік сөзінің көмегімен құрылады. Оның құрылымы try-except операторының құрылымы сияқты, бірақ онда фильтр бейнесі жоқ. Аяқтау өңдеушілері жеке жағдай өңдеушілері сияқты дескриптор жабылуын, ресурс босатуларын, масканың қайта пайда болуына және блоктан шығару алдындағы белгілі күйге процестің қайтуы бойынша басқа әрекеттердің орнатылуына ыңғайлы әдістер береді. Мысалы, программа return операторын блок ортасында орындай алады, ал аяқтау өңдеушісі тазарту бойынша жұмысты орындайды. Осылайша, тазарту кодының тікелей блокқа қоюын керек етпейді және осы кодқа өту үшін goto операторына қатынасты да керек етпейді.
__try { /* Код блогы. */ }
__finally { /* Аяқтау өңдеушісі (блок finally). */ }
Try блогынан шығу
Аяқтау өңдеушісі төмендегі себептердің есебінен басқару try блогынан шығатын әр кезде орындалады:
Блок соңы жетіледі және аяқтау өңдеушісіне басқару "құлайды";
Блоктан шығуды шақыратын келесі операторлардың біреуі болады: return, break, goto, longjmp, continue, __leave
Жеке жағдай.
Авариялық аяқталу
Кез келген басқа себептен аяқталу, яғни блок соңына жетудің ерекшелігі және аяқталу өңдеушісіне өтудің немесе __leave операторының орындаулары авариялық болып табылады. __leave операторы __try блогына өтуді орындайды және аяқтау өңдеушісін шақырады, бұл goto-ға қарағанда өте эффективті, өйткені бұл жағдайда стекті айналдыру қажет емес. Try блогы қалай аяқталғандығын анықтау үшін аяқтау өңдеушісінде келесі функция қолданылады:
BOOL AbnormalTermination (VOID)
Функция авариялық аяқталуда TRUE –ді және кәдімгі аяқталуда FALSE-ты қайтарады.
Аяқтау өңдеушісінің орындалуы мен одан шығуы
Аяқтау өңдеушісі немесе finally блогы өзі бақылайтын блок контекстінде немес функциясында орындалады. Басқару аяқтау өңдеушісінің аяғынан келесі операторға өтее алады. Сонымен қатар аяқтау өңдеушісінде өту операторы орындала алады (return, break, continue, goto, longjmp немесе __leave).
Тағы бір вариант — өңдеушіден жеке жағдай арқылы шығу.
Finally және Except блоктарының сәйкестігі
Try бөлек блогы бір-ақ finally немесе except блогын иелену керек; екі блок бірден өткізілмейді. Бірақ бір блокты екінші блокқа салуға болады; бұл әдіс жиі пайдалы болып шығады.
Келесі код дұрыс және программа логикасы арқылы да, жеке жағдай арқылы да уақытша файл циклден шығу кезінде жойылады деп кепілдік береді. Бұл методика файл бұғаттаудан шығуға кепілдік беру үшін де өте пайдалы. Сонымен қатар жылжымалы үтір операциясы үшін try-except ішкі блогын қолдануға болады.
try { /* Сыртқы блок try-except. */
while (...) try ( /* Ішкі блок try-finally. */
hFile = CreateFile (TempFile, ...);
if (...) try { /* Ішкі блок try-except. */
/* ПЗ жеке жағдайына рұқсат беру және санағышты орындау. */}
except (EXCEPTION EXECUTE HANDLER) {
... /* ПЗ жеке жағдайын өңдеу. */ _clearfp (); }
... /* ПЗ –ке байланысты емес өңдеу. */ }
finally { /* цикл соңы while loop. */
/* ӘР цикл итерациясында орындалады */
CloseHandle (hFile); DeleteFile (TempFile); } }
except (айтылу_сүзгі) {
/* Жеке жағдай өңдеушісі. */ }
Негізгі әдебиет: 1 [ 327 - 356] , 2 [ 90 - 111]
Бақылау сұрақтары:
Жеке жағдайдың құрылым өңдеушісі нені білдіреді?
Try и Except блоктарының құрылымы
Аяқтау өңдеушілерінің міндеті
Дәріс 14. Win32 объекттер қауіпсіздігі
Қауіпсіздік жүйесінің мақсаты
Қауіпсіздік жүйесінің екі негізгі мақсаты: қатынас құру деңгейін тексеру және клиенттің іс-әрекетін бақылау. Бірінші мақсатты жүзеге асыру үшін пайдаланушының қорғалған объектіге қатынау құқығы бар екендігіне көз жеткізу керек. Егер де олай болмаса, қатынау сәтсіз аяқталуы тиіс, ал пайдаланушы «қатынас құруға тиым салынған» деген хабарлама алуы керек(access denied). Қауіпсіздік жүйесінің екінші функциясы— аудит, яғни клиенттің іс-әрекетін бақылау, әрқашан орындала бермейді. Аудит бір немесе басқа қорғалған объектіге қатынас құрумен байланысқан клиенттің іс-әрекет журналының файлындағы құжаттауды білдіреді. Администраторлар аудит жүйесін қоса және сөндіре алады, олар сонымен қатар барлық қатынауларды құжаттамай-ақ, тек қана қатынас құрудың тәртіптерін бұзумен байланысты және нәтижесінде сәтсіз аяқталған қатынаулар құжатталатындай жүйе құра алады.
Құқық және артықшылықтар
Қауіпсіздік жүйесі клиенттің іс-әрекетерінің орындалуын екі негізгі механизмдер көмегімен қадағалайды. Бұл екі механизм — құқық және артықшылық. Артықшылық — бұл кейбір пайдаланушының бүкіл жүйеге қатысты кейбір іс-әрекеттерге рұқсат беруі. Мысалы, пайдаланушы жүйеге қосылу, дисктерді резервті көшіру немесе форматтауды іске асыру, бағдарламаларды кейінге қалдыру артықшылықтарын иеленуі мүмкін.
Құқық артықшылықтармен салыстырғанда өзгеше түрде қолданылады. Құқық — бұл кейбір пайдаланушының жеке объектіге қатысты кейбір іс-әрекеттерге рұқсат беруі. Құқық қатынас құруы операциялық жүйемен басқарылатын белгілі объекттерге қатысты тағайындалады. Құқықты тек жеке пайдаланушылар ғана емес, сонымен қатар пайдаланушылар топтары да иемдене алады.
Қауіпсіздік атрибуттары
Create жүйелік шақырудың көмегімен құрылған әрбір объектте бірінші кезекте қауіпсіздік атрибуттарының параметрі болады. Сондықтан бағдарламалар файлдарды, үрдістерді, ағындарды, оқиғаларды, семафораларды, атанған каналдарды және т.б. қорғай алады.
Қауіпсіздіктің құрылуы Create шақыруына SECURITY_ATTRIBUTES структурасын қосудан басталады. SECURITY_ATTRIBUTES структурасының маңызды элементі – әртүрлі құқықтарды иемдену немесе иемденуге тиым салынған объект иелері және пайдаланушылар туралы мәліметтері бар қауіпсіздік дескрипторына көрсеткіш.
Жеке үрдіс пайдаланушы-иегерді және оның топқа жататындығын анықтайтын өзінің қатынас құру маркерімен идентификатталады. Үрдіс объектіге байланыс құруға талпынған кезде, Windows NT ядросы сол маркер бойынша үрдісті тани алады, және қауіпсіздік дескрипторындағы мәлімет бойынша процесстің объектімен байланысуына құқығы бар ма екенін шеше алады.
Қауіпсіздік атрибуттары келесідей анықталады:
Typedef struct _ SECURITY_ATTRIBUTES {
DWORD nLength; // структура өлшемі
LPVOID lpSecurityDescriptor; // Объектіге қатынас құруды
// басқаратын қауіпсіздік дескрипторы
BOOL bInheritHandle; //Ұрпақтық үрдісіне дескриптордың
// (handle)
// мұрагерлігін рұқсат етеді
} SECURITY_ATTRIBUTES;
nLength элементі sizeof (SECURITY_ATTRIBUTES) мәнін қабылдау қажет.
Қауіпсіздік элементтеріне шолу: қауіпсіздік дескрипторы.
Қауіпсіздік дескрипторы InitializeSecurityDescriptor функциясымен инициализацияланады.
SECURITY_DESCRIPTOR құрылымы өзінде кейбір объектіге рұқсат етілмеген қатынас құрудан қорғаумен байланысқан мәліметтерді сақтайды. Қауіпсіздік дескрипторы деп аталатын бұл құрылымда қандай пайдаланушылар объектіге қатынас құру құқығына ие және сол объектіге қатысты пайдаланушы қандай іс-әрекет жасай алатыны туралы мәлімет сақталады.
Объекттің қауіпсіздік дескрипторы өзінде келесі мәліметтерді сақтайды:
- SID (security identifier) объект иесі;
- SID объект иесінің негізгі тобы;
- қатынас құрудың шектеулі тізімі (Discretionary Access Control List, DACL-қатынас құруды басқарудың дискреционды тізімі);
- қатынас құрудың жүйелік тізімі (System Access Control List, SACL);
- басқарушы мәлімет (мысалы, ACL тізімдерінің ұрпақтық қауіпсіздік дескрипторына ақпаратты беру туралы мәліметтер);
DACL тізімі объектіге кімнің қатынас құру құқығы бар екенін немесе жоқ екенін анықтайды. SACL тізімі қай іс-әрекет туралы ақпарат журнал файлына енгізілетінін анықтайды.
InitializeSecurityDescriptor функциясы сіз белгілеген дескриптордың ішінде DASL, SACL, иегер және иегердің негізгі тобы болмайтындай етіп инициализациялайды, ал барлық басқарушы жалаушалар FALSE мәніне орнатылған. Осының өзінде, дескриптордың абсолют форматы бар. Бұл нені білдіреді? Абсолют форматтағы дескриптор объекттің қорғанысымен байланысты ақпаратқа көрсеткішті сақтайды. Бұл түрмен салыстырғанда қатысты(self-relative) форматтағы дескриптор жадыда тізбектей қатар-қатар орналасқан бүкіл керекті ақпаратты сақтайды. Осылайша, абсолют дескрипторды дискіге жазуға болмайды, ал қатысты дескрипторды- болады.
Windows абсолют дескрипторды қатысты формаға және керісінше түрлендіруге мүмкіндік береді. Әдетте бұл егер де сіз дескрипторды дискке жазсаңыз және дисктен дескрипторды оқысаңыз қажет болатын нәрсе. Қауіпсіздік дескрипторына көрсеткіштің берілуін керек ететін жүйелік шақырулар тек абсолют форматтағы дескриптормен жұмфс жасайды.
Түрлендіру MakeSelfRelativeSD және MakeAbsoluteSD шақырулардың көмегімен жүзеге асырылады. Абсолют форманы қатысты формаға түрлендіру қиын емес. Алайда, кері түрлендіру(қатысты формадан абсолютке) бірнеше этаптардан тұрады.
SetSecurityDescriptorOwner және SetSecurityDescriptorGroup функциялары SID пен қауіпсіздік дескрипторларын байланыстырады. ACL тізімдері InitializeAcl функия көмегімен инициализацияланады және содан соң қауіпсіздік дескрипторымен SetSecurityDescriptorDacl немесе SetSecurityDescriptorSacl функциялары арқылы байланысады.
Қатынас құруды басқарудың тізімдері
Әрбір ACL қатынас құруды басқарудың(access control entry — ACE) элементтерінің тізімі болып табылады. Қатынас құруды басқарудың элементтерінің екі түрлі типі бар: қатынас құруға рұқсат беру үшін және тиым салу үшін.
Біріншіден, ACL InitializeAcl функциясымен инициализацияланады, ал содан соң оған қатынас құруды басқарудың элементтері қосылады. Әрбір АСЕ SID идентификаторын және рұқсат етілетін немесе тиым салынатын құқықтарды анықтайтын қатынас құру маскасын сақтайды. Типтік қатынас құру құқықтары — GENERIC_READ және DELETE.
Қатынас құруды басқарудың элементтерін шектеулі ACL құрамына қосу үшінекі функция қызмет көрсетеді: AddAccessAllowedAce және AddAccessDeniedAce. Осы функциялардың біріншісі SACL ге қосу үшін тағайындалған. Бұл қатынас құру аудитін SIDке шақырады.
Қатынас құруды басқарудың элементтерін өшіру үшін DeleteAce функциясы қызмет етеді, ал олармен байланысу үшін — GetAce.
Win32 объектілерінің қауіпсіздігін қолдану
Әрбір процесстің SID идентификаторлары бар(қатынас құрудың маркерінде). Солардың негізінде жүйенің ядросы қатынас құруға рұқсат па және аудит енгізу керек пе екендігін анықтайды. Қатынас құрудың маркері сонымен қатар иегерге кейбір артықшылықтар бере алады(операцияларды ACL дегі құқыққа қарағанда жоғары приоритетті орындау қабілеттілігі). Осының арқасында администратор ACL файлдарында белгілі құқыққа ие болмай-ақ оқу және барлық файлдарға жазу артықшылығына ие бола алады.
Үрдіс объектпен байланысқа сұраныс жіберген кезде не болатынын көру оңай. Біріншіден, пайдаланушының өзінің жеке куәлігі және оның топқа жататындығы негізінде процесстің кейбір артықшылықтары бар. Бұл артықшылықтар SID идентификаторларына жазылған.
Егер пайдаланушының және топтың идентификаторлары қатынас құруға рұқсат бермесе, жүйе ядросы қатынас құру құқығын ACL-дан іздейді. Керекті қызметке тиым салатын немесе рұқсат беретін бірінші элемент шешуші мән болады. Сондықтан, ACL-ге енгізілетін қатынас құруды басқару элементтерінің реті маңызды. Анық қатынас құра алмайтын пайдаланушы қатынас құра алатын топқа мүшелік негізінде оны алып кетпес үшін қатынас құруға тиым салатын АСЕ жиі тізімнің бас жағына орналастырылады. Алайда, рұқсат беру және тиым салу элементтерін қажетті семантика алу үшін араластыруға болады. Барлық құқыққа тиым салатын АСЕ тізімнің соңында да болуы мүмкін; Бұл ACE-де ескерілмеген барлық пайдаланушыларға қатынас құруға тиым салынатынына кепілдік береді.
Объект құқығы және объектіге қатынас құру
Объект, мысалы файл, құрылған кезінде өз құқықтарын алады, алайда олар кейін өзгертілуі мүмкін. Үрдіс объектіге қатынас құруды дескрипторды колданғысы келген кезде сұратады. Дескриптор сұранысы өзінің параментрлерінің бірінде қажетті қатынас құруды сақтайды, мысалы GENERIC_READ. Егер үрдіс керекті қатынас құруды алуға құқықтарға ие болса, онда сұраныс сәтті өтеді. Бір объекттің әртүрлі дескрипторларында әртүрлі қатынау болуы мүмкін. Қатынас құрудың жалаушалары үшін де ACL-ды құрған кездегі құқыққа рұқсат беру немесе тиым салу үшін қолданылатын мәндер пайдаланылады.
Қауіпсіздік сипаттаушысының инициализациясы
Дескриптормен жұмыс оның инициализациясынан басталады. Бұл жағдайда psd параметрінде SECURITY_DESCRIPTOR дұрыс құрылымының адресін көрсетіп кету қажет. Бұл құрылымдар программист үшін мөлдір емес, және олармен жұмыс істеу үшін белгілі функциялар қолданылады.
dwRevision параметріне тұрақты мән меншіктеледі SECURITY_DES-CRIPTOR_REVISION
BOOL InitializeSecurityDescriptor (
PSECURITY_DESCRIPTOR psd, DWORD dwRevision)
Қауіпсіздік идентификаторлары
SID идентификаторлары Win32 пайдаланушыларды және топтарды тану үшін пайдаланылады. Бағдарлама SID-ді пайдаланушыға, топқа, доменге және т.б. сәйкес келетін есепке алу жазбаның аты бойынша іздей алады. Есепке алу жазба алыстатылған жүйеде орналасуы мүмкін.
BOOL LookupAccountName ( LPCTSTR lpszSystem,
LPCTSTR lpszAccount, PSID psid, LPDWORD lpcbSid,
LPTSTR lpszReferencedDomain, LPDWORD lpcchReferencedDomain,
PSID_NAME_USE psnu)
Параметрлер
lpszSystem және lpszAccount жүйенің және есепке алу жазбалар аттарына сілтейді. Жиі lpszSystem-ге локальды жүйеге сілтеу үшін NULL мәні меншіктеледі.
psid — *lpcbSid өлшемі бар қайтарылатын ақпарат. Егер буфер жеткіліксіз үлкен болатын болса, функция керекті өлшемді қайтарып, қателікпен аяқталады.
lpszReferencedDomain — ұзындығы *lpcchReferencedDomain символ жол.. Ұзындық параметрі буфер өлшеміне инициализациялануы керек (өшулер жай протоколдармен өңделеді). Қайтарылатын мән ізделінді ат орналасатын доменді анықтайды. "Administrators" есепке алу жазбасы "BUILTIN" қайтарады, сол уақытта пайдаланушының есепке алу жазбасының аты сол пайдаланушының атын қайтарады.
Psnu параметрі айнымалы SID_NAME_USE (перечислимого типа)-ға сілтейді және SidTypeWellKnownGroup, SidTypeUser, SidTypeGroup және т.б. мәндер үшін тексерілуі мүмкін.
BOOL LookupAccountSid ( LPCTSTR lpszSystem, PSID psid,
LPTSTR lpszAccount, LPDWORD lpcchName,
LPTSTR lpszReferencedDomain,
LPDWORD lpcchReferencedDomain, PSID_NAME__USE psnu)
LookupAccountSid функциясы SID сілтеп және есепке алу жазбасының атын алып, кері үрдіс жасауға мүмкіндік береді. Есепке алу жазбасының аты ретінде кез-келген үрдіске колайлы ат таңдасақ болады. Кейбір аттар, мысалы Everyone (Все), кең қолданбалы. Берілген процесстегі пайдаланушының есепке алу жазбасының атын келесі функция көмегімен алуға болады
BOOL GetUserName ( LPTSTR lpBuffer, LPDWORD lpcchBuffer)
Пайдаланушы аты және оның ұзындығы жай тәсілмен қайтарылады. InitializeSid және AllocateAndInitializeSid функцияларының көмегімен SID-ді құруға және оларды басқаруға болады. Бірақ, мысалдар есепке алу жазбаларының аттары бойынша алынған идентификаторлармен ғана шектелген.
SID белгілі болған жағдайда, олар инициализацияланған қауіпсіздік дескрипторына ендірілуі мүмкін.
BOOL SetSecurityDescriptbrOwner ( PSECURITY__DESCRIPTOR psd,
PSD psidOwner, BOOL fOwnerDefaulted)
BOOL SetSecurityDescriptorGroup ( PSECURITY__DESCRIPTOR psd,
PSID psidGroup, BOOL fGroupDefaulted)
Мына жерде psd сәйкес қауіпсіздік сипаттаушысына сілтеп отыр, ал psidOwner немесе psidGroup) — бұл SID иесінің адресі (топтың). fOwnerDefaulted немесе (fGroupDefaulted) параметрі үнсіздікпен берілген ақпаратты қолдану керектігін көрсетеді.
GetSecurityDescriptbrOwner және GetSecurityDescriptorGroup функциялары берілген қауіпсіздік сипаттаушысының SID (иегер немесе топтың) қайтарады.
ACL тізімдерін басқару
ACL тізімдерін қалай басқару, ACL- ді қауіпсіздік дескрипторымен қалай байланыстыру және оған құатынас құруды басқарудың элементтерін қалай қосатындығын қарастырайық.
Жұмыс ACL структурасының инициализациясынан басталады. ACL-мен тікелей байланысуға болмайды. Бағдарлама ACL ролін ойнайтын тек буфер беруі тиіс; оның мазмұнын функция басқарады.
BOOL InitializeAcl ( PACL pAcl, DWORD cbAcl,
DWORD dwAclRevision)
Бұл жерде pAcl — программист берген өлшемі cbAcl байт буфер адресі. ACL 1 Кбайт өлшемі көптеген есептер үшін жеткіліктіден де жоғары. dwAclRevision параметрі ACL_REVISION мән қабылдауы қажет.
Инициализациядан кейін қатынас құруды басқарудың элементтері тізімге қалаған ретпен қосылады.Ол үшін келесі екі функциялар тағайындалған:
BOOL AddAccessAllowedAce ( PACL pAcl, DWORD dwAclRevision,
DWORD dwAccessMask, PSID pSid)
BOOL AddAccessDeniedAce ( PACL pAcl, DWORD dwAclRevision,
DWORD dwAccessMask, PSID pSid)
Бұл жерде pAcl InitializeAcl функциясымен инициализацияланған сол ACL құрылымына сілтейді, ал dwAclRevision қайтадан ACL_REVISION мәнін қабылдап тұр. pSid параметрі SID-ке сілтеп тұр, мысалы LookupAccountName функциясынан алынған.
(dwAccessMask) қатынас құру маскасы SID идентификаторы белгілеген топ немесе пайдаланушыға рұқсат берілген немесе тиым салынған құқықтарды анықтайды. Алдын-ала анықталған маска мәндері объект типіне тәуелді.
Соңында ACL-ды қауіпсіздік дескрипторымен қосу қажет. Шектелген ACL үшін келесі функция қолданылады:
BOOL SetSecurityDescriptbrDacl ( PSECURITY_DESCRIPTOR psd,
BOOL fDaclPresent, PACL pAcl, BOOL fDaclDefaulted )
Егер fDaclPresent TRUE мәніне тең болса, онда ол pAcl құрылымында ACL бар екенін көрсетеді; ал егер FALSE — функция рАс1-дың барлық берілген мазмұнына мән бермейді.
Егер fDaclDefaulted соңғы жалаушасы FALSE тең болса, ол ACL-ң программистпен генерацияланып отырғанын білдіреді. Кері жағдайда ACL мұрагерлік сияқты үнсіздікпен қабылданған механизммен қалыптасады, және fDaclDefaulted мәні FALSE тең болуы тиіс.
Қауіпсіздік дескрипторын оқу және өзгерту
Қауіпсіздік дескрипторы файлмен байланысқаннан кейін, бар файлдың қауіпсіздік параметрлерін анықтау және керек болса өзгерту қажет. Файлдың қауіпсіздік параметрлерін беру және оқу үшін қауіпсіздік дескрипторында келесі функциялар қолданылады:
BOOL GetFileSecurity ( LPCTSTR lpszFileName,
SECURITY_INFORMATION secInfo,
PSECURITY__DESCRIPTOR psd, DWORD cbSd,
LPDWORD lpcbLengthNeeded)
BOOL SetFileSecurity ( LPCTSTR lpszFileName,
SECURITY__INFORMATION secInfo,
PSECURITY_DESCRIPTOR psd)
Параметрлер
secInfo — OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION, DACL_SECURITY_INFORMATION және SACL_SECURITY_INFORMATION мәндерін қабылдайтын саналған тип константасы.
Бұл параметр қауіпсіздік сипаттаушысының қай бөлігін алу немесе орнату керек екендігін көрсетеді.
GetFileSecurity үшін қайтару буфері өлшемін анықтаудың ең тиімді тәсілі— осы функцияны екі рет шақыру. Бірінші шақыруда cbSd параметрінде 0-ді көрсетіңіз. Буфердің белгіленуінен кейін функцияны екінші рет шақырамыз.
Әрине белгілі, бұл операцияларды орындау үшін файлға сәйкес рұқсаттар керек. Мысалы, SetFileSecurity-ді сәтті орындау үшін WRITE_DAC рұқсаты немесе объект иегері болу қажет.
GetSecurityDescriptorOwner және GetSecurityDescriptorGroup функциялары қауіпсіздік дескрипторынан GetFileSecurity функциясы арқылы алынған SID идентификаторын бөліп ала алады. АСL-ды алу үшін келесі функция қызмет етеді:
BOOL GetSecurityDescriptorDacl ( PSECURITY_DESCRIPTOR psd,
LPBOOL fDaclPresent, PACL *pAcl, LPBOOL lpfDaclDefaulted)
Оның параметрлері SetSecurityDescriptorDacl параметрлерімен бірдей, айырмашылығы жалаушалар орнатылмайды, керісінше олар берілген АСL бар ма және пайдаланушымен немесе үнсіздікпен орнатылған ба екенін көрсетіп қайтарылады.
АСL бұғатталуын шешу үшін оның қанша АСЕ элементтерін сақтайтынын білу керек.
BOOL GetAclInformation ( PACL pAcl, LPVOID pAclInformation, DWORD cbAclInfo, ACL_INFORMATION_CLASS dwAclInfoClass)
Көп жағдайларда АСL dwAclInfoClass ақпарат класы AclSizeInformation мәнін қабылдайды, ал AclInformation параметрі — бұл ACL_SIZE_INFORMATION типінің құрылымы. Тағы да бір класс мәні Acl- RevisionInformation бола алады.
ACL_SIZE_INFORMATION құрылымы үш элемент сақтайды: олардың ең маңыздысы- AceCount тізімдегі элементтер санын көрсетеді. АСL-дың үлкендігін анықтау үшін AclBytesInUse және AclBytesFree элементтерінің мәндерін қараңыз..
BOOL GetAce ( PACL pAcl, DWORD dwAceIndex, LPVOID *pAce)
Бұл функция АСЕ элементтерін (олардың жалпы саны белгілі) индекс бойынша алуға мүмкіндік береді. рАсе параметрі өз кезегінде АсеТуре элементін сақтайтын Header элементі бар АСЕ құрылымына сілтейді. Элемент типін ACCESS_ALLOWED_ACE_TYPE және ACCESS_DENIED_ACE_TYPE мәндеріне тексеруге болады..
Негізгі әдебиет: 1 [371 - 698] , 2 [112 - 131]
Бақылау сұрақтары:
Қауіпсіздік атрибуттары қандай ақпарат сақтайды?
Қауіпсіздік десерипторв қандай элементтерден тұрады?
3. Қатынас құрудың басқару тізімдерінің міндеті.
Дәріс 15. Үрдісаралық қарым-қатынас
Win32 үрдісаралық қарым-қатынасты (interprocess communication, IPC) қамтамасыз ету үшін екі негізгі механизм болып, анонимдік канал және аталған канал деп аталынатын екі негізі бар.
Сонымен қатар "бірдің көпке" типті хабарламаларды кеңауқымды таратуды жүргізуге мүмкіндік беретін пошталық ұяшықтар бар..
Анонимдік каналдар
Win32 анонимдік каналдары бірбағытты (жартыдуплексті), символды-бағытталған үрдісаралық қарым-қатынас құруға рұқсат береді. Әр каналдың екі дескрипторы бар: оқу дескрипторы және жазу дескрипторы. Канал құру үшін келесі CreatePipe функциясы қызмет атқарады:
BOOL CreatePipe ( PHANDLE phRead, PHANDLE phWrite, LPSECURITY_ATTRIBUTES lpsa, DWORD cbPipe)
IPC үшін каналды қолдану үшін тағы бір канал дескрипторларының бірімен байланысқан үрдіс керек.
Егер канал бос болса, онда каналдан оқу дескрипторынан оқу бұғатталады. Керісінше жағдайда ReadFile шақыруында белгіленген байт соңынан аспайтын каналда қанша байт болса, соншасы саналады.
Сонымен қатар, жады буферінде реализацияланатын толған каналдағы жазу операциясы бұғатталады. Одан басқа анонимдік каналдар мәліметтерді тек бір жаққа өткізеді. Қосбағытталған байланыс үшін екі канал қажет.
Аталған каналдар
Аталған каналдар IPC-ті қолданумен қосымшаларды реализациялаудың ыңғайлы құралы ретінде қолданылатын ерекшеліктер қатарына ие.
Аталған каналдардың ерекшеліктері төменде көрсетілген:
Аталған каналдар хабарламаларға бағытталған, сондықтан оқу процесі айнымалы ұзндықты хабарламаларды олардың жазу процесімен берілу сияқты оқи алады.
Аталған каналдар қосбағытталған, сондықтан екі процесс хабарламалармен бір канал арқылы алмасуы мүмкін.
Аталған каналдардың бірнеше тәуелсіз үлгілері болу мүмкін. Мысалы, бірнеше клиент бір каналды қолдану арқылы бір сервермен байланыса алады және сервер клиентке сол канал үлгісі арқылы жауап береді.
Ат бойынша каналмен желідегі жүйелер байланыса алады. Аталған канал арқылы байланыс екі машинада жұмыс істеп жатқандығы тәуелсіз емес.
Аталған канал бойынша қарым-қатысты жжәне клиенттің сервермен байланысын жеңілдететін бірнеше жартыфабрикат-функция бар.
Аталған каналдарды қолдану
CreateNamedPipe функциясы аталған каналдың бірінші үлгісін құрады және оны дскрипторға қайтарады. Сонымен қатар бұл функция канал үлгілерінің максимал санын анықтайды және бір уақытта қызмет көрсетуге болатын клиенттер санын анықтайды.
Әдетте құру процесі сервер деп аталады. Басқа жүйеде жұмыс істейтін процестер-клиенттер бұл каналды CreateFile көмегімен ашады.
Аталған каналдардың құрылуы
Төменде CreateNamedPipe функциясы келтірілген:
HANDLE CreateNamedPipe ( LPCTSTR lpszPipeName,
DWQRD fdwOpenMode, DWORD fdwPipeMode,
DWORD nMaxInstances, DWORD cbOutBuf, DWORD cblnBuf,
DWORD dwTimeOut, LPSECURITY_ATTRIBUTES lpsa)
Параметрлер
lpszPipeName канал атын \\.\pipe\[жол]канал-аты формасында келтіреді; Нүкте локальді машинаны білдіреді; басқаша айтқанда алыстатылған машинада каналды құруға болмайды.
fdwOpenMode келесі мәндердің бірін қабылдайды:
PIPE_ACCESS_DUPLEX — GENERIC_READ және GENERIC_WRITE комбинацияларына эквивалентті;
PIPE_ACCESS_INBOUND — Мағлұматтардың бағыты тек клиенттен серверге, GENERIC_READ-ке эквивалентті;
PIPE_ACCESS_OUTBOUND — GENERIC_WRITE –қа эквивалентті.
Сонымен қатар тәртіп FILE_FLAG_WRITE_THROUGH (хабарлама каналдары үшін қолданылмайды) және FILE_FLAG_OVERLAPPED болуы мүмкін.
fdwPipeMode үш өзара жекелейтін жалаушылар жұптарын қабылдауы мүмкін. Олар жазбаның хабарламаға бағытталғанын немесе байттық екенін, хабарламам оқу бойынша немесе блок бойынша іске асырылатындығын және оқу операциясы бұғатталынатындығын көрсетеді.
өзара бір-бірін жоятын PIPE_TYPE_BYTE және PIPE_TYPE_MESSAGE, деректер каналға байт ағыны немесе хабарлама ағыны ретінде жазылатынын көрсетеді. Барлық каналдар үлгісіне бір тип қолданылады.
PIPE_READMODE_BYTE и PIPE_READMODE_MESSAGE деректер каналға байт ағыны немесе хабарлама ағыны ретінде оқылатынын көрсетеді. PIPE_READMODE_MESSAGE үшін PIPE_TYPE_MESSAGE қажет.
PIPE_WAIT және PIPE_NOWAIT определяют, будет ли ReadFile операциясы бұғатталатынын анықтайды. PIPE_WAIT мәнін көрсетіңіз, себебі асинхронды енгізу-шығарудың жақсырақ тәсілдері бар.
nMaxInstances канал үлгілерінің және бір уақытта қызмет көрсетілетінін клиеттер санын аныққтайды. Егер PIPE_UNLIMITED_ INSTANCES мәнін көрсетсек, каналдар саны ОЖ қатынас құруға рұқсат етілген жүйелік ресурстарға тәуелді анықтайды.
cbOutBuf және cbInBuf аныққталған каналдар үш енгізу-шығару буферінің өлшемін байтта береді. Егер нуль көрсетсек, үздікпен берілген мәндер қолжанылады.
dwTimeOut — WaitNamedPipe функция үшін үнсіздікпен қабылданған тайм-аут. Құрылыс функциясы басқа функция үшін тайм-аутты анықтайтын бұл жағдай уникалды болып табылады.
Қателік кеткен жағдайдағы қайтарылатын мән — INVALID_HANDLE_VALUE, себебі канал дескрипторлары файл дескрипторларына ұқсас.
lpsa басқа құрылу функцияларында сол рольді ойнайды.
CreateNamedPipe бірінші шақыру кезінде жай ғана үлгі құрылмайды, аталған канал құрылады. Үлгінің соңғы дескрипторын жапқан кезде үлгінің өзі өшіріледі. Аталған каналдың соңғы үлгісінің өшірілуі сол каналдың үлгісінің өшірілуі шақырылады.
Клиенттің аталған каналға қосылуы
Клиент аталған каналға канал атын көрсетумен CreateFile шақыру көмегімен қосыла алады. Көп жағдайларда клиент және сервер бір машинада орналасады. Сонда ат келесідей түр қабылдайды: \\.\pipe\[путь]имя_канала
Егер де сервер басқа машинада орналасқан болса, онда ат мынадай түр қабылдайды:
\\имя_сервера\pipe\[путь]имя_канала
Егер сервер локальді болса, онда машинаның өз атын көрсетудің орнына "." символын қолдану жылдам қозғалуды мейлінше көтереді.
Аталған каналдың күйлер функциясы
GetNamedPipeHandleState берілген ашық дескрипторға канал бұғаттаулы немесе бұғаттаулы емес тәртібінде орналасқандығы, оның хабарламаға немесе байттарға бағытталғандығы туралы, саны және тағы басқа мәлімдерді қайтарады.
SetNamedPipeHandleState программаға осы күйлер атрибутын беруді рұқсат етеді.
GetNamedPipelnfo дескриптор клиентпен немесе сервермен байланысын буфердің өлшемі қандай және тағы да басқа сұрақтарды анықтайды.
Аталған каналдың қосылу функциялары
ConnectNamedPipe функциясын қолдана отырып, аталған каналдың үлгісін құрудан кейін сервер клиенттің қосылуын бақылай алады.(CreateFile немесе CallNamedPipe функцияларының көмегімен)
BOOL ConnectNamedPipe ( HANDLE hNamedPipe,
LPOVERLAPPED lpo)
Егер lpo-ға NULL мәнін берсек, ConnectNamedPipe қосылуы пайда болған кезде тез арада аяққталады. Әдетте функция TRUE-ді қайтарады. Егер клиент CreateNamedPipe және ConnectNamedPipe функциясы серверлерінің арасындағы шақырулары қосылғанда, FALSE мәні болады. Бұл жағдайда GetLastError ERROR_PIPE_CONNECTED- тің мәнін қайтарады.
ConnectNamedPipe-тен қайтқаннан кейін сервер ReadFile көмегімен сұрақтарды оқи алады және WriteFile –ды қолдана отырып жауап жаза алады. Қорытындысына, басқа клиентпен байланыстыру мақсатында дескрипторды (канал үлгісі) босату үшін сервер DisconnectNamedPipe функциясын шақыру керек.
Соңғы функция WaitNamedPipe, клиент қосылуларының синхрондауы үшін қолдануға міндеттелген. Егер серверде ConnectNamedPipe-ке аяқталмаған байланыс болса, онда бұл функция аяқталады. WaitNamedPipe –ті қолдана отырып, клиент сервердің қосуға дайын екендігіне көзін жеткізе алады, осыдан кейін CreateFile-ды шақыра алады. Бұдан басқа серверлердің ConnectNamedPipe ты шақыруы бұл жағдайда сәттілікпен бітеді.
Аталған канал арқылы клиентпен және сервермен байланысу
Бірінші сервер тізбегінде клиент байланысты үзгенше қосылуды іске асырады, сосын сервер байланысты сервер жаққа жабады және басқа клиенттермен байланысады.
Ары қарай жұмысы аяқталғандағы клиент жабылуының тізбегі орныдалады. Жұмысты аяқтағанда клиент жабылады да, басқа клиентке каналдың сол аталған үлгісі арқылы қосылуға мүмкіндік береді. Егер клиентке сервер аты мәлім болса, клиент сервермен желі арқылы байланыса алады.
Назар аударыңыз, клиент пен сервер арасында жарыс болып тұрады. Біріншіден, егер сервер аталған канал құрмаса, WaitNamedPipe клиентінің шақыруы сәтсіздікпен аяқталады. Екіншіден, мынадай жағдай болуы мүмкін: сервер ConnectNamedPipe-ті шақырудан бұрын, клиент CreateFile өзінің шақыруын аяқтай алады . Бұндай жағдайда ConnectNamedPipe FALSE-ті қайтарады, бірақ міндеті бойынша, аталған каналы арқылы байланыс жұмыс істеп тұрады.
Аталған каналдың транзакциондық функциясы
Мыналарды клиент орындайды:
Серверге көпуақытты қосылу құру арқылы канал үлгісін ашады және осы үлгіні қолдана отырып;
Уақыт сайын сұраныс жібереді және жауабын күтеді;
Қосылуды жабады.
WriteFile, ReadFile қарапайым тізбекті функцияларды жеке клиент транзакциясы деп санауға болады және хабарлама каналдары үшін Win32-де осындай функциялар бар.
BOOL TransactNamedPipe ( HANDLE hNamedPipe, LPVOID lpvWriteBuf,
DWORD cbWriteBuf, LPVOID lpvReadBuf, DWORD cbReadBuf,
LPDWORD lpcbRead, LPOVERLAPPED lpa)
Міндеттелген өлшемдер түсініктемені қажет етпейді, себебі аталған канал дескрипторы үшін бұл функция WriteFile мен ReadFile файлдарының үйлесімдігін көрсетеді. Шығу буфері сияқты кіру буфері де көрсетіледі, ал * lpcbRead хабарламаның ұзындығын береді.
TransactNamedPipe функциясы ыңғайлы, бірақ клиент санын шектегендіктен, әрқашан қосылуын талап етеді.
CallNamedPipe, екінші функция-жартыфабрикат, мына жетіспеушіліктен айырылған, өйткені өзінде мына баолық тізбектерді біріктіреді: CreateFile, WriteFile, ReadFile, CloseHandle.
Әр сұраныс сайын қосылу қиыншылықтарына қарамастан, артықшылық әсері көбірек каналды қолдануында болады.
BOOL CallNamedPipe ( LPCPSTR lpszPipeName, LPVOID lpvWriteBuf,
DWORD сbWriteBuf, LPVOID lpvReadBuf, DWORD сbReadBuf,
LPDWORD lpcbRead, DWORD dwTimeOut)
Өлшемдерді пайдалану TransactactNamedPipe-тің жеке жағдайына ұқсас, мұнда канал үшін дескриптор емес, ат беріледі.
CallNamedPipe функциясы сихронды болып табылады.
Мұнда транзакцияға емес, қосылуға арналған миллисекундпен берілген тайм-аут көрсетіледі. dwTimeOut үшін үш әдейі келтірілген мән бар:
NMPWAIT_NOWAIT;
NMPWAIT_WAIT_FOREVER;
NMPWAIT_USE_DEFAULT_WAIT — бұл жағдайда тайм-аут үнсіздікпен қолданылады, CreateNamedPipe шақыруында берілгендей.
Аталған каналдағы хабарламаларды бақылау
ReadFile көмегімен аталған каналды оқудан басқа, онда санауға болатын хабарламаның қатысты ма екендігін анықтауға болады. Бұл үшін PeekNamedPipe функциясы жұмыс істейді.
BOOL PeekNamedPipe ( HANDLE hPipe, LPVOID lpvBuffer,
DWORD cbBuffer, LPDWQRD lpcbRead, LPDWORD lpcbAvail,
LPDWORD lpcbMessage)
PeekNamedPipe функциясы барлық байттарды немесе каналдағы хабарламаларды оқиды (оларды бұзбай); бұл функция бұғатталмайды және лезде аяқталады.
Каналда мағлұматтың бар екендігін білу үшін *lpcbAvail мәнін тексеріңіз; егер бар болса, *lpcbAvail нөлден жоғары болады. Бұл жағдайда lpvBuffer мен lpcbRead-те NULL мәнін иемдене алады. Егер буфер lpvBuffer мен cbBuffer параметрлерімен берілсе, онда, *lpcbMessage буферге жазылмайтын қалған хабарлама байттары бар ма екендігін абарлайды Байттық тәртіпте оның мәні нөлге тең.
Тағы да ескерте кетеміз, PeekNamedPipe хабарламаны жоймайды, сондықтан хабарламам немесе байтты каналдан өшіру үшін қосымша ReadFile шақыруы керек.
Аталған каналдың қауіпсіздігі
Аталған канал үшін төменде қауіпсіздіктің маңызды құқығы келтірілген.
GENERIC_READ.
GENERIC_WRITE.
SYNCHRONIZE (ағын күтуінің рұқсаты).
Мүмкіншілік тәртібінің тәуелділігінен лайықты құқық орнатылады. (дуплексті, кіріс немесе шығыс). Барлық үш тәртіп үшін SYNCHRONIZE құқығы қажет етіледі.
Пошталық ұяшықтар
Win32 пошталық ұяшықтың аты болады. Пошталық ұяшық өзімен кең тарамды механизмды ұсынады және атауған арналарға қарағанда өзін басқаша ұстанады. Маңызды бірақ аз жағдайларда оларды пайдалы етеді. Төменде пошталық ұяшытардың негізгі сипаттамалары келтірілген.
Пошталық ұяшық бірбағытты болады.
Пошталық ұяшықта бірнеше жіберушілер мен бірнеше қабылдаушылар болады, бірақ көбінесе бір жіберуші және бірнеше қабылдаушы болады немесе керісінше.
Хабарламаның ұзындығы шектеулі. Пошталық ұяшықтарды қолдану үшін бірқатар операцияларды орындау керек.
CreateMailslot көмегімен әр сервер (қабылдаушы) пошталық ұяшықта дескриптор құрады.
ReadFile шақыра отырып, сервер пошталық ұяшықтан хабарламаның түсуін күтеді.
Оқуға мүмкіншілігі жоқ клиент, CreateFile функциясымен пошталық ұяшықты ашуы керек және WriteFile көмегімен хабарлама жіберуі керек. Егер күтуші қабылдаушылары жоқ болса, онда ашылу операциясы сәтсіздікпен аяқталады (аты табылмайды).
Клиент хабарламалары барлық серверлермен оқылады; олардың бәрі сол хабарламан алады.
Тағы бір мүмкіндік бар. Клиент, CreateFile –ды шақыра отырып, пошталық ұяшықтың атын мына формада бере алады: \\*\maiIslot\пошталық_ұяшық_аты
Осылайша, * сиволы қойылатын белгінің ролін ойнайды және клиент желілік администратор жалпы ат енгізген желі тобының жүйесіне біріккен – домен атында әр серверді таба алады.
Пошталық ұяшықты ашу және құру
Пошталық ұяшықтың серверлері CreateMailslot функциясының көмегімен пошталық ұяшықтарды құрады және ReadFile –да қолдану үшін дескриптор алады. Жеке машиналар берілген атпен тек бір ғана пошталық ұяшық бола алады, алайда желідегі бірнеше жүйелер бір атты қолдана отырып, бірнеше қабылдаушылар пошталық ұяшықтардың артықшылықтарымен желідегі бірнеше жүйе қолдануға мүмкіндік береді.
HANDLE CreateMailslot ( LPCTSTR lpszName, DWORD cbMaxMsg,
DWORD dwReadTimeout, LPSECURITY__ATTRIBUTES lpsa)
Параметрлер
lpszName пошталық ұяшықтың атын \\.\mailslot\[путь]имя формада көрсетді.
Аты уникалды болуы керек. "." символы пошталық ұяшықтың ағындағы машинаға құрылғандығын көрсетеді.
cbMaxMsg – Клиент жібере алатын хабарламаның максималды өлшемі (байттарда). 0 шектеу жоқ екендігін көрсетеді.
dwReadTimeout – Оқу операциясын күтудегі ұзындық (миллисекундтарда). 0 мәні лездік қайтаруды білдіреді, ал MAILSLOT_WAIT_FOREVER – шексіз күту (тайм-аутсыз).
Қорытындысында клиент FILE_SHARE_READ жалауын көрсету керек.
GetMailslotInfo және SetMailslotInfo функцияларыаталған каналдар үшін өзінің аналогына ұқсас.
Негізгі әдебиет: 1 [237 - 324] , 2 [286 - 306]
Бақылау сұрақтары:
1. Анонимдік каналдардың көмегімен үрдістер арасындағы байланыс қалай орындалады?
2. Аталған каналдарды клиент пен сервер қалай қолданады?