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

     

     

     

     

     

         
     
    Процеси і IPC
         

     

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

    Процеси і IPC

    Відразу хочу засмутити програмістів під Windows. На жаль, деякі з описаних нижче рецептів під Windows працювати не будуть. Я й сам довго скреготав зубами, коли у відповідь на перевизначення STDOUT за допомогою open розгалужуються в логи падали повідомлення про те, що, мовляв, немає такої команди. Кого вже тут винити, не знаю, і шукати не збираюся. А раджу всім, щоб не витрачати свій дорогоцінний час, писати свої програми з розрахунком на UNIX. Чесно кажучи, після всього, що я пережив, програмування під Windows, і дізнавшись, що хостинг на IIS набагато дорожче (як дуже рідкісний звір чи що?) ніж на UNIX-ах, я трохи з крісла не вивалився.

    Процеси і з чим їх їдять

    Давним-давно в одній далекій галактиці жив-був DOS. І було в нього всього-на-всього 640 Килов пам'яті, і міг виконувати він лише тільки одне завдання. І з'явився грізний монстр Windows, який розділив процесорний час на частини. Одну частину відвів він Сонмище процесів, а іншу частину - Сонмище потоків. І перегукувалися вони з допомогою мьютексом і семафорів. А дані передавалися де як. Була там і загальна купа (heap), і пайпи кой де працювали ... Загалом розповідати далі думаю не має сенсу. Ще багато чого можна написати - все це нудно і відволікає від основних цілей.

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

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

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

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

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

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

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

    fork;

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

    На Насправді, оператор fork повертає значення, яке використовується для визначення процесу. Наприклад, людина виходить з-за рогу, а йому цеглиною по голові. Прокинувся, а в руці у нього на папірці написано - ти номер 1. Він встав і пішов далі. Піти то пішов, та на його місці знову ж таки ця людина лежить. А у нього в руці папірець, на якому написано - ти номер 2. Ця людина піднявся, подумав, що зараз ось зайду за інший кут, а там знову цеглиною по голові дадуть, і пішов в інший бік.

    Так Отож, повернімося до наших баранів. Одному процесу дістається значення, ідентифікує породжений процес. Тобто, дописуємо в папірець першим людини фразу типу "у другого номер 2". Це буває необхідним, у разі якщо мається на увазі взаємодія з породженим процесом. Породжений процес, отримує від fork значення 0. Але можливі такі помилкові ситуації, коли створити процес не вдалося. Повертаючись до нашого прикладу, людина заходить за кут і ... Нічого не відбувається. Людина думає, дивно, тут на мене повинен впасти цеглина, мабуть погода нельотна. Розгортається і йде додому. Коли fork не возвращает значення (undef), означає породити процес не вдалося. Це, поза сумнівом, помилкова ситуація і її необхідно обробити. У загальному випадку виклик fork повинен виглядати так

    unless defined (fork) (print "обробіть помилку, або замість цього викличте die ")

    Напевно вас вже перекрючіло, в марних спробах відривання пальців від улюбленої клавіатури. Давайте спробуємо застосувати наші знання про fork на якому-небудь (як завжди марно) прикладі.

    #!/usr/bin/perl-w

    # fork.pl

    die "Non-flying weather"

    print "I'm number $ $ n";

    В результаті виконання ви побачите щось подібне до

    [root @ avalon tests] #./fork.pl

    I'm number 6773

    I'm number 6774

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

    Так, мало не забув, важливо завершувати процес оператором exit. Ну, думаю, досить з вас марної писанини. Пора зайнятися чимось більш серйозним.

    Фільтрація вихідних даних

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

    Почекайте розминати пальці. Спочатку вип'ємо по гуртку кофею, а я, в цей час, змалюю ситуацію в цілому. Що таке фільтр на вихідні дані всім зрозуміло? Ну, якщо кому не зрозуміло, то знову ж таки - уявімо. Програма щось там виводить в STDOUT (стандартний потік виводу), а в цей час якась інша програма тихо і непомітно краде ці дані і робить з ними все що заманеться. Реальний приклад? Ну, найперше, що прийшло мені в голову - це заміна всіх URL на гіперпосилання. Або в допомогу розсіяному програмісту, вічно забуваємо про HTTP-заголовках, перевіряти наявність оних заголовків і додавати їх якщо потрібно. Насправді, все може бути набагато складніше. Наприклад, вирізування ненормативної лексики (отакий невидимий цензор) з тексту повідомлення, відправляється за допомогою WEB-інтерфейсу, перед тим, як воно буде передаватися на вхід SENDMAIL. Ну і в такому дусі.

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

    #!/usr/bin/perl-w

    # nfilter.pl

    filter ();

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

    (print "Output line $ in ";)

    sub filter

    (

    die "Cannot fork" unless defined ($ fpid = open (STDOUT ,"|-"));

    return if ($ fpid! = 0);

    num = 0;

    while () (Print "$ num: t $ _"; $ num + +;)

    exit;

    )

    Не здумайте запускати. Що, вже запустили? Тоді натисніть Ctrl + C. За те, тепер назавжди запам'ятайте - потрібно закривати дескриптори (бажано все:). У чому ж справа? Чому програма зависла? Всі породжені процеси є процесами єдиного завдання. Потоки введення виводу автоматично закриваються, коли завершується останній процес. Конструкція open (STDOUT, "|-") неявно викликає fork. Згадайте документацію по файлових операціях:

    open (HANDLE, "| $ Cmd"); # направити інформацію на вхід програми

    Так Ось тут аналогічна ситуація, тільки в якості програми тут створюється дочірній процес. А так як в якості дескриптора ми вказуємо STDOUT, то в цьому процесі він перевизначається. Як і у випадку з fork, щодо даних - дублюється їх стан на момент перед викликом fork. Таким чином, в дочірній процес потрапляє нормальної не перевизначених STDOUT. Зауважу, що open з вказаними аргументами як результат повертає ті ж самі значення, що і fork. Далі, програма визначає в якому вона потоці - якщо не у породженому ($ fpid! = 0), тоді повертається і емулює висновок рядків. Сам фільтр читає STDIN поки не закінчаться дані. А дані закінчаться, коли потік введення буде закритий (для батьківського процесcа, це потік виводу). Батьківський процесc вже завершив свою роботу, а система чекає коли завершиться останній процес, що б закрити потоки. І так далі, і так далі. Відчуваєте, де собака заритий? Після того, як виведення рядків завершений, необхідно закрити потік висновку, що б фільтр, що приймає вихідні дані через потік введення вийшов з циклу

    while () (print "$ num: t $ _"; $ num + +;)

    Ось так то, беремо і правим

    #!/usr/bin/perl-w

    # nfilter.pl

    filter ();

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

    (print "Output linen";)

    close (STDOUT);

    sub filter

    (

    die "Cannot fork" unless defined ($ fpid = open (STDOUT ,"|-"));

    return if ($ fpid! = 0);

    num = 0;

    while () (Print "$ num: t $ _"; $ num + +;)

    exit;

    )

    Ну це звичайно, дюже примітивно. Але якщо нам потрібно тільки лише фільтрувати, потік виводу, то зійде. А от якщо ми, наприклад, пишемо супер-систему обробки помилок, то цього все-таки замало. Уявімо, що такий собі сторож фільтрує висновок і відразу відправляє його на справжній STDOUT. А якщо виникла фатальна помилка? Ми виводимо повідомлення про помилку, але все це в догонку тому непотребу, що вже був відправлений у STDOUT. Така обробка помилок, як-то кажуть, "що мертвому припарка ". Можна, звичайно, накопичувати висновок всередині фільтра та виводити тільки цілком. У разі чого, можна пришиб породжений процесc з допомогою оператора kill. Але на жаль, потік виведення вже перевизначений безповоротно.

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

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

    #!/usr/bin/perl-w

    # errfilter.pl

    my ($ fpid, $ oldout);

    pipe (FOR_READ, FOR_WRITE);

    select ((select (FOR_READ), $ | = 1) [0 ]);

    select ((select (FOR_WRITE), $ | = 1) [0 ]);

    start_filter ();

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

    (print "Output linen";)

    # Error ( "bug ");

    close (FOR_WRITE);

    waitpid ($ fpid, 0);

    sub start_filter

    (

    die "Cannot fork" unless defined ($ fpid = fork);

    unless ($ fpid == 0)

    (

    close (FOR_READ);

    $ oldout = select (FOR_WRITE);

    return;

    )

    close (FOR_WRITE);

    my ($ out, $ num) = ( "", 0);

    while () ($ Out .= "$ numt $ _"; $ num + +;)

    close (FOR_READ);

    print $ out;

    exit;

    )

    sub Error

    (

    my ($ error_text) =_;

    select ($ oldout);

    kill KILL => $ fpid;

    close (FOR_WRITE);

    print "Error: $ error_textn";

    exit;

    )

    Ну що, налили чергову порцію кави? Тоді приступимо до розбору польотів. Першим справою, програма пов'язує дві дескриптора FOR_READ і FOR_WRITE в канал з допомогою pipe. При цьому, FOR_READ вийде тільки для читання, а FOR_WRITE, відповідно, лише для запису. Про наступні два рядки скажу тільки що вони відключають буфферізацію. Для нас це поки не важливо, їх можна взагалі прибрати. Далі викликається функція start_filter (). Ось на неї треба поглянути з усією уважністю.

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

    Повернемося до функції start_filter () в тій його частині, де виконується безпосередньо фільтрація. Насамперед не використовуваний в дочірньому процесі кінець каналу закривається. Далі, процес у циклі зчитує дані з каналу і конкатенірует їх у змінній $ out. Ну далі має бути все зрозуміло. Запустіть програму. Працює? Принаймні повинна.

    Тепер приберіть коментарі з рядка, де викликається функція Error ( "bug"). Запустіть програму знову. Ну, який результат? Цього ми добивалися? (Правильний відповідь так, якщо ні, то дивіться що ви там понаписали).

    Давайте подивимося, що робить функція Error (). Перш за все відновлює стандартний потік виведення. У цей час дочірній процес у режимі накопичення даних нічого про це не підозрює. Наступна жорстока операція вбиває дочірній процес. А дочірній процес ще нічого не вивів в потік виводу. Після закривається дескриптор для запису, і виконується обробка помилки. Ну і що б минути останні рядки головного процесу виконується exit.

    Ось і все. Як вже ви будете застосовувати отриману інформацію на практиці, залежить лише від вас.

    Що таке мінлива

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

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

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

    В загальному випадку, змінна - це пойменована область пам'яті. Залежно від мови, оголошення змінної може супроводжуватися зазначенням типу. Звичайно, в мовах високого рівня вказівка типу не використовується. Як правило, синтаксичні відмінності між мовами найчастіше виявляються саме у способах оголошення змінних (C, C + + - конкретизація типу; perl - ідентифікатор структури $, @ або%).

    Однак, в сучасному світі програмування ім'я і тип це ще не все, що програміст повинен знати про змінної. Існують такі поняття як простір імен і область дії. Уявіть, що ви пишете програму, в якій використовуються різних змінних. Імена всі змінних складають список, який визначає простір імен. Припустимо, в процесі розробки ви допустили помилку, і оголосили дві змінні з однаковими іменами. При спробі зібрати програму ваш компілятор попередить про цю помилку, що було б неможливим, якби імена всіх змінних залишалися без контролю з боку компілятора. Таким чином, цілісність простору імен звалюється з пліч програміста на компілятор, що знову ж таки, значно полегшує процес розробки і налагодження. У дійсності, наведений приклад не є помилковим для всіх мов програмування. Кожен компілятор (або інтерпретатор) висуває свої вимоги до простору імен і що в одній мові (в даному випадку C і C + +) є помилкою, в інших мовах може такої і не бути.

    Якщо раніше програми були досить маленькими, що б вміститися в одному файлі, то зараз вихідний код програм може складатися з декількох файлів. При цьому абсолютно нереально запам'ятати унікальні імена по всій програмі. У зв'язку з цим (і не тільки) було введено поняття області дії (або області видимості) змінної. Область дії поняття абстрактне. Цей термін пріменітелен тільки по відношенню до мов середнього та вищого рівнів. Сенс у те, що б якось розбити простір імен на кілька незалежних частин. Таким чином, в одній програмі зможуть безболісно співіснувати кілька змінних з однаковими іменами та типами. У досвідчених програмістів область дії асоціюється з поточним програмним блоком, але тому що ми ще не знаємо, що таке програмний блок, ми розглянемо це на іншому прикладі. Новачкам буде більш зрозуміла концепція поділу області дії в межах різних файлів (така методика використовується, наприклад, в perl). Це означає, що мінлива оголошена в одному з файлів програми буде абсолютно не видно з інших файлів програми (за умови, що ми оголосимо змінну за допомогою специфікатор my). Таким чином, ми можемо оголосити змінну з ім'ям Variable в декількох файлах проекту і це не буде помилкою. Більш докладно області дії ми будемо розглядати в процесі розбору програмних блоків.

    Що таке тип даних

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

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

    На цьому етапі важливо зрозуміти, що різні мови призначені для різних рівнів розробки. Наприклад, в мовах високого рівня (таких як perl) не має значення рядкові дані зберігає мінлива або числові. Компілятор (або інтерпретатор) самостійно визначає як йому інтерпретувати значення в залежно від контексту. Якщо необхідно виконати арифметичне додавання, то виконується спроба перетворити значення змінної до числовому типу. Якщо ж виконується конкатенація або інтерполяція рядки, то будь-який числовий операнд буде автоматично перетворено до строковому типу.

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

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

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

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

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

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

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

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://prolib.ru/

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

     

     

     

     

     

     

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