А.В. Столяров - Введение в операционные системы (1152218), страница 38
Текст из файла (страница 38)
Âñå ôóíêöèè âîçâðàùàþò 0 â ñëó÷àå óñïåõà, ëèáî íåíóëåâîé êîäîøèáêè, ïðè÷åì â ñëó÷àå, åñëè pthread_mutex_trylock() ïðèìåíÿåòñÿ ê çàêðûòîìó ìüþòåêñó, îíà âîçâðàùàåò êîä EAGAIN.Ìüþòåêñ ìîæíî óíè÷òîæèòü âûçîâîì ôóíêöèèint pthread_mutex_destroy(pthread_mutex_t *mutex);êîòîðàÿ âûñâîáîäèò èñïîëüçóåìûå ìüþòåêñîì ðåñóðñû, åñëè òàêîâûå åñòü (çàìåòèì, â ðåàëèçàöèè ìüþòåêñîâ â ÎÑ Linux âåñü ìüþòåêñ öåëèêîì óìåùàåòñÿâ ïåðåìåííîé pthread_mutex_t, òàê ÷òî âûñâîáîæäàòü îêàçûâàåòñÿ íå÷åãî).Íà ìîìåíò óíè÷òîæåíèÿ ìüþòåêñà îí äîëæåí íàõîäèòüñÿ â ñîñòîÿíèè îòêðûò, èíà÷å ôóíêöèÿ âåðíåò îøèáêó.29.4POSIX-ñåìàôîðûÊàê óæå ãîâîðèëîñü, ñåìàôîðû â ñòàíäàðòå POSIX èçíà÷àëüíî ðàñ÷èòàíûíà âçàèìîäåéñòâèå íåñêîëüêèõ ïðîöåññîâ, â òîì ÷èñëå, âîçìîæíî, íåðîäñòâåí175íûõ. Îäíàêî íåêîòîðûå ñóùåñòâóþùèå ðåàëèçàöèè POSIX-ñåìàôîðîâ (âêëþ÷àÿ, íàïðèìåð, ðåàëèçàöèþ â ÎÑ Linux) äîïóñêàþò èñïîëüçîâàíèå POSIXñåìàôîðîâ òîëüêî â ðàìêàõ îäíîãî ïðîöåññà äëÿ âçàèìîäåéñòâèÿ ïîòîêîâ. êà÷åñòâå ñåìàôîðà èñïîëüçóåòñÿ ïåðåìåííàÿ òèïà sem_t (POSIX ïðåäïîëàãàåò, ÷òî ýòî ìîæåò áûòü ñëîæíàÿ ñòðóêòóðà äàííûõ, íî â ðåàëèçàöèèpthreads â ÎÑ Linux ýòî ïðîñòàÿ öåëî÷èñëåííàÿ ïåðåìåííàÿ, õîòÿ è íå ðàâíàÿçíà÷åíèþ ñåìàôîðà, ïîñêîëüêó ñîäåðæèò ñëóæåáíóþ èíôîðìàöèþ).Èíèöèàëèçàöèÿ ñåìàôîðìà ïðîèçâîäèòñÿ ôóíêöèåéint sem_init(sem_t *sem, int pshared, unsigned int value);Ïàðàìåòð sem çàäàåò àäðåñ èíèöèàëèçèðóåìîãî ñåìàôîðà.
Ïàðàìåòð psharedóêàçûâàåò, áóäåò ëè ñåìàôîð äîñòóïåí äëÿ äðóãèõ ïðîöåññîâ; â ðåàëèçàöèÿõ,êîòîðûå íå ïîääåðæèâàþò òàêóþ ôóíêöèîíàëüíîñòü ñåìàôîðîâ, îí äîëæåíáûòü ðàâåí íóëþ. Íàêîíåö, ïàðàìåòð value çàäàåò íà÷àëüíîå çíà÷åíèå ñåìàôîðà.Êàê ìû ïîìíèì, ñåìàôîð, ïî îïðåäåëåíèþ, åñòü îáúåêò, âíóòðåííåå ñîñòîÿíèå êîòîðîãî ïðåäñòàâëÿåò ñîáîé íåîòðèöàòåëüíîå öåëîå ÷èñëî, è íàä êîòîðûì îïðåäåëåíû äâå îïåðàöèè: up() è down(). Ïåðâàÿ èç íèõ óâåëè÷èâàåòçíà÷åíèå ñåìàôîðà íà 1 è íåìåäëåííî âîçâðàùàåò óïðàâëåíèå. Âòîðàÿ, åñëè çíà÷åíèå ñåìàôîðà ðàâíî íóëþ, áëîêèðóåò âûçâàâøèé ïðîöåññ èëè ïîòîêäî òåõ ïîð, ïîêà êòî-òî äðóãîé íå óâåëè÷èò çíà÷åíèå ñåìàôîðà (åñëè çíà÷åíèå èçíà÷àëüíî íåíóëåâîå, áëîêèðîâêè íå ïðîèñõîäèò), ïîñëå ÷åãî óìåíüøàåòçíà÷åíèå ñåìàôîðà íà 1 è âîçâðàùàåò óïðàâëåíèå.Äëÿ ñåìàôîðîâ POSIX ñîîòâåòñòâóþùèå îïåðàöèè âûïîëíÿþòñÿ ôóíêöèÿìèint sem_post(sem_t *sem);int sem_wait(sem_t *sem);/* up()*//* down() */Òàêæå èìååòñÿ íåáëîêèðóþùèé âàðèàíò îïåðàöèè down():int sem_trywait(sem_t *sem); ñëó÷àå, åñëè ñåìàôîð íà ìîìåíò âûçîâà èìååò çíà÷åíèå 0, ýòà ôóíêöèÿ,âìåñòî òîãî ÷òîáû áëîêèðîâàòü âûçâàâøèé ïðîöåññ, íåìåäëåííî çàâåðøàåòñÿ,âîçâðàòèâ çíà÷åíèå EAGAIN.Ïðè íåîáõîäèìîñòè ìîæíî óçíàòü òåêóùåå çíà÷åíèå ñåìàôîðà ñ ïîìîùüþôóíêöèèint sem_getvalue(sem_t *sem, int *sval);Çíà÷åíèå ñåìàôîðà âîçâðàùàåòñÿ ÷åðåç ïàðàìåòð sval.Íàêîíåö, óíè÷òîæèòü ñåìàôîð ìîæíî âûçîâîì176int sem_destroy(sem_t *sem);Ïðè ýòîì íå äîëæíî áûòü íè îäíîãî ïîòîêà, íàõîäÿùåãîñÿ â ñîñòîÿíèèîæèäàíèÿ íà ýòîì ñåìàôîðå, òî åñòü âûïîëíÿþùåãî â íàñòîÿùèé ìîìåíòsem_wait() ñ òåì æå ïàðàìåòðîì, ÷òî è sem_destroy().
Îòìåòèì, ÷òî â ðåàëèçàöèè ÎÑ Linux ýòà ôóíêöèÿ íå äåëàåò íè÷åãî, êðîìå ïðîâåðêè, íå íàõîäèòñÿ ëè êòî-ëèáî â ðåæèìå îæèäàíèÿ íà çàäàííîì ñåìàôîðå.29.5ÏðèìåðÐàññìîòðèì çàäà÷ó, â êîòîðîé íàì ïîòðåáóåòñÿ ðåàëèçîâàòü âçàèìîèñêëþ÷åíèå âèäà ïðîèçâîäèòåëè-ïîòðåáèòåëè.Ïóñòü äàíû íåñêîëüêî èñòî÷íèêîâ äàííûõ, èç êîòîðûõ ïîñòóïàþò â òåêñòîâîì âèäå ÷èñëà ñ ïëàâàþùåé òî÷êîé.  ðîëè èñòî÷íèêîâ ìîãóò âûñòóïàòü îáû÷íûå ôàéëû, à òàêæå ñîêåòû, FIFO èëè ñèìâîëüíî-îðèåíòèðîâàííûåóñòðîéñòâà, òî åñòü ïðî÷èòàòü ïîñëåäîâàòåëüíî ñíà÷àëà îäèí èñòî÷íèê, ïîòîìäðóãîé è ò.ï.
íåëüçÿ.Ïîëó÷àåìûå èç èñòî÷íèêîâ ÷èñëà íóæíî ïîäâåðãíóòü îïðåäåëåííîé îáðàáîòêå: âû÷èñëèòü äëÿ êàæäîãî ÷èñëà íàòóðàëüíûé ëîãàðèôì, à ðåçóëüòàòó÷åñòü òàêèì îáðàçîì, ÷òîáû â êàæäûé ìîìåíò âðåìåíè ìîæíî áûëî âûäàòü ñðåäíåå àðèôìåòè÷åñêîå âû÷èñëåííûõ çíà÷åíèé (äëÿ ýòîãî äîñòàòî÷íî,íàïðèìåð, õðàíèòü ñóììó âñåõ ðåçóëüòàòîâ è èõ îáùåå êîëè÷åñòâî).Âû÷èñëåíèå ëîãàðèôìîâ ñàìî ïî ñåáå ÿâëÿåòñÿ çàäà÷åé, òðåáóþùåé ïðîöåññîðíîãî âðåìåíè. Äîïóñòèì, â íàøåé ñèñòåìå ìîæåò áûòü íåñêîëüêî ôèçè÷åñêèõ ïðîöåññîðîâ, òàê ÷òî ïðèìåíåíèå ïàðàëëåëüíûõ ïîòîêîâ ìîæåò óñêîðèòü îáðàáîòêó. Âìåñòå ñ òåì, íåèçâåñòíî, ñ êàêèìè ñêîðîñòÿìè áóäóò ïîñòóïàòü ÷èñëà îò èñòî÷íèêîâ, ïðè÷åì, âîçìîæíî, ýòè ñêîðîñòè îêàæóòñÿ ñóùåñòâåííûì îáðàçîì íåïîñòîÿííû.  ðåçóëüòàòå ïðîöåññîðû ìîãóò îêàçàòüñÿ÷àñòü âðåìåíè ïåðåãðóæåíû ðàáîòîé (÷òî ïðèâåäåò ê çàäåðæêàì â ïðèåìåäàííûõ îò èñòî÷íèêîâ), à ÷àñòü âðåìåíè − ïðîñòàèâàòü. ×òîáû ñãëàäèòü ýòèýôôåêòû, ìîæíî èñïîëüçîâàòü åäèíûé áóôåð äàííûõ äîñòàòî÷íîé âìåñòèìîñòè.Ðåàëèçóåì çàäà÷ó â ìíîãîïîòî÷íîé ñõåìå, âûäåëèâ ïî îäíîìó ïîòîêó íà÷òåíèå êàæäîãî èñòî÷íèêà äàííûõ è çàïóñòèì N ïîòîêîâ äëÿ îáðàáîòêè äàííûõ (ëîãàðèôìèðîâàíèÿ è ñóììèðîâàíèÿ).
Ïåðåäàâàòü äàííûå îò ïåðâûõ êïîñëåäíèì áóäåì ÷åðåç îáùèé áóôåð ïî ñõåìå ïðîèçâîäèòåëè-ïîòðåáèòåëè.Ïîñêîëüêó ñóììèðîâàíèå ïðèäåòñÿ âåñòè â îáùèõ ïåðåìåííûõ, äîñòóï êíèì íåîáõîäèìî îãðàíè÷èòü ìüþòåêñîì. ×òîáû óìåíüøèòü ïîòåðè íà îæèäàíèå ïîòîêàìè îñâîáîæäåíèÿ ýòîãî ìüþòåêñà, áóäåì íàêàïëèâàòü äàííûå âëîêàëüíûõ ïåðåìåííûõ ïîòîêà, à äîñòóï ê ãëîáàëüíîé ñóììå îñóùåñòâëÿòü ïî177íåáëîêèðóþùåìó ïðèíöèïó: åñëè çàõâàòèòü ìüþòåêñ óäàëîñü, ñáðàñûâàåì íàêîïëåííûå äàííûå, èíà÷å ðàáîòàåì äàëüøå, íàêàïëèâàÿ äàííûå â ëîêàëüíîìñóììàòîðå.Èìåíà ôàéëîâ èñòî÷íèêîâ ïîëó÷èì ñ êîìàíäíîé ñòðîêè. ×òîáû ðàáîòàòü ñïðîãðàììîé áûëî èíòåðåñíåå, ñäåëàåì òàê, ÷òîáû ãëàâíàÿ ïðîãðàììà êàæäûåïÿòü ñåêóíä âûäàâàëà çíà÷åíèå ñóììû è âû÷èñëåííîãî ñðåäíåãî, à ñ÷åò÷èêèîáíóëÿëà.Íàêîíåö, ïî ìåðå èñ÷åðïàíèÿ èñòî÷íèêîâ (ïî ïîëó÷åíèè êîíöà ôàéëà)áóäåì çàâåðøàòü ïîòîêè-ïðîèçâîäèòåëè.
ßñíî, ÷òî ïî çàâåðøåíèè ïîñëåäíåãî ïðîèçâîäèòåëÿ äàëüíåéøàÿ ðàáîòà ïðîãðàììû òåðÿåò ñìûñë. Ñîîòâåòñòâåííî, ïðåäóñìîòðèì ìåõàíèçì ïîäñ÷åòà îñòàâøèõñÿ ïðîèçâîäèòåëåé.×òîáû íå âîçèòüñÿ ñ ìüþòåêñîì è ãëîáàëüíîé ïåðåìåííîé, âîñïîëüçóåìñÿîáûêíîâåííûì ñåìàôîðîì; â ýòîì ñëó÷àå áóäåì èñïîëüçîâàòü ñåìàôîð èñêëþ÷èòåëüíî ðàäè àòîìàðíîñòè äåéñòâèé íàä íèì, áåç áëîêèðîâîê.Ïîëíîñòüþ ïðîãðàììà ïðèâåäåíà â ëèñòèíãå íà ñòð. 179−181.×òîáû îïðîáîâàòü ïðîãðàììó, ñîçäàéòå íåñêîëüêî èìåíîâàííûõ êàíàëîâñ ïîìîùüþ êîìàíäû mkfifo. Çàïóñòèâ íåñêîëüêî ïðîãðàìì xterm, ñîçäàéòå ïðîöåññû, ÷èòàþùèå ñ êëàâèàòóðû è ïèøóùèå â òîëüêî ÷òî ñîçäàííûåèìåíîâàííûå êàíàëû.
Ýòî ïðîùå âñåãî ñäåëàòü ñ ïîìîùüþ êîìàíäû cat è ïåðåíàïðàâëåíèÿ âûâîäà.  îòäåëüíîì îêíå çàïóñòèòå íàøó ïðîãðàììó, óêàçàâåé èìåíà âàøèõ êàíàëîâ â êîìàíäíîé ñòðîêå. Òåïåðü ìîæíî ââîäèòü ÷èñëàíà âõîä ïðîãðàììàì cat; íàøà ïðîãðàììà áóäåò èõ îáðàáàòûâàòü.178#include#include#include#include#include<stdio.h><unistd.h><pthread.h><semaphore.h><math.h>#define BUFFER_SIZE 4096/* Áóôåð îáìåíà ìåæäó ïðîèçâîäèòåëÿìè è ïîòðåáèòåëÿìè */struct buf_str {int count;double values[BUFFER_SIZE];} buffer;void init_buffer(){buffer.count = 0;}void put_buffer_item(double v){buffer.values[buffer.count] = v;buffer.count++;}double get_buffer_item(){buffer.count--;return buffer.values[buffer.count];}/* ñåìàôîðû è ìüþòåêñ äëÿ îðãàíèçàöèè ðàáîòû ñ áóôåðîì */sem_t buf_empty;sem_t buf_full;pthread_mutex_t buf_mutex = PTHREAD_MUTEX_INITIALIZER;/* ïåðåìåííûå äëÿ ñóììèðîâàíèÿ è ìüþòåêñ äëÿ èõ çàùèòû */double grand_total = 0;long grand_count = 0;pthread_mutex_t grand_mutex = PTHREAD_MUTEX_INITIALIZER;/* ñåìàôîð äëÿ ïîäñ÷åòà îñòàâøèõñÿ "ïðîèçâîäèòåëåé" */sem_t producers_count;179/* Ïîòîê äëÿ ÷òåíèÿ äàííûõ ("ïðîèçâîäèòåëü") */void *producer_thread(void *v){/* ïîëó÷àåì â v óêàçàòåëü íà èìÿ èñòî÷íèêà */double val;FILE *f = fopen((char*)v, "r");if(!f) return NULL;sem_post(&producers_count);while(!feof(f)) {if(1 != fscanf(f, "%lf", &val)) continue;sem_wait(&buf_empty);/* àëãîðèòì ïðîèçâîäèòåëÿ */pthread_mutex_lock(&buf_mutex);put_buffer_item(val);pthread_mutex_unlock(&buf_mutex);sem_post(&buf_full);/*------*/}sem_trywait(&producers_count);return NULL;}/* Ïîòîê-ïîòðåáèòåëü.
Ïîëó÷àåìîå âõîäíîå çíà÷åíèå èãíîðèðóåò */void *consumer_thread(void *ignored){double local_total = 0; /* ëîêàëüíûå ñóììàòîðû */long local_count = 0;for(;;) {double val;sem_wait(&buf_full);/* àëãîðèòì ïîòðåáèòåëÿ */pthread_mutex_lock(&buf_mutex);val = get_buffer_item();pthread_mutex_unlock(&buf_mutex);sem_post(&buf_empty);/*------*//* òåïåðü ìîæíî çàíÿòüñÿ âû÷èñëåíèÿìè */local_total += log(val); local_count++;/* åñëè åñòü âîçìîæíîñòü, ñáðàñûâàåì äàííûå */if(0==pthread_mutex_trylock(&grand_mutex)) {grand_total += local_total;grand_count += local_count;local_total = 0; local_count = 0;pthread_mutex_unlock(&grand_mutex);}}}180int main(int argc, char **argv){pthread_t thr;int i;/* èíèöèàëèçèðóåì ãëîáàëüíûå äàííûå */init_buffer();sem_init(&buf_empty, 0, BUFFER_SIZE);sem_init(&buf_full, 0, 0);sem_init(&producers_count, 0, 0);/* çàïóñêàåì "ïðîèçâîäèòåëåé" */for(i = 1; i<argc; i++)pthread_create(&thr, NULL, producer_thread, (void*)argv[i]);/* çàïóñêàåì "ïîòðåáèòåëåé" */for(i = 0; i<10; i++)pthread_create(&thr, NULL, consumer_thread, NULL);}/* òåïåðü êàæäûå 5 ñåêóíä ïå÷àòàåì è îáíóëÿåì ðåçóëüòàò */for(;;) {int p_c;sleep(5);pthread_mutex_lock(&grand_mutex);/* âî èçáåæàíèå äåëåíèÿ íà 0 ïðîâåðèì íàëè÷èå äàííûõ */if(grand_count>0) {printf("total average: %f (sum = %f; count = %ld)\n",grand_total/((double)grand_count),grand_total, grand_count);} else {printf("No data yet...\n");}grand_total = 0; grand_count = 0;pthread_mutex_unlock(&grand_mutex);sem_getvalue(&producers_count, &p_c);if(p_c == 0) {printf("No more producers\n");break;}}return 0;181Ëåêöèÿ 1530Ãðàôè÷åñêèé èíòåðôåéñ â ÎÑ Unix.