Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lektsii_SPO_kaz_1.docx
Скачиваний:
70
Добавлен:
18.02.2016
Размер:
1.35 Mб
Скачать

Тақырып 8. Көпағындық бағдарламалау

Мақсаты: Көпағындық бағдарламалаудың ерекшеліктеріне талдау жасау

Кілттік сөздер: ағын, синхронизация, блокировка, модель, ядро, бірағынды үрдіс, көпағынды үрдіс, мултипроцессорлы архитектура

Дәріс жоспары (1 сағат)

  1. Sun фирмасының API орындалу ағындары және POSIX анықтамасы.

  2. Орындалу ағындары синхронизациясы: өзара шектеуші бұғаттар, шартты айнымалылар, барьерлер, оқу-жазуды бұғаттау (блокировка).

Бұл дәрісте ағын және көпағынды орындалу түсініктері; көпағынды модельдер; ядролардың ағындары және қолданушылық ағындар; "Эльбрусе", Solaris, Linux, POSIX, Windows 2000, Java ағындары туралы қарастырылған.

Көпағындық- бұл курстың маңызды және қызықты тақырыптарының бірі. Бұл тақырыптың маңыздылығы көпядролы процессорлардың пайда болуымен байланысты. Дәрісте мынандай сұрақтар қарастырылған:

Бірағынды және көпағынды үрдістер

Өкiнiшке орай, көп бағдарламалаушылардың бағдарлама әзiрлеуі бiртiндеп орындалады. Көпағындықты жеке алғанда қатар тұрудың кең мүмкіндіктері есепке алынбайды.

Біртіндеп орындалатын (бірағынды) үрдіс- бұл оның командалар есептеуiшiнiң өзгерiсін сипаттайтын бір басқару ағыны (control flow) болытын үрдіс. Ағын (thread ) - параллелді орындалатын ерекше үрдіс.Ол ата-аналық үрдістің адрестік кеңістігінде орындалады.

Сурет.1  Бірағынды және көпағынды үрдіс

Схемада бір ағынды үрдіс өзі жұмыс істейтін негізгі жады мен файлдардың кодын қолданады. Үрдіс сонымен қатар процедураларда орындалатын регистрлерді және стектерді қолданады. Көпағынды үрдіс біршама күрделі ұйымдастырылған. Ол кез-келген ОЖ үшiн өз стегiн құратын және регистрлердiң мәнiн меншiктi сақтайтын бiрнеше параллел ағындардан тұрады. Ағындар жалпы негізгі жадыда жұмыс істейді және ата-аналық үрдістер қолданатын адрестік кеңістікте пайдаланады, сонымен қатар үрдіс және файл кодтарын бөледі.

Көпағындықтың артықшылықтары:

  • Жылдамдықтың артуы ( қарапайым үрдістермен салыстырғанда) Көпағындылық виртуалды жадының жалпы кеңістігінде орындалатын жеңілдетілген үрдістерді (lightweight processes)қолдануға негізделген. Көпағындалықтың арқасында UNIX ОЖ-ге тән тиімді емес жағдайлар болмайды.Әрбір shell командасы жеке үрдіс ретінде өзінің жеке адрестік кеңістігінде орындалады.Жеңілдетілген үрдістерге қарама қарсы үрдістерді ауырсалмақты (heavyweight) үрдістер деп атайды.

  • Жалпы ресурстарды қолдау. Бір үрдістің ағындары жалпы жады мен файлды қолданады.

  • Үнемдеу. Көпағындықтың арқысында жадыны үнемдеуге болады.Сонымен қатар қарапайым үрдіске қарағанда контекстерді жеңілдетілген үрдістерге ауыстыру үшін қажет стектерді алмастыру және регистрлердің мәнін қалпына келтіру тез орындалады.

Мултипроцессорлы архитектураны қолдану. Бұл көп ядролық гибридты және көп процессорлық жүйелердiң кең қолдануының мерзiмiнде маңызды. Көпядролы үрдістердің негізіндегі бағдарламалардың көпағындылығы параллелді орындалудың нақты артықшылықтарын көрсетеді.

Көпағындылықтың тарихы

Көпағындылықты қолданудың алғашқы шарттары 1970-ші жылдарда кеңестік компьютерлік аппаратураны құрастырушылар мен бағдарламашылар көмегімен жасалған. 1979 жылы құрылған "Эльбрус-1" аппаратурасында және операциялық жүйеде үрдістің тиімді тұжырымдамасын қолданды. "Эльбрусе" үрдісінде көбінесе өзінің стектерімен сипатталды. "Эльбрусе" үрдісінде басқа үрдістер болмағандықтан виртуалды жадының жалпы кеңістігінде орындалады және жеңілдетілген үрдістер болады.

Көпағындылықтың тұжырымдамасы 1980 жылдары UNIX операциялық жүйесінде және оның диалектерінде қалыптаса бастады. Көпағындылықтың дамуы AT&T фирмасындағы UNIX диалектісінде болды, оның негізінде Solaris жүйесі құрылды. Бұның барлығы POSIX стандартында UNIX-тің негізгі мүмкіндіктерімен көрсетілді.

1990 жылдардың ортасында көпағындылық қосылған ОС Windows NT шығарылды.

API жүйесіндегі әртүрлі операциялық жүйелердің көпағындылығы ерекше болды. Сондықтан да, жоғары деңгейлі тілдерде жазылған көпағынды бағдарламалар бір платформадан басқа платформаға ауыспайтындықтан ыңғайсыз болды.

Спецификацияның ерекшеліктеріне және әр түрлі жүйелерде көпағындылықтың іске қосылу себептеріне байланысты Бьярн Страуструп өзі құрған C++ тіліне көпағындылықты қоспады, бірақ оның кітапханасының базалық негізін құрады. С++тіліндегі бағдарламашылар нақты операциялық жүйелердің кітапханасында және жүйелік шақыртулар деңгейінде қолданды.

1995 жылдары шығарылған Java және Java-технологиясының авторлары маңызды алға қадам жасады. Java-да алғаш рет көпағындылық базалық кітапханалар және тілдің конструкторлық деңгейінде іске асырылды. Java-да арнайы әдістер және тілдің конструкциясы түрінде ұсынылған ағын және операция -Thread классы енгізілген.

2000 жылы пайда болған NET платформасы Java идеясын дамытушы механизмін ұсынды.

Әртүрлі операциялық жүйелерде және әртүрлі платформаларда көпағындылық бағдарламаларды құрастыру қазіргі уақыттқа дейін сақталады. Қолданбалы бағдарламалар үшін Java және .NET платформаларында көпағындылықты іске асыруды ұсынады. Ол жоғары дегейлі түсініктер мен конструкцияларды қолдануға мүмкіндік береді. Бірақ, операциялық жүйеге арналған курсымызда көпағындылықтың жүйелік сұрақтарына және операциялық жүйелерде іске асуына көп көңіл бөлеміз.

Қолданушылық ағын және ядролардың ағындары

Көпағындылықтың моделі. Операциялық жүйеде көпағындылықтың іске асуы бірнеше абстракцияның деңгейлерінен тұрады. Қолданушының көзқарасы бойынша оның бағдарламасын басқару қолданушылық деңгей ағындарының кітапханасы (user threads) арқылы жүзеге асады. Нақты операциялар жайлы кейінірек қарастырамыз. Қазір ағындардың қолданушылық деңгейлеріндегі моделдерін қарастырамыз:

POSIX Pthreads – POSIX стандартымен спецификацияланған ағындар және POSIX қосымшаларында қолданылады.

Mac C-threads –MacOS жүйесіндегі қолданушылық ағындар;

Solaris threads –Solaris операциялық жүйесіндегі қолданушылық ағындар.

Қолданушыық ағындар көрсетілетін төмен деңгейлі ағындар- ядро ағыны (kernel threads) деп аталады. Олар операциялық жүйеның ядро деңгейінде қолданылады. Әртүрлі операциялық жүйелерде қолданушылық ағындардың жүйеде бейнеленуі әр түрлі. Мысалы, келесі операциялық жүйелерде өзінің спецификациясымен ядро ағынының моделдері іске сады:

  • Windows 95/98/NT/2000/XP/2003/2008/7;

  • Solaris;

  • Tru64 UNIX;

  • BeOS;

  • Linux.

Көп деңгейліктің бірнеше моделдері бар- ядро ағынында қолданушылық ағындарды бейнелеу тәсілдері. Көпағындылықтың келесі моделдері орындалуы мүмкін:

- көп/ бір моделі (many-to-one) – бірнеше қолданушылық ағындарды ядроның ағындардың біреуінде көрсетіледі. Бұл модель көп жүйелік ағындары жоқ операциялық жүйелерде қоданылады.

Аталған модель келесі суретте көрсетілген.

Сурет 2. Көпағындылықтың «көп/бір» моделінің схемасы

- бір/бір моделі – әрбәр анықталаған ядро ағынында қолданушылық ағынды біресепті көресетілуі. Осы модельді қолданатын операциялық жүйелер:Windows 95/98/NT/2000/XP/2003/2008/7; OS/2.

Аталған модель келесі суретте көрсетілген

Сурет 3. Көпағындылықтың « бір/бір» моделінің схемасы

- Көп/көп моделі (many-to-many) – бірнеше қолданушылық ағындарды бірнеше жүйелік ағындарда көрсетеді. Бұндай модель операциялық жүйеде көп жүйелік ағындарды құрады. Аталған моделді қолданатын операциялық жүйелерге мысал: Solaris, Windows NT / 2000 / XP / 2003 / 2008 / 7 ThreadFiber пакеттерімен

Бұл модель Сурет 4-те көрсетілген

Сурет 4. Көпағындылықтың «көп/көп» моделінің схемасы

Көпағындылықтың мәселесі

Көпағындылық- өте күрделі,себебі әлі толық зерттелмеген әрі толық қалыптаспаған аймақ және көптеген маңызды мәселелері бар. Солардың кейбіреуін қарастырып өтейік.

fork() және exec()жүйелік шақыртулардың семантикасы. Классикалық UNIX операциялық жүйесінде fork жүйелік шақыртуы өзінің адрестік кеңістігі бар ауырсалмақты үрдіс құрады. Бірақ, төменнен жоғарыға қарай бағдарламалардың сәйкестігін қолдау мақсатында осы семантиканы сақтау қажет, ал көпағындық болса, жаңа жүйелік шақырту көмегімен енгізіледі.

Ағындар жұмысын тоқтату. Маңызды мәселелердің бірі ағындар жұмысын тоқтату болып табылады. Мысалы: Егер ата-аналық ағын тоқатылса, оған тәуелді ағын тоқтытылу қажет пе? Егер бірнеше ағынды құратын стандартты ағын тоқтатылса, оның барлық ағындары тоқтатылу керек пе? Осы сұрақтардың жауабы барлық операциялық жүйелерде әртүрлі.

Сигналдарды өңдеу. UNIX операциялық жүйесінің сигналы- қателік жағдайларындағы төмендеңгейлі механизмдерді өңдеу. Сигналдарға мысал: SIGSEGV- сегменттің бұзылуы, SIGKILL- kill командасын орындау және жою үрдісінің сигналы.

Қолданушы signal жүйелік шақыртуы арқылы өзінің өңдеуші-процедура сигналын анықтайды. Бұның мәселесі мынада: көпағынды бағдарламада сигналдар қалай таралады және олар қандай ағын арқылы өңделеді?

Көп жағдайларда бұл сұрақ былай шешіледі: сигналгенерацияланған ағын арқылы өңделеді және осы ағынның орындалуына әсер етеді.

Қазіргі кездегі объектілі-бағытталған операциялық жүйелерде сигнал тұжырымдамасы жоғары деңгейлі ерекшелік (исключения) (exception) тұжырымдамасымен алмастырылған. Ерекшелік тәртіп бойынша ағындардың стегімен таралады. Ерекшелікті өңдеудің ұқсастық моделі Java және .NET жүзеге асырылған.

Ағындар топтары. Мысалы мынандай күрделі есептерде : әртүрлі ағындар анында моделдеу есебінінің құрылымдау және ағындар тобының тұжырымдамасын қажет етеді. Ағындар тобы- топтық операциялары анықталған және аты бар ағындардың жиыны. Ағындардың тобы алғаш рет Java-да іске қосылған. NET-те ағындардың пулын (ThreadPool) тиімді қосылуын атап өту қажет.

Ағындардың жергілікті деректері (thread-local storage - TLS)- бір ғана ағынға тән және осы ағында қолданылатын деректер. Осы деректердің көпағындылықта қажеттілігі – күрделі есепті шешетін параллелді әдістің бірі, онда әрбір ағын берілген бөлікті шешуде жұмыс істейді. Қазіргі операциялық жүйелер және платфорламалардың барлығы ағындар деркетірінің жергілікті тұжырымдамасын қолдайды.

Ағындарды синхрондау. Барлық ағындар үрдістер сияқты жалпы ресурстарды қолдана алады және жалпы оқиғаға әсер етеді.

Тығырық (тығырық) және оларды жою жолдары. Ағындар үрдістер сияқты бір-бірін бұғаттай( блокровка) алады.

POSIX (Pthreads) ағындары

Көпағындылықтың нақты моделі ретінде POSIX ағынын қарастырамыз. POSIX-тегі көпағындылық ағындарды құратын және синхрондауға арналған API –ді сипаттайтын IEEE 1003.1c стандартымен спецификацияланған. POSIX стандарты ағындардың кітапхана тәртібін анықтайды.

Ағындарды іске қосу автордың қалауынша POSIX сәйкестік кітапханасын таңдауымен жүзеге асады. POSIX ағындары UNIX операциялық жүйесінде кең таралған және Solaris және Windows NT операциялық жүйелерінде де қолданылады.

POSIX стандарты ағындар үшін деректердің екі типін анықтайды:

pthread_t – ағындар дескрипторы; pthread_attr_t – ағындардың атрибуттар жиынтығы.

POSIX стандарты ағындарды басқару келесі функциялар жиынтығымен спецификацияланады:

  • pthread_create():ағынды құру

  • pthread_exit(): ағынды аяқтау

  • pthread_cancel(): ағынды болдырмау

  • pthread_join(): келесі ағын тоқтағанға дейін ағынның орындалуын бұғатау.

  • pthread_detach(): ағындар орын алатын ресурстарды босату pthread_attr_init(): ағындар атрибуттарының құрылымын инициализациялау

  • pthread_attr_setdetachstate(): ағын аяталғаннан кейін ол автоматты түрде ресурстарды босатуды жүйеде көрсетеді.

  • pthread_attr_destroy(): ағын атрибуттарын жадыдан босатады.

POSIX ағынын синхрондаудың мынандай примитивтері бар:мюьтекстер (mutexes) – семафора ұқсастықтары және шартты айнымалылар (conditional variables)

  • pthread_mutex_init() –мюьтексті құру;

  • pthread_mutex_destroy() – мюьютексті жою;

  • pthread_mutex_lock() –мюьтексті аяқтау;

  • pthread_mutex_trylock() – мюьтексті алдын-ала жабу

  • pthread_mutex_unlock() – мюьтексті ашу;

  • pthread_cond_init() – шартты айнымалыларды құру;

  • pthread_cond_signal() – шартты айнымалыларды бұғаттау;

  • pthread_cond_wait() – шартты айнымалы бойынша күту.

Си тілінде POSIX ағындарын қолдану мысалын қарастырайық .

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <pthread.h>

static void wait_thread(void)

{

time_t start_time = time(NULL);

while (time(NULL) == start_time)

{

// никаких действий, кроме занятия процессора на время до 1 с.

}

}

static void *thread_func(void *vptr_args)

{ int i;

for (i = 0; i < 20; i++) {

fputs(" b\n", stderr);

wait_thread();

}

return NULL;

}

int main(void)

{ int i;

pthread_t thread;

if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {

return EXIT_FAILURE;

}

for (i = 0; i < 20; i++) {

puts("a");

wait_thread();

}

if (pthread_join(thread, NULL) != 0) {

return EXIT_FAILURE;

}

return EXIT_SUCCESS;

}

Бұл мысалда негізгі ағынның параллелді орындалуын иллюстрациялайды. Ағындарды құруға (pthread_create), оның денесін көрсетуге (thread_func) және тән ағынның аяқталуын күтуге (pthread_join) ерекше көңіл бөлген жөн.

Solaris операциялық жүйесінің ағындары мен үрдістері

Solaris операциялық жүйесінде көп/көп ағындар моделі қолданылады. Сонымен қатар бұл жүйеде жеңілдетілген үрдістер пайдаланылады. Solaris операциялық жүйесінде қолданушылық ағын өзінің жеңілдетілген үрдісінде бейнеленіледі, өз кезегінде ядро ағынында бейнелінеді, соңғысы компьютерлік жүйенің кез-келген үрдісінде орындалады.

Сурет 5. Solaris ағындарын ұйымдастыру схемасы

Сурет 6. Solaris операциялық жүйесінде үрдістерді ұйымдастыру

Суретте көргеніміздей әрбір үрдіс үрдістерді басқару ақпараттық блогынының стандартынан басқа өзінің жеңілдетілген үрдістерінің тізімінен тұрады.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]