Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Очікування|чекання| завершення роботи потоку




#include <pthread.h>

int pthread_join (pthread_t thread, void **status_addr);

Функція pthread_join блокує роботу потоку, що викликав|спричинив| його, до завершення, вказаного як параметр потоку. Після|потім| розблокування в покажчик, розташований|схильний| за адресою status_addr, заноситься адреса, яка повернула той, що завершився thread або при виході з|із| асоційованої з|із| ним функції, або при виконанні функції pthread_exit(). Якщо нас не цікавить, що повернув нам потік, цього параметра можна використовувати як значення NULL.

Функція повертає значення 0 при успішному завершенні. У разі|в разі| помилки повертається позитивне значення (а не негативне|заперечне|, як в більшості системних викликів і функцій!), яке визначає код помилки, описаний у файлі <errno.h>. Значення системної змінної errno при цьому не встановлюється.

struct char_print_params

{

char character;

int count;

};

void *char_print(void *params)

{

struct char_print_params *p = (struct char_print_params *) params;

int i;

for (i = 0; i < p->count; i++)

fputc(p->character, stderr);

return NULL;

}

int main(int argc, char *argv[])

{

pthread_t thread1_id, thread2_id;

struct char_print_params thread1_args, thread2_args;

thread1_args.character = 'x';

thread1_args.count = 2000;

pthread_create(&thread1_id, NULL, &char_print, &thread1_args);

thread2_args.character = 'o';

thread2_args.count = 2000;

pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

pthread_join(thread1_id, NULL);

pthread_join(thread2_id, NULL);

fprintf(stderr, "\n");

return 0;

}

Канали як спосіб міжпроцесової взаємодії

Програмний канал в Unix/Linux є одним із засобів|коштів| взаємодії між процесами. Сама назва (pipe, дослівно - трубка|люлька|) достатньо|досить| точна передає сенс|зміст,рацію| функціонування цього засобу|кошту|. Канал подібний трубопроводу, прокладеному між двома процесами, і по цьому трубопроводу процеси можуть пересилати один одному дані. Подібно до трубопроводу, канал має власну місткість|ємкість|, дані, направлені|спрямовані| в канал процесом-відправником, не обов'язково повинні бути негайно прочитані процесом-одержувачем, але|та| можуть накопичуватися в каналі. Як і у|в,біля| трубопроводу, місткість|ємкість| каналу обмежена за кідькістю|скінченна|, коли вона буде вичерпана, запис в канал стає неможливим.

Операційні системи Unix/Linux надають| в розпорядження програмістів два види каналів - іменовані і неіменовані. Робота з|із| обома видами багато в чому подібна роботі з|із| файлами.

Неіменовані канали

Неіменований канал є|з'являється,являється| засобом|коштом| взаємодії між зв'язаними процесами - батьківським і дочірнім. Батьківський процес створює канал за допомогою системного виклику:

int pipe(int fd[2]);

Масив з|із| двох цілих чисел є|з'являється,являється| вихідним параметром цього системного виклику. Якщо виклик виконався нормально, то цей масив містить|утримує| два файлові дескриптори. fd[0] є|з'являється,являється| дескриптором для читання з|із| каналу, fd[1] - дескриптором для запису в канал. Коли процес породжує інший процес, дескриптори батьківського процесу успадковуються|наслідують| дочірнім процесом, і, таким чином, прокладається трубопровід між двома процесами. Природно, що один з процесів використовує канал тільки|лише| для читання, а інший - тільки|лише| для запису. Тому, якщо, наприклад, через канал повинні передаватися дані з|із| батьківського процесу в дочірній, батьківський процес відразу після|потім| запуску дочірнього процесу закриває|зачиняє| дескриптор каналу для читання, а дочірній процес закриває|зачиняє| дескриптор для запису. Якщо потрібен двонаправлений обмін даними між процесами, то батьківський процес створює два канали, один з яких використовується для передачі даних в один бік, а інший - в іншій. Після|потім| отримання|здобуття| процесами дескрипторів каналу для роботи з|із| каналом використовуються файлові системні виклики:

int read(int pipe_fd, void *area, int cnt); int write(int pipe_fd, void *area, int cnt);

Перший аргумент цих викликів - дескриптор каналу, другий - покажчик на область пам'яті, з|із| якою відбувається|походить| обмін, третій, - кількість байт. Обидва виклики повертають число переданих байт (або -1 - при помилці).

Виконання цих системних викликів може переводити|перекладати,переказувати| процес в стан очікування|чекання|. Це відбувається|походить|, якщо процес намагається|пробує| читати дані з|із| порожнього|пустого| каналу або писати дані в переповнений канал. Процес виходить з|із| очікування|чекання|, коли в каналі з'являються|появляються| дані або коли в каналі з'являється|появляється| вільне місце, відповідно.

При завершенні використання каналу процес виконує системний виклик:

int close(int pipe_fd);

Якщо батьківський процес, що створив канал, породжує декілька дочірніх процесів, то всі дочірні процеси підключені до іншого кінця каналу. Якщо, наприклад, батьківський процес виводить дані в канал, то вони "дістануться" тому дочірньому процесу, який раніше виконає системний виклик read.

Іменовані канали в Linux

Іменовані канали в Linux (у UNIX їх іноді|інколи| називають FIFO) можуть використовуватися як засіб|кошт| взаємодії між неспорідненими|родинними| і навіть видаленими|віддаленими| процесами. Такий канал має зовнішнє ім'я, яке включається в простір імен файлової системи. Тому іменований канал ще більш схожий на файл, чим неіменований. У системі канал представляється спеціальним файлом і створюється спеціальним системним викликом:

int mknod(char *name, int mode, int dev);

Цей системний виклик може використовуватися також і для створення|створіння| звичайних|звичних| файлів, каталогів і інших спеціальних файлів. Параметр name цього виклику є|з'являється,являється| покажчиком на символьний рядок, що містить|утримує| ім'я каналу (ім'я може включати також і шлях|колія,дорога|). Параметр mode визначає тип створюваного файлу і режим доступу до нього. Старші 7 біт цього числа визначають тип створюваного файлу (для іменованого каналу він може кодуватися макроконстантою: S_IFIFO, молодші 9 біт визначають права доступу "rwx" для власника (старша трійка), для групи (середня трійка), для всіх інших (молодша трійка). Так, наприклад, для каналу, який буде доступний тільки|лише| для власника, код параметра mode буде S_IFIFO|0x140, а для каналу, доступного для всіх-всіх-всіх - S_IFIFO|0x1B6. (Природно, право "x " для каналу не визначається.) Третій параметр при створенні|створінні| каналу задається 0.

Далі при роботі з|із| іменованим каналом використовуються файлові системні виклики:

int open(int *name, int oflag); int read(int pipe_fd, void *area, int cnt); int write(int pipe_fd, void *area, int cnt); int close(int pipe_fd);

Зверніть увагу на те, що при відкритті|відчиненні| файлу-каналу можуть бути задані прапори відкриття|відчинення|, серед яких може бути і прапор O_NDELAY. Якщо іменований канал відкритий|відчинений| з|із| цим прапором, то процес, що працює з|із| іменованим каналом, не переходить в очікування|чекання| в тих випадках, які приводять|призводять,наводять| до припинення процесу, що працює з|із| неіменованим каналом, - натомість системні виклики read і write закінчуються з|із| ознакою помилки.

Іменований канал є|з'являється,являється| постійним об'єктом, він зберігається навіть після|потім| завершення процесу, що створив його, і при необхідності повинен бути знищений явно - за допомогою системного виклику:

int unlink(char *name);





Поделиться с друзьями:


Дата добавления: 2016-07-29; Мы поможем в написании ваших работ!; просмотров: 474 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Велико ли, мало ли дело, его надо делать. © Неизвестно
==> читать все изречения...

2450 - | 2133 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.009 с.