Spis treści Skorowidz Poziom główny Poziom nadrzędny ©
«« Początek »» Koniec

Język programowania, kod źródłowy, program

W niniejszym rozdziale rozważamy podstawowe pojęcia związane ze skłonieniem systemu automatycznego do wykonania poleceń zapisanych w postaci programu źródłowego.

Formalne języki programowania, takie jak linearny Fortran, funkcjonalny LISP, proceduralny Pascal i C czy obiektowa Java albo Python, stanowią — podobnie jak sieci działań — standardowy środek dokumentowania algorytmów. Spotkaliśmy się z nimi w podrozdziale 1.3.3. właśnie przy okazji omawiania sposobów wyrażania algorytmów. Zastosowanie języków programowania jest jednak znacznie szersze: z pliku źródłowego zawierającego zapis algorytmu można uzyskać program realizujący ten algorytm, dający się uruchomić pod nadzorem systemu operacyjnego lub w specyficznym środowisku uruchomieniowym.

Tryby uruchamiania kodu

Ciągi poleceń zapisane w postaci programu źródłowego nadają się do wykonania przez automat. Niektóre języki programowania wymagają specyficznego środowiska, dostarczanego przez odpowiedni system użytkowy. Liczne współczesne pakiety użytkowe są wyposażona w obsługę jakiegoś języka programowania i posiadają narzędzia pomocne podczas tworzenia i uruchamiania napisanych w nim programów.

Istnieją dwa zasadniczo odmienne sposoby uruchamiania programów napisanych przy użyciu języków programowania.

Programy kompilowane

Pierwszy sposób polega na przetłumaczeniu całego tekstu programu z symbolicznego języka programowania na kod wewnętrzny związany z konkretnym środowiskiem. Proces ten nosi nazwę kompilacji, zaś programy dokonujące takiego tłumaczenia określa się mianem kompilatorów.

    plik z kompletnym kodem źródłowym (np. *.c)                                                                                
     |                                                                                                                         
     |  kompilacja                                                                                                             
     ↓                                                                                                                         
    plik z kompletnym kodem binarnym (np. *.o) ––→ plik z kodem symbolicznym (opcjonalnie; np. *.asm)                          
     |                                                                                                                         
     |  konsolidacja                                                                                                           
     ↓                                                                                                                         
    binarny plik wykonywalny właściwy dla systemu operacyjnego (np. EXE lub ELF)                                               
     |                                                                                                                         
     |  uruchamianie programu (wiele razy, w określonym systemie operacyjnym)                                                  
     ↓                                                                                                                         

Wynikiem kompilacji jest program binarny zapisany w pliku wykonywalnym. Program taki da się uruchomić jako polecenie systemu operacyjnego lub środowiska wykonawczego. Użytkownik nie będący współtwórcą programu ma zazwyczaj do czynienia tylko z plikiem wykonywalnym.

Klasyczne kompilatory generują kod dla danego typu procesora i zapisują go w formacie zależnym od systemu operacyjnego. Użycie tego samego programu w systemie o innej architekturze wymaga osobnej kompilacji w celu wygenerowania odpowiedniego pliku wykonywalnego.

Programy interpretowane

Drugi sposób uruchamiana programów napisanych przy użyciu języka programowania nosi nazwę interpretacji. Polega on na odłożeniu tłumaczenia tekstu poleceń do chwili bezpośrednio poprzedzającej wykonanie. W środowiskach interpretujących program jest wykonywany instrukcja po instrukcji według schematu:

        |                                                          
        | uruchomienie kodu źródłowego                             
        |                                                          
        ↓←---------------------.                                   
        |                      |                                   
    przeczytaj                 ↑                                   
        ↓                  przejdź do następnej instrukcji         
    przetłumacz                ↑                                   
        ↓                      |                                   
    wykonaj                    |                                   
        ↳ ---------------------                                    

Możliwa jest także praca interaktywna, podczas której instrukcje wprowadzane przez operatora są na bieżąco tłumaczone i wykonywane.

David Harel w klasycznej książce Rzecz o istocie informatyki (wyd. IV: WNT 2008) wskazuje kilka istotnych argumentów za budowaniem i używaniem interpreterów: skonstruowanie interpretera jest na ogół łatwiejsze, niż kompilatora; w sytuacji, kiedy program jest układany i modyfikowany doraźnie, przetestowanie i przebudowanie kodu interpretowanego jest prostsze; wreszcie, interpreter umożliwia pracę w trybie konwersacyjnym, wykonując polecenia podawane na bieżąco przez operatora, co poszerza zakres możliwych zastosowań.

Ceną prostoty jest wielokrotnie (nawet kilkaset razy) wolniejsza praca programów interpretowanych w porównaniu z kodem skompilowanym.

W przeszłości poznaliśmy już co najmniej jedno środowisko interpretujące: był nim systemowy procesor poleceń (shell). Trybu interpretacji używa się także do wykonywania programów napisanych w językach skryptowych, takich jak Basic, Perl, Python czy PHP.

W niektórych współczesnych systemach interpretujących, takich jak Perl czy Python, mamy do czynienia z wstępnym etapem kompilacji. Kompilator generuje wtedy kod binarny będący przekształceniem oryginalnego kodu źródłowego. Kod ten, poddawany wykonaniu w środowisku maszyny wirtualnej (patrz następny podrozdział), wymaga przetłumaczenia na kod maszynowy. Dzieje się to przy każdym uruchomieniu; dlatego termin interpretacja pozostaje poprawny.

Maszyny wirtualne

W tworzonych współcześnie platformach wykonawczych mamy często do czynienia z tzw. maszynami wirtualnymi. Maszyna taka jest programem, zapewniającym określone właściwości środowiska wykonawczego w taki sposób, by można je było traktować jak właściwości sprzętu. Dzięki temu program w postaci wykonywalnej dla maszyny wirtualnej działa w taki sam sposób na wszystkich platformach sprzętowych (typ procesora) i operacyjnych (system operacyjny). Zatem raz skompilowany program źródłowy można przenosić z miejsca na miejsce bez ograniczeń technicznych związanych ze sprzętem i oprogramowaniem systemowym — jedyne wymaganie dotyczy istnienia odpowiedniej maszyny wirtualnej. Takie właściwości są charakterystyczne m.in. dla języka Java oraz dla środowiska .NET.

    plik z kompletnym kodem źródłowym (np. *.java, *.py)                                                                       
     |                                                                                                                         
     |  kompilacja (wykonywana jeden raz)                                                                                      
     ↓                                                                                                                         
    plik z pośrednim kodem binarnym (np. *.class, *.pyc) -- program wykonywalny dla maszyny wirtualnej                         
     |                                                                                                                         
     |  uruchamianie (wiele razy, w różnych maszynach wirtualnych, w różnych systemach operacyjnych)                           
     ↓                                                                                                                         

Kompilacja just-in-time

Istnieje również zaawansowana technika kompilacji w trakcie wykonywania programu, zwana just-in-time (JIT). Polega ona na generowaniu kodu binarnego w momencie, kiedy dany fragment programu jest wykorzystywany po raz pierwszy w danym uruchomieniu. Następne przypadki użycia danej funkcji będą już korzystać z efektów kompilacji, co znacznie przyspieszy wykonywanie programu.

Uruchamianie własnego kodu źródłowego

Na ćwiczeniach będziemy mieć do czynienia z wybranymi algorytmami przetwarzania dyskretnego i numerycznego. Będziemy zgłębiać zasady ich działania, konstruować je samodzielnie, przetwarzać dane według opisanych za ich pomocą reguł — samodzielnie oraz za pośrednictwem dostępnego sprzętu obliczeniowego.

Algorytmy te posłużą jako podstawa do tworzenia kodu źródłowego programów w wybranym języku programowania wysokiego poziomu. Kod programu będzie przechowywany w pliku tekstowym, takim jak w zamieszczonych niżej przykładach.

Podstawowym językiem wykorzystywanym podczas kursu będzie Python. W laboratoriach zainstalowane jest oprogramowanie pozwalające uruchamiać kod źródłowy utworzony w tym języku.

Teksty źródłowe programów zapisanych za pomocą języka Python
[ plik źródłowy programu ] Rozwiązywanie równania algebraicznego
[ plik źródłowy programu ] Sumowanie ciągu liczb

Proszę o sprawdzenie, że przedstawione programy realizują te same algorytmy, które wcześniej w podrozdziale 1.3.2. opisano za pomocą sieci działań.

Uruchomienie kodu Pythona jest proste. Jeden z elementarnych sposobów polega na wpisaniu polecenia

python rkw.py

do konsoli systemowej. W omawianym przypadku plik źródłowy rkw.py powinien znajdować się w bieżącej kartotece. Jeżeli tak nie jest, trzeba podać ścieżkę dostępu do niego.

W praktyce do tworzenia programów w języku Python przydatne jest oprogramowanie pomocnicze. Zostanie ono przedstawione w dalszym toku opracowania.

Uruchomienie przykładów napisanych w innych językach jest również możliwe. Chętnych odsyłamy do podręczników programowania w odpowiednim języku; wskazówki można też otrzymać podczas konsultacji.

Narzędzia dodatkowe

W systemach informatycznych przeznaczonych do uruchamiania kodu źródłowego, stanowiącemu ich zasadniczy składnik kompilatorowi lub interpreterowi zazwyczaj towarzyszy środowisko robocze, wyposażone w edytor i oprogramowanie pomocnicze. Pełni ono kilka funkcji:

Użycie systemu wyposażonego w takie środowisko nie jest niezbędne, chociaż w wielu sytuacjach pozwala na bardzo efektywną pracę.

Wgląd w narzędzia i środowiska programistyczne, pozwalające na tworzenie, uruchamianie i dogłębne testowanie kodu źródłowego oraz na generowanie z niego programów wykonywalnych daje poświęcona temu tematowi galeria ilustracji.

Pytania kontrolne

  1. Co to jest język programowania?
  2. Co to jest kod źródłowy programu?
  3. Jakie oprogramowanie służy do uruchamiania kodu?
  4. Czym różnią się interpretery od kompilatorów?
  5. Co to jest kod wykonywalny programu?
  6. Jakie oprogramowanie służy do analizy wykonywania kodu?
© Copyright 2000–2012 by Jan Jełowicki, Katedra Matematyki Uniwersytetu Przyrodniczego we Wrocławiu
Ostatnia modyfikacja w czerwcu 2013 r.
janj@aqua.up.wroc.pl
http://karnet.up.wroc.pl/~jasj