ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Interprocess Communication
         

     

    Інформатика, програмування

    Лекція № 17

    Interprocess Communication

    Ми з вами говорили, що далі мова піде про поділюваних ресурсах,доступ до яких може здійснюватися з боку довільних процесів, взагальному випадку, у довільному порядку. Ці ресурси доступні будь-якомупроцесу, а процеси не обов'язково повинні бути спорідненими. За наявностітакої схеми виникають дві принципові проблеми:
    1. Іменування;
    2. Синхронізація;

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

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

    Рішення цих проблем ми й будемо розглядати.

    Проблема іменування вирішується за рахунок асоціювання з кожним ресурсомдеякого ключа. У загальному випадку це цілочисельне значення. Тобто пристворення розділяється ресурсу його автор приписує йому номер і визначаєправа доступу до цього ресурсу. Після цього будь-який процес, який вкажесистемі, що він хоче спілкуватися з розділяються ресурсом з ключем N, іволодіє необхідними правами доступу, буде допущений для роботи з цимресурсом.

    Однак таке рішення не є ідеальним, оскільки цілком можливаколізія номерів - коли співпадають номери поділюваних ресурсів. У цьомувипадку процеси будуть плутатися, що неминуче призведе до помилок. Тому всистемі передбачено стандартна програма створення унікальних ключів. Длястворення унікального ключа використовується функція ftok

    # include

    # include key_t ftok (char * s, char c);

    Суть її дії - по текстовому рядку і символу генеруєтьсяунікальне для кожної такої пари значення ключа. Після цьогозгенерувати ключі можна користуватися як для створення ресурсу, так ідля підтвердження використання ресурсу. Більш того, для виключенняколізій, рекомендується вказувати в якості параметра "покажчика нарядок "шлях до деякого свого файлу. Другий аргумент - символьний,який дозволяє створювати деякі варіанти ключа, пов'язаного з цимім'ям, цей аргумент називається проектом (project). При такому підходіможна домогтися відсутності колізій.

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

    Колективна пам'ять.

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

    Давайте розглянемо ті функції, які надаються нам для роботиз розділяються ресурсами.

    Перша функція - створення спільної пам'яті. int shmget (key_t key, int size, int shmemflg); key - ключ розділяється пам'яті size - розмір розділу пам'яті, який повинен бути створений shmemflg - прапори

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

    За допомогою цієї функції можна як створити новий розділяється ресурс
    "Пам'ять" (у цьому випадку під прапорах повинен бути вказаний IPC_CREAT)?, А такожВи можете приєднатися до існуючого ресурсів, що розділяються. Крім того, вможливих прапорах може бути вказаний прапор IPC_EXECL, він дозволяє перевірити іпідключитися до існуючого ресурсу - якщо ресурс існує, то функціяпідключає до нього процес і повертає код ідентифікатора, якщо ж ресурсне існує, то функція повертає -1 і відповідний код у errno.

    Наступна функція - доступ до поділюваного пам'яті: char * shmat (int shmid, char * shmaddr, int shmflg); shmid - ідентифікатор розділяється ресурсу shmaddr - адреса, з якої ми хотіли б розмістити поділюванупам'ять

    При цьому, якщо значення shmaddr - адреса, то пам'ять буде підключена,починаючи з цієї адреси, якщо його значення - нуль, то система сама підбереадреса початку. Також як значення цього аргументу можуть бутидеякі зумовлені константи, які дозволяють організувати, вЗокрема вирівнювання адреси по сторінці або початку сегмента пам'яті. shmflg - прапори. Вони визначають різні режими доступу, зокрема,є прапор SHM_RDONLY.

    Ця функція повертає вказівник на адресу, починаючи з якого будепочинатися запитувана Колективна пам'ять. Якщо відбувається помилка, топовертається -1.

    Хотілося б трохи поговорити про права доступу. Вони реально можутьвикористовуватися і коректно працювати не завжди. Тому що, якщо апаратно НЕпідтримується закриття області даних на читання або на запис, то в цьомувипадку можуть виникнути проблеми з реалізацією такого роду прапорів. По -перше, вони не будуть працювати, тому що ми отримуємо покажчик і починаємопрацювати з покажчиком, як з покажчиком, і загальна схема тут непередбачає захисту. Друге, можна програмно зробити так, щобпрацювали прапори, але тоді ми не зможемо вказувати довільний адресу, в цьомувипадку система буде підставляти і повертати в якості адреса розділеноїпам'яті деякі свої адреси, звернення до яких буде створювати свідомопомилкову ситуацію, виникне переривання процесу, під час якогосистема подивиться - хто і чому був ініціатором некоректного поводження допам'яті, і якщо той процес має потрібні права доступу - система підставитьпотрібні адреси, інакше доступ для процесу буде заблоковано. Це схоже навстановлення контрольної точки в програмі при налагодженні, коли створюваласясвідомо помилкова ситуація для того, щоб можна було перервати процес іоцінити його стан.

    Третя функція - відкріплення розділяється пам'яті: int shmdt (char * shmaddr); shmaddr - адреса прикріпленою до процесу пам'яті, який був отриманийпри підключенні пам'яті на початку роботи.

    Четверта функція - управління пам'яттю, що розділяється: int shmctl (int shmid, int cmd, struct shmid_ds * buf); shmid - ідентифікатор розділяється пам'яті cmd - команда управління.

    Зокрема, можуть бути команди: IPC_SET (змінити права доступу івласника ресурсу - для цього треба мати ідентифікатор автора даногоресурсу або супер-), IPC_STAT (показує стан ресурсу - вцьому випадку заповнюється інформація в структуру, покажчик на якупередається третім параметром, IPC_RMID (знищення ресурсу - після того,як автор створив процес - з ним працюють процеси, які підключаються івідключаються, але не знищують ресурс, а за допомогою цієї команди мизнищуємо ресурс в системі).

    Це все, що стосується функцій управління пам'яттю, що розділяється.

    Передача повідомлень.

    Наступним засобом взаємодії процесів у системі IPC - цепередача повідомлень. Її суть в наступному: у системі є так званачергу повідомлень, в якій кожне повідомлення представляє із себеструктуру даних, з якою асоційований буфер, що містить текст повідомлення іознака, яка називається типом повідомлення. Черга повідомлень може бутирозглянута двояко:
    1. чергу розглядається, як одна єдина наскрізна чергу, порядок повідомлень в якій визначається хронологією їх потрапляння в цю чергу.
    2. крім того, так як кожне повідомлення має тип (на схемі - буква поруч з номером повідомлення), то цю чергу можна розглядати, як суперпозицію черг, пов'язану з повідомленнями одного типу.

    Система IPC дозволяє створювати розділяється ресурс, званий
    "Черга повідомлень" - таких черг може бути довільна кількість. Зааналогією з пам'яттю, що розділяється - ми можемо створити чергу, підключитися доній, надіслати повідомлення, прийняти повідомлення, знищити чергу і т.д.
    Розглянемо функції роботи з чергами повідомлень:

    Створення черги повідомлень: int msgget (key_t key, int flags);

    Залежно від прапорів при зверненні до даної функції або створюється розділяється ресурс, або здійснюється підключення до вже існуючого.

    Відправлення повідомлення: int msgsnd (int id, struct msgbuf * buf, int size, int flags); id - ідентифікатор черги повідомлення; struct msgbuf (long type;/* тип повідомлення */char mtext [s]/* покажчик на тіло повідомлення */

    ) size - розмір повідомлення, тут вказується розмір повідомлення, розміщеного за вказівником buf; flags - прапори, зокрема, прапором може бути константа IPC_NOWAIT .

    При наявності такого прапора будуть наступні дії - можлива ситуація, коли буфера, передбачені системою під чергу повідомлень, переповнені. У цьому випадку можливі два варіанти - процес буде чекати звільнення простору, якщо не вказано IPC_NOWAIT, або функція поверне -1 (з відповідним кодом в errno), якщо було вказано

    IPC_NOWAIT.

    Прийом повідомлення: int msgrcv (int id, struct msgbuf * buf, int size, long type, intflags); id - ідентифікатор черги; buf - покажчик на буфер, куди буде прийнято повідомлення; size - розмір буфера, в якому буде розміщено текст повідомлення; type - якщо тип дорівнює нулю, то буде прийнято перші повідомлення з наскрізного черзі, якщо тип більше нуля, то в цьому випадку буде прийнято перше повідомлення з черги повідомлень, пов'язаної з типом, рівним значенню цього параметра. flags - прапори, зокрема, IPC_NOWAIT, він забезпечить роботу запиту без очікування приходу повідомлення, якщо такого повідомлення в момент звернення функції до ресурсу не було, інакше процес буде чекати.

    Управління чергою: int msgctl (int id , int cmd, struct msgid_dl * buf); id - ідентифікатор черги; cmd - команда управління, для нас інтерес представляє IPC_RMID, яка знищить ресурс. buf - цей параметр буде залишений без коментарів.

    Ми описали два засоби взаємодії між процесами. Що ж мипобачили? Зрозуміло, що назви та описи інтерфейсів мало зрозумілі. Першза все слід зауважити те, що як тільки ми переходимо до питаннявзаємодії процесів, у нас виникає проблема синхронізації. І тутми вже бачимо проблеми, пов'язані з тим, що після того, як ми попрацювали зпам'яттю, що розділяється чи чергою повідомлень, в системі може залишатися
    "Мотлох", наприклад, процеси, які очікують повідомлень, які в своючергу не були послані. Так, якщо ми звернулися до функції отриманняповідомлень з типом, яке взагалі не прийшов, і якщо не варто ключ
    IPC_NOWAIT, то процес буде чекати його появи, доки не зникне ресурс.
    Або ми можемо забути знищити ресурс (і система нікого не поправить) - цейресурс залишиться у вигляді забруднюючої елемента системи.

    Коли людина починає працювати з подібними засобами, то він берена себе відповідальність за всі наслідки, які можуть виникнути. Цеперший набір проблем - системна синхронізація і акуратність. Другапроблема - синхронізація даних, коли приймач і передавач працюютьсинхронно. Зауважимо, що найгірший із синхронізації ресурс зрозглянутих нами - Колективна пам'ять. Це означає, що коректнаробота з пам'яттю, що розділяється не може здійснюватися без використаннязасобів синхронізації, і, зокрема, деяким елементом синхронізаціїможе бути чергу повідомлень. Наприклад, ми можемо записати в пам'ять дані івідправити повідомлення приймача, що інформація надійшла в ресурс, після чогоприймач, отримавши повідомлення, починає зчитувати дані. Також яксинхронізуючого засоби можуть застосовуватися сигнали.

    І це головне - не мова інтерфейсів, а проблеми, які можутьвиникнути при взаємодії паралельних процесів.

    Лекція № 18

    До сьогоднішнього дня ми розібрали два механізми взаємодії процесівв системі IPC - це механізм загальної (або що розділяється) пам'яті та механізмповідомлень. Ми з вами з'ясували, що однією з основних проблем, що виникаєпри взаємодії процесів, є проблема синхронізації. Яскравимприкладом механізму, для якого ця проблема є найбільш гострою,є механізм взаємодії процесів з використанням розділяєтьсяпам'яті.

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

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

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

    Порядок читання та запису повідомлень з черги відповідає назвіцієї структури - черга. Крім того, за рахунок того, що кожне повідомленнятипізовані, є можливість розгляду цієї черги з декількох точокзору. Перша точка зору - це одна черга і порядок в нійхронологічний. Друга точка зору - це можливість подання цієїчерги у вигляді кількох черг, кожна з яких містить елементипевного типу.

    Зрозуміло, що механізм повідомлень може виступати в двох ролях: якзасіб передача даних, і як засіб синхронізації (зрозуміло якимчином).

    Отже, до сьогоднішнього дня ми познайомилися з двома цими механізмами.
    Нагадаю, як тільки ми переходимо до роботи від однопроцессной задачі до задачімногопроцессной, у нас одразу ж виникають проблеми, пов'язані з тим, щобудь-який паралелізм накладає певну відповідальність на програму.
    Це відповідальність за синхронізації доступу до поділюваного пам'яті,відповідальність за правильність підпрограми, що займається прийомом іпередачею повідомлень і т.д. Можна, наприклад, помилитися в механізмі передачіі прийому повідомлень за рахунок того, що якийсь процес буде нескінченнодовго чекати неіснуюче повідомлення, те, що ніколи в черзі нез'явиться, і система вам ніколи таку помилку не зафіксує. Тобто можливізависання процесів, можуть утворитися незвільненими ресурси ( "сміття"),і це призводить до деградації системи.

    Зараз ми напишемо наступну програму: перший процес буде читатидеяку текстовий рядок зі стандартного вводу і у випадку, якщо рядокпочинається з букви 'a', то цей рядок як повідомлення буде переданапроцесу А, якщо 'b' - процесу В, якщо 'q' - то процесам А і В, а потімбуде здійснено вихід. Процеси А і В роздруковують отримані рядка настандартний висновок.

    Основний процес
    # include
    # include
    # include
    # include struct (long mtype;/* тип повідомлення */char Data [256];/* повідомлення */

    ) Message;

    int main ()
    (Key_t key; int msgid; char str [256]; key = ftok ( "/ usr/mash", 's');/* отримуємо унікальний ключ, однозначновизначає доступ до ресурсу даного типу */msgid = msgget (key, 0666 | IPC_CREAT);/* створюємо чергу повідомлень, 0666визначає права доступу */for (;;) (/ * запускаємо вічний цикл */gets (str);/* читаємо зі стандартного вводу рядків??
    */Strcpy (Message.Data, str);/* і копіюємо її в буфер повідомлення
    */Switch (str [0]) (case 'a': case 'A': Message.mtype = 1;/* встановлюємо тип і посилаємоповідомлення в чергу */msgsnd (msgid, (struct msgbuf *) (& Message),strlen (str) +1, 0); break; case 'b': case 'B': Message.mtype = 2; msgsnd (msgid, (struct msgbuf *) (& Message),strlen (str) +1, 0); break; case q ': case' Q ': Message.mtype = 1; msgsnd (msgid, (struct msgbuf *) (& Message),strlen (str) +1, 0);

    Message.mtype = 2; msgsnd (msgid, (struct msgbuf *) (& Message),strlen (str) +1, 0); sleep (10);/* чекаємо отримання повідомленьпроцесами А і В */msgctl (msgid, IPC_RMID, NULL);/* знищуємо чергу */exit (0); default: break;

    )
    )
    )
    Процес-приймач А/* процес В аналогічний з точністю до четвертогопараметра в msgrcv */
    # include
    # include
    # include
    # include struct (long mtype; char Data [256];

    ) Message;

    int main ()
    (Key_t key; int msgid; key = ftok ( "/ usr/mash", 's');/* отримуємо ключ за тими ж параметрами */msgid = msgget (key, 0666 | IPC_CREAT);/* створюємо чергу повідомлень */for (;;) (/ * запускаємо вічний цикл */msgrcv (msgid, (struct msgbuf *) (& Message), 256, 1, 0);/* читаємоповідомлення з типом 1 */if (Message.Data [0] = 'q' | | Message.Data [0] = 'Q') break; printf ( "% s", Message.Data);
    ) exit (0);
    )

    Семафори

    З точки зору тих проблем, з якими ми знайомимося, семафори - цеє цілком законне і існуюче поняття. Вперше ввів це поняттядосить відомий вчений Дейкстра. Семафор - це деякий об'єкт,який має цілочисельне значення S, і з яким пов'язані дві операції:
    V (S) і P (S).

    Операція P (S) зменшує значення семафора на 1, і якщо S (0 процеспродовжує роботу. Якщо S0, то процеспродовжує виконання. Якщо S (0, то розблокується один з процесів,стані очікування в черзі процесів, пов'язаної з семафором S, і поточний процеспродовжить виконання.

    Вважається, що операції P (S) і V (S) неподільні. Це означає, щовиконання цих операцій не може перерватися до їх завершення. Тобто якщосемафор реалізований в системі, то це повинна бути одна команда.

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

    Насправді двійкові семафори найбільш часто знаходили застосування вапаратних реалізаціях, наприклад, в багатомашинних комплексах із загальноюоперативною пам'яттю.

    Одним з поділюваних ресурсів, який підтримує система IPCє т.зв. масив семафорів. Система дозволяє процесам, які беруть участь увзаємодії з даними розділяються ресурсом, збільшувати або зменшуватиодин або кілька семафорів з даного масиву на довільне значення (вмежах розрядної сітки). Система забезпечує очікування процесамиобнулення одного або декількох семафорів.

    Давайте розглянемо кошти, що надаються системою IPC, длястворення, управління та взаємодії з семафора.

    int semget (key_t key, int n, int flags);int semop (int semid, struct sembuf * sops, int n);

    struct sembuf (short sem_num;/* номер семафора в масиві семафорів */short sem_op;/* код операції, яку треба виконати */short sem_flg;/* прапори */

    )

    Перший параметр функції semget - ключ, друга - кількість семафорів
    (довжина масиву семафорів) і третій параметр - прапори. Через прапори можнавизначити права доступу і ті операції, які повинні виконуватися
    (відкриття світлофора, перевірка, і т.д.). Функція semget повертаєцілочисельний ідентифікатор створеного розділяється ресурсу, або -1, якщоресурс не вдалося створити (причина - в errno).

    Перший параметр функції semop - ідентифікатор світлофора, друга --покажчик на структуру sembuf і третій параметр - кількість вказівників нацю структуру, які передаються функцією semop. У структурі міститьсявся інформація про необхідний дії.

    Поле операції інтерпретується наступним чином. Нехай значеннясемафора з номером sem_num одно sem_val. У цьому випадку, якщо значенняоперації не дорівнює нулю, то оцінюється значення суми (sem_val + sem_op).
    Якщо ця сума більша або дорівнює нулю, то значення даного семафораустановлюється рівним сумі попереднього значення та коду операції. Якщо цясума менше нуля, то дія процесу буде призупинено до настанняодного з наступних подій:

    1. Значення суми (sem_val + sem_op) стане більше або дорівнює нулю.

    2. Прийшов якийсь сигнал. (Значення semop в цьому випадку буде дорівнює

    -1).

    Якщо код операції semop дорівнює нулю, то процес буде очікувати обнуленнясемафора. Якщо ми звернулися до функції semop з нульовим кодом операції, а доцього моменту значення семафора стало рівним нулю, то ніякого очікування невідбувається.

    Розглянемо третій параметр - прапори. Якщо третій параметр дорівнює нулю,то це означає, що прапори не використовуються. Прапорів є великакількість у т.ч. IPC_NOWAIT (при цьому прапорі у всіх тих випадках, коли миговорили, що процес буде очікувати, він не буде очікувати).

    Звертаю вашу увагу, що за одне звернення до функції semop можнапередати n структур і відповідно виконати дії з n семафора зцього масиву. Якщо в цій послідовності будуть присутні дварізних операції з одні світлофором, то швидше за все, виконається остання.

    Функція управління масивом семафорів.

    int semctl (int id, int sem_num, int cmd, union sem_buf arg);

    Перший параметр - ідентифікатор, друга - номер семафора в масиві, зяким ми будемо виконувати команду cmd з третього параметра. Останнійпараметр - деякий об'єднання типу sembuf.

    Команди можуть бути традиційні (IPC_RMID), і крім них є іншікоманди, і серед них IPC_SET, яка встановлює значення світлофора, прице значення передається через об'єднання arg. При установці семафора цієїфункцією, затримок, які визначають основний зміст роботи світлофора, небуде.

    Ось ті функції, які призначені для роботи з семафора. Прикладроботи з семафора розглянемо на наступній лекції.

    Лекція № 19

    Ми зупинилися на засобах синхронізації доступу до поділюванихресурсів - на семафорах. Ми говорили про те, що семафори - це тойформалізм, який спочатку був запропонований вченим у галузі комп'ютернихнаук Дейкстра, тому часто в літературі їх називають семафора Дейкстри.
    Семафор - це є деяка змінна і над нею визначені операції P і
    V. Одна дозволяє збільшувати значення семафора, інша - зменшувати. Причомудо цих змін пов'язані можливості блокування процесу та розблокуванняпроцесу. Звернемо увагу, що мова йде про неподільні операції, тоТобто тих операціях, які не можуть бути перервані, якщо почалися. Тобтоне може бути так, щоб під час виконання P або V прийшло переривання, ісистема передала керування іншому процесу. Це принципово. Томусемафори можна реалізовувати програмно, але при цьому ми повинні розуміти,що ця реалізація не зовсім коректна, тому що

    1) програма пишеться людиною, а переривається апаратурою, звідси можливе порушення неразделяемості;

    2) у розвинених обчислювальних системах, які підтримують багатопроцесорну обробку або обробку поділюваних ресурсів в рамках одного процесу, передбачені семафорні команди, які фактично реалізовують операції P і V. Це важливо.

    Ми говорили про реалізацію семафорів в Unix в системі IPC і про те, щоця система дозволяє створити розділяється ресурс "масив семафорів",відповідно, як і до будь-якого ресурсів, що розділяються, до цього масиву можебути забезпечений доступ з боку різних процесів, що володіють потрібнимиправами і ключем до даного ресурсу.

    Кожен елемент масиву - семафор. Для керування роботою семафорає функції:

    A. semop, що дозволяє реалізовувати операції P і V над одним або кількома семафора;

    B. segctl - управління ресурсом. Під управлінням тут розуміється три речі:

    1. - Отримання інформації про стан семафора;

    2. - Можливість створення певного режиму роботи світлофора, знищення семафора;

    3. - Зміна значення семафора (під зміною значення тут розуміється встановлення початкових значень, щоб використовувати надалі семафори, як семафори, а не скриньки для передачі значень, інші зміни - тільки за допомогою semop);

    Давайте наведемо приклад, яким спробуємо проілюструвативикористання семафорів на практиці.

    Наша програма буде оперувати з пам'яттю, що розділяється.

    1 процес - створює ресурси "Колективна пам'ять" і "семафори", далівін починає приймати рядки зі стандартного вводу і записує їх уподілювану пам'ять.

    2 процес - читає рядки з розділяється пам'яті.

    Таким чином ми маємо критичний ділянку в момент, коли однапроцес ще не дописав рядок, а інший її вже читає. Тому слідвстановити деякі синхронізації і затримки.

    Слід зазначити, що, як і всі програми, які ми наводимо, цяпрограма не досконала. Але не тому, що ми не можемо її написати (украйньому випадку можна попросити своїх аспірантів або студентів), а тому,що досконала програма буде займати занадто багато місця, і мисвідомо робимо деякі спрощення. Про ці спрощення ми постараємосязгадувати.

    1й процес:
    # include
    # include
    # include
    # include

    int main (void)
    (Key_t key; int semid, shmid; struct sembuf sops; char * shmaddr; char str [256]; key = ftok ( "/ usr/mash/exmpl", 'S');/* створюємо унікальнийключ */semid = semget (key, 1,0666 | IPC_CREAT);/* створюємо один семафор зпевнимиправами доступу */shmid = shmget (key, 256, 0666 | IPC_CREAT);/* створюємо поділюванупам'ять на 256елементів */shmaddr = shmat (shmid, NULL, 0);/* підключаємося до розділу пам'яті, вshaddr - покажчик на буфер зпам'яттю, що розділяється */semctl (semid, 0, IPC_SET, (union semun) 0);/* ініціалізіруем семафор ззначенням 0 */sops.sem_num = 0; sops.sem_flg = 0;

    /* запуск нескінченного циклу */while (1) (printf ( "Введіть рядок:"); if ((str = gets (str)) == NULL) break; sops.sem_op = 0;/* очікування обнулення семафора */semop (semid, & sops, 1); strcpy (shmaddr, str);/* копіюємо рядок урозд. пам'ять */sops.sem_op = 3;/* збільшення семафора на 3 */semop (semid, & sops, 1);

    )

    shmaddr [0] = 'Q';/* вкажемо 2ому процесу на те,
    */Sops.sem_op = 3;/* що пора завершаться */semop (semid, & sops, 1); sops.sem_op = 0;/* чекаємо, поки обнулиться семафор */semop (semid, & sops, 1); shmdt ( shmaddr);/* відключається від розд. пам'яті */semctl (semid, 0, IPC_RMID, (union semun) 0);/* вбиваємо семафор
    */Shmctl (shmid, IPC_RMID, NULL);/* знищуємо поділюванупам'ять */exit (0);
    )


    2й процес:

    /* тут нам треба коректно визначити існування ресурсу, якщо він є
    - Підключитися, якщо ні - зробити щось ще, але саме цього ми робитине будемо */
    # include
    # include
    # include
    # include

    int main (void)
    (Key_t key; int semid; struct sembuf sops; char * shmaddr; char st = 0;

    /* далі аналогічно попередньому процесу - ініціалізації ресурсів */semid = semget (key, 1,0666 | IPC_CREAT) ; shmid = shmget (key, 256, 0666 | IPC_CREAT); shmaddr = shmat (shmid, NULL, 0); sops.sem_num = 0; sops.sem_flg = 0;

    /* запускаємо цикл */while (st! = 'Q') (printf ( "Чекаємо відкриття семафора n ");

    /* очікування позитивного значеннясемафора */sops.sem_op =- 2; semop (semid, & sops, 1);

    /* будемо чекати, поки "значення семафора" + "значення sem_op" неперевалить за 0, то єякщо прийде "3", то "3-2 = 1" */

    /* тепер значення семафора одно 1 */st = shmaddr [0];

    (/ * критична секція - робота з пам'яттю, що розділяється - у цей момент перший процес до поділюваного пам'яті доступу не має */}

    /* після роботи - закриємо семафор */sem.sem_op =- 1; semop (semid, & sops, 1);

    /* повернувшись в початок циклу ми зновубудемо чекати, поки значення семафора НЕстане більше нуля */
    ) Shmdt (shmaddr);/* звільняємо поділювану пам'ять і виходимо */exit (0);
    )

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

    На цьому ми закінчуємо велику і досить важливу тему організаціївзаємодії процесів у системі.

    Наша самоціль - не вивчення тих коштів, які надає Unix,а вивчення принципів, які надає система для вирішення тих чиінших завдань, так як інші ОС надають аналогічні або схожізасоби управління процесами.

    Системи програмування.

    Система програмування - це комплекс програмних засобів, що забезпечуютьпідтримку технологій проектування, кодування, тестування й налагодження,називається системою програмування

    Етап проектування

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

    Наприклад, фірма Боїнг підняла в повітря літак "Боїнг-777",чудово цього факту полягає в тому, що літак злетів безпопередньої продувки в аеродинамічній трубі. Це означає, що весьлітак був спроектований і промодельований на програмних моделях, і цепроектування та моделювання було настільки чітким і правильним, щодало змогу відразу ж підняти літак у повітря. Для довідки - продуваннялітака в аеродинамічній трубі коштує шалені гроші.

    Приблизно та ж ситуація відбувається при створенні складних сучаснихпрограмних систем. На початку 80х рр. було розпочато СОІ (стратегічнаоборонна ініціатива), її ідея була в тому, щоб створити складноїтехнічної системи, яка б в автоматичному режимі встановила контрольза пусковими установками СРСР і країн Варшавського блоку, і у разіфіксації старту з наших позицій якогось непродекларірованного об'єктаавтоматично починалася війна. Тобто запускалися б кошти знищенняданого об'єкту і засоби для відповідних дій. Реально той департаментзбройних сил, який займався цим проектом, зазнав ряд криз узв'язку з тим, що провідні фахівці в галузі програмного забезпеченнявідмовлялися брати участь у реалізації цього проекту через неможливістькоректно його спроектувати, тому що система володіла гігантськимпотоком вхідних даних, на основі яких повинні були бути прийнятіоднозначні рішення, відповідальність за які оцінити вельми складно. НаНасправді ця проблема підштовхнула до розвитку з одного боку - мовпрограмування, які володіли надійністю, зокрема, мова Ада,однією з метою якого було створення безпомилкового ПЗ. У таких мовахнакладалися обмеження на місця, де найбільш ймовірно виникненняпомилки (міжмодульних інтерфейси; вирази, де присутні різні типиданих і т.п.) Зауважимо, що мова C не відповідає вимогамбезпеки. З іншого боку - до детального проектування, яке бдавало можливість деяким формальним чином описувати створюваний проект іпрацювати з проектом в частині його деталізації. Причому, перехід від деталізаціїдо кодування не мав би чіткої межі. Зрозуміло, що це є деяказавдання не сьогоднішнього, а завтрашнього дня, але реально розробники програмзнаходяться на шляху створення таких засобів, які дозволили б поєднатипроектування та кодування. Сьогоднішні системи програмування, якібудуються на об'єктно-орієнтованому підході, частково вирішують цю проблему.

    Наступна проблема проектування. Ми продекларували модулі,оголосили їх взаємозв'язку, як-то описали семантику модулів (це тежпроблема). Але ніхто не дасть гарантії, що цей проект правильний. Для вирішенняцієї проблеми використовується моделювання програмних систем. Тобто, колиразом з побудовою проекту, який декларує всі інтерфейси,функціональність та інше, ми можемо якимось чином промоделювати роботуусієї або частин створюваної системи. Реально при створенні великихпрограмних систем на сьогоднішній день немає єдиних інструментаріїв для такихдій. Кожні з існуючих систем мають різні підходи. Іноді ціпідходи (як і у нас, так і за кордоном) досить архаїчні.

    Але тим не менше слід розуміти, що період проектування єдуже важливий момент.

    Кодування

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

    Основний компонент системи кодування - мова програмування. Уголові кожного програміста лежить ієрархія мов програмування - відмашинного коду і асемблера до універсальних мов програмування
    (FORTRAN, Algol, Pascal, C і т.д.), спеціалізованих мов (SQL, HTML,
    Java і т.д.)

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

    Компілятор - це транслятор, що переводить текст програми в машиннийкод.

    Інтерпретатор - це транслятор, який звичайно суміщає процесперекладу та виконання програми (компілятор спочатку переводить програму, атільки потім її можна виконати). Він, грубо кажучи, виконує кожнурядок, при цьому машинний код не генерується, а відбувається звернення додеякої стандартної бібліотеки програм інтерпретатора. Якщо результатроботи компілятора - код програми на машинній мові, то результат роботитранслятора - послідовність звернень до функцій інтерпретації. Прице, також як і при компіляції, коли створюється оттранслірованнаяпрограма, у нас теж може бути створена програма, але в цьомуінтепретіруемом коді (послідовності звернень до функційінтерпретації).

    Зрозуміла різниця - компілятори більш ефективні, тому що вінтерпретатора неможлива оптимізація та постійні виклики функцій також неефективні. Але інтерпретатори зручніші за рахунок того, що приінтерпретації можливо включати у функції інтерпретації безліч сервіснихкоштів: відладки, можливість інтеграції інтерпретатора і мовногоредактора (компіляція це робити не дозволяє).

    На сьогоднішній день кожен з методів - і компіляція і інтерпретаціязаймають свої певні ніші.

    Лекція № 20

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

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

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status