Vademecum informatyki praktycznejvip.opcode.eu.org/vademecum.pdfVademecum informatyki praktycznej...
Transcript of Vademecum informatyki praktycznejvip.opcode.eu.org/vademecum.pdfVademecum informatyki praktycznej...
Vademecuminformatykipraktycznej(aktualizacja:2021-07-27)
W założeniu ma to być kompleksowy przegląd podstawowych zagadnień z zakresu elektroniki,programowania oraz użytkowania i administracji systemami unixowymi. Nie jest to tutorial, anisamouczekprowadzącykrokpokrokuwzgłębianietajników"komputerologii",natomiastteksttenmożebyć wykorzystywany jako materiał pomocniczy do zająć o takiej tematyce, bądź też materiał służącyprzypomnieniu/uzupełnieniuposiadanejwiedzynaprzedstawianetematy.Korzystanieztegodokumentuprzysamodzielnejnaucejesttakżemożliwe,należyjednakliczyćsięztymżekoniecznemożebyćsięganiedo innych, bardziej szczegółowych źródeł, a co najważniejsze także duża ilość praktyki i próbsamodzielnegorozwiązywaniaproblemów-samoprzeczytanieniewystarczy.
Założeniemtegodokumentubyłożemabyćkompletnyizamknięty,jednymzefektówtegojestunikanieodsyłaniadoinnychmateriałówbezpośredniowtekście,wszystkieodnośnikidozewnętrznychźródeł(zawyjątkiem powoływania się na dokumentację narzędzi/bibliotek) znajdują się wyłącznie w dziale"Literatura".Założeniemtegodokumentubyłotakżeżemabyćwmiaręuniwersalnyiponadczasowy(niezdezaktualizować się po roku) dlatego też skupia się na bardziej uniwersalnych aspektach omawianychzagadnień, faktach, definicjach, itp bez odniesień w stylu "obecnie już", "nadal jest używany", itd, niepokazuje też różnego rodzaju sztuczek czy obejść doraźnych problemów, ani nie omawia szczegółówtechnologiiszybkozmieniającychsię.
ElektronikaElektronika zajmuje się wytwarzaniem i przetwarzaniem sygnałów w postaci prądów i napięćelektrycznych.Zjawiskoprąduzwiązanejestzprzepływemładunku(zuporządkowanymruchemnośnikówładunku), aby wystąpiło konieczna jest różnica potencjałów (napięcie) pomiędzy końcami przewodnika,prowadzionodoneutralizacjitejróżnicy.Dlategodlapodtrzymaniastałejróżnicypotencjałówkoniecznejestistnienieźródełprądu,prowadzącychdorozdzielaniaładunkówdodatnichodujemnych.
PodstawyNapięcieiprąd
Dlaelementów liniowych (np. zwykłykawałekprzewodu)zachodziproporcjonalnośćnatężeniaprądupłynącegoprzeztakielementdonapięciapomiędzyjegokońcami:R = UI .
NatężenieprąduelektrycznegoII (określaneskrótowojakoprąd)jesttostosunekprzemieszczonegoładunkudoczasujegoprzepływu.
NapięcieelektryczneUU pomiędzypunktemAiB(jakiegośobwodu)jesttoróżnicapotencjałuelektrycznegowpunkcieAiwpunkcieB.
PotencjałelektrycznyVV wpunkcieAjest skalarną wielkością charakteryzującą pole elektryczne w danym punkcie. Odpowiada pracyktórą trzebabywykonaćabyprzenieść ładunek q z tegopunktudonieskończoności podzielonejprzezwielkośćtegoładunku(jestniezależnyodwartościq ).WelektroniceużywasięwartościpotencjałówwzględemumownegopotencjałuzerowegoGND(coumożliwia traktowanie ich jako różnic potencjałów - napięć elektrycznych), w efekcie tegookreślenia"(stałe)napięcie"i"potencjał"bardzoczęstostosowanesązamiennie.
Masa,GNDumownypotencjałzerowy,względemktóregowyrażasięinnepotencjaływukładzie(coumożliwiatraktowanie ich jako różnic potencjałów - napięć elektrycznych). Potencjał ten może być równypotencjałowiziemi(masieochronnejPE),bądźmożebyćznimniezwiązany(układyizolowane).
Podstawowym przykładem teoretycznych (w rzeczywistości mogą występować tylko elementyrealizująceichfunkcjęwpewnymzakresieiwpewnymprzybliżeniu)elementównieliniowychsą:Idealneźródłoprądowe
wymuszaprzepływokreślonegoprąduprzezprzyłączonyukład,niezależnieodspadkównapięćwukładzie(czylimożeodłożyćsięnanimdowolnenapięcie).
Idealneźródłonapięciowewymusza określoną różnicę potencjałów pomiędzy swoimi zaciskami (czyli może przez nieprzepływaćdowolnenatężenieprądu).
Węzeł układu (sam w sobie, pomijając zjawiska pasożytnicze) nie jest w stanie gromadzić ładunkuelektrycznegozatem:Sumaprądówwpływającychdowęzłajestrównasumieprądówwypływającychztegowęzła.
Jeżeli rozważamyobwódzamkniętyodpunktuAzpotencjałemVA to sumującnapięcianakolejnychelementachobwodu (oporach, źródłachnapięciowych,etc) zuwzględnieniem ichznakugdywrócimy
do punktu A to potencjał nadal musi wynosić VA , zatem: Suma spadków napięć w zamkniętymobwodziejestrównazeru.
Opór,pojemnośćiindukcyjnośćPojęcia
Rezystancja(opórelektryczny)wyraża trudność przepływu prądu przez dany przewodnik - im większy opór elementu to (przytakimsamymprzyłożonymnapięciu)będziepłynąłmniejszyprąd.R = UI
Pojemność(wzajemna)wyrażazdolnośćdogromadzeniaładunkuprzezdanyelement-imwiększapojemnośćtymwięcejładunku(przytakimsamymprzyłożonymnapięciu)zgromadzielement.C = qU
Indukcyjnośćwyrażazdolnośćdowytwarzaniastrumieniapolamagnetycznegozwiązanegozprzepływemprąduprzezdanyelement.L = IΦ
Obwodyprądustałegoazmiennego
Pojemność oraz indukcyjność wprowadzona do obwodu ma znaczenie tylko gdy zachodzi zmiananatężaniaprądupłynącegoprzezobwód/zmianawartościnapięćodłożonychnajegoelementach.Wstanieustalonymobwoduprądustałegowprowadzonadoobwodupojemnośćoraz indukcyjnośćnieodgrywająroli,gdyż:
pojemności zgromadziły już (stosowny do przyłożonego do nich napięcia) ładunek i niepobierająprąduzobwodu,indukcyjnościwytworzyłypolemagnetyczne(stosownedoprzepływającegoprzeznieprądu) iniestanowiąoporudlapłynącegoprąduwobwodzie.
Wtakimprzypadkumożnatraktowaćpojemnościjakorozwarcia,aindukcyjnościjakozwarcia.
Impedancjajest wielkością charakteryzującą zależność pomiędzy natężeniem prądu i napięciemuwzględniającąreaktancjęobwodu.Z = R + jX
Reaktancjajest wielkością charakteryzującą opór bierny elementów pojemnościowych (kapacytancjaXC = − 1
ωC )iindukcyjnych(induktancjaXL = ωL ).
Pulsacjaωωcharakteryzuje szybkość zmian (jest proporcjonalna do odwrotności czasu trwania okresuzmiany).ω = 2πT
Elementyrzeczywiste
Rezystor(opornik)wprowadza do układu rezystancję związaną z swoją wartością nominalną. Typowo służy doograniczaniawartościprąduprzezniegoprzepływającego.Symbole: , .Powodujewydzielaniesięenergii(cieplnej)związanejzstrataminarezystancji-mocwydzielanadanajestzależnościami:P = UI = U
2
R = I2R ,czyliprzystałymnapięciuprzyłożonymdorezystoraim większy jego opór tym mniejsza moc się wydzieli (gdyż popłynie mniejszy prąd), ale przystałymprądziepłynącymprzezrezystormocrośniewrazzewzrostemoporu.
Kondensatorwprowadza do układu pojemność związaną z swoją wartością nominalną. Typowo służy doograniczaniazmiannapięcia(poprzezgromadzenieenergiiwpoluelektrycznym).Symbole: ,
.Czaspotrzebnydozmianynapięcianakondensatorzedanyjestzależnością:ΔT = C ⋅ ΔUICewka(dławik)
wprowadza do układu indukcyjność związaną z swoją wartością nominalną. Typowo służy doograniczaniazmianprądu(poprzezgromadzenieenergiiwpolumagnetycznym).Symbol: .Czaspotrzebnyzmianyprądupłynącegoprzezcewkę(dławikstawiaopórtakiejzmianietakjakkondensatorzmianienapięcia)danyjestzależnością:ΔT = L ⋅ ΔIU .Częstocewkanawinięta jestnardzeń ferrytowy,bardzosilniezwiększaon indukcyjnośćcewki,aleograniczaodgóryczęstotliwośćpracycewki.Ponadtoprzyodpowiedniodużymprądziemożedochodzić do nasycenia rdzenia, które objawia się tym, że zaczyna in hamować wzrost polazamiastgopoprawiać.Cewkanawiniętanaodpowiednimrdzeniumożestanowićelektromagnes.
Transformator
Układ cewek sprzężonych magnetycznie, z których część służy do wytwarzania energii polamagnetycznego,aczęśćdo jejodbierania.Typowosłużydoprzekazywaniaenergiipoprzezpolemagnetycznymcelemzmianynapięcialubseparacjigalwanicznejobwodów.W przypadku dwu uzwojeniowego transformatora zachodzi:
UweUwy
=IwyIwe
= nwenwy = z , gdzie z to
przekładniatransformatora,nwe toliczbauzwojeństronypierwotnej(wejściowej),anwy toliczbauzwojeństronywtórnej(wyjściowej).
Stykjesttoelementsłużącydomechanicznegozałączanialubodłączaniaprądu,nazywanybywatakżeprzełącznikiem. Wyróżnia się styki monostabilne (chwilowe), które samoistnie (po ustaniuczynnika przełączającego) wracają do jednej ze swoich pozycji oraz styki bistabilne, które poprzełączeniu pozostają w wybranej pozycji. Wyróżnia się także styki zwierne (normalnierozwarte),rozwierne(normalniezwarte)lubprzełączne(następujeprzełączaniepomiędzydwomalubwięcejmożliwymiwyjściami).Czynnikiemodpowiedzialnymzaprzełączaniestykówmożebyćmanualne działanie (przełącznik naciskany, przekręcany, pociąganym, itd przez człowieka) lubdziałanieelektromagnesu(cewki)-jesttowtedyprzekaźnikelektromagnetycznylubstycznik.Stanzwarciaokreślasięczęstomianem"zamknięty"(ang."close"),arozwarciamianem"otwarty"("open").Należy(zwłaszczawsystemachcyfrowych)pamiętać,żestykipotrafiądrgać -naogółprzyzmianiepozycjizamiastpojedynczegoimpulsugenerującałąserię.
Elementy rzeczywiste oprócz wartości nominalnej (wprowadzanej przez nie rezystancji, pojemnościlubindukcyjności)charakteryzujątakże:
wartościgraniczne(takiejakmaksymalnamocktóramożewydzielićsięnarezystorze,napięcieprzebiciakondensatora,maksymalnyprądprzewodzeniacewki, temperaturowyzakrespracy,...),impedancje pasożytnicze (każdy element rzeczywisty wprowadza zarówno niepożądanąrezystancję,jakiniepożądanąreaktancjęniezwiązanązjegowartościąnominalną).
W większości przypadków impedancję pasożytniczą można pominąć. Jednak np. w przypadkurzeczywistych źródeł napięciowych i prądowych rezystancja wewnętrzna takiego źródła częstoodgrywaistotnąrolędladziałaniaukładuiniemożezostaćpominięta.
Układypołączeń
Połączenieszeregowejesttotakiepołączenieelementówżeprzepływaprzeznie jednakowyprąd.Impedancje(zarównorezystancyjnejakireaktancyjne)takpołączonychelementówsumująsię.
~ Z1 Z2
Połączenierównoległe
jesttotakiepołączenieelementówżeprzyłożonedonichnapięciasąjednakowe(aprądpłynącywobwodzie ulega rozdzieleniu). Odwrotność impedancji takiego układu jest sumą odwrotnościimpedancjitakpołączonychelementów.
~ Z1 Z2
Dzielniknapięcia(rezystancyjny)
jest to szeregowepołączeniedwóch rezystorów.Poprzezdobórwartości rezystorówuzyskuje siępożądanenapięcienawyjściu takiegodzielnika,któredane jest zależnościąUwy = Uwe
R2R1+R2
.Ze
względu na to iż jest ono proporcjonalne do napięcia przyłożonego do całego dzielnika może onsłużyćtakżedoskalowanianapięciowegosygnałuwejściowego.Abyminimalizowaćwpływwartościimpedancjipodłączonejdowyjściadzielnikananapięciewyjściowenależyzapewnićodpowiedniomałewartości rezystorówwdzielniku - takabyprądpłynącyprzezR2byłzdecydowaniewiększy(typowo5do10razy)odprądupłynącegoprzezobciążenie(RL ).
Uwe
R1
R2
Uw
y RL
Dzielnikprądu(rezystancyjny)jest torównoległepołączeniedwóchrezystorów.Poprzezdobórwartości rezystorówuzyskujesiępożądanenatężenieprąduwwyjściowejgałęzi.
Z = Z1+ Z2
Z = Z1| |Z2⟺1Z =
1Z1+ 1Z2
⟺Z = 11Z1+ 1Z2
dioda
LED
diodaZenera
A K
A K
A K A K
B
C
E NPN
Rb
Rload
Vzasilania
Vster
Rb
Rload
Vzasilania
Vster
B
C
E
PNP
ObwódRCjest to szeregowe połączenie rezystora i kondensatora. Obwód taki charakteryzuje się stałączasową τ = RC . Napięcie na kondensatorze w trakcie jego ładowania dane jest zależnością
UC t = Uwe ⋅ 1 − e−tτ , a w trakcie rozładowywania UC t = UC 0 ⋅ e−
tτ . W przypadku
wyjścianazaciskachrezystorastanowifiltrgórnoprzepustowy,awprzypadkuwyjścianazaciskachkondensatora stanowi filtr dolnoprzepustowy, częstotliwość graniczna (zapewniająca tłumieniewiększeniż3dB)takichfiltrówwynosifgr = 1
2πτ .
Dioda
Diodaidealnatoelementprzewodzącyprądtylkowjednymkierunku.Rzeczywiste diody przewodzą prąd zdecydowanie chętniej w jednymkierunkuniżwdrugim(naogółprzewodzeniewkierunkuzaporowymsię pomija) ponadto charakteryzują je cechy zależne od technologiwykonaniatakiejak:
spadek napięcia w kierunku przewodzenia (typowo dla diodkrzemowych0.6V-0.7V,adladiodSchottky’ego0.3V)napięcie przebicia - napięcie, które przyłożone w kierunku zaporowym powoduje znacząceprzewodzenie diody w tym kierunku - w większości przypadków parametr którego nie należyprzekraczać,jednakwykorzystywane(istanowiąceichparametr)wniektórychtypachdiodmaksymalnyprądprzewodzeniaczasprzełączania(związanygłówniezpasożytnicząpojemnościązłącza)-zdecydowaniekrótszy(około100ps)wdiodachSchottky’egoniżwdiodachkrzemowych,.
Ponadtostosowanesąm.in.:diodyZenera-wykorzystujesię(charakterystycznądladanegotypu)wartośćnapięciaprzebiciadouzyskaniawukładziespadkunapięciaotejwartości,diodyświecące(LED)-emitująceświatłowtrakcieprzewodzenia(naelemenciewystępujestałyspadeknapięcia,jasnośćzależyodnatężeniaprądu),fotodiody - będące detektorami oświetlenia (przewodzenie spolaryzowanej w kierunkuzaporowym zależy od ilości padającego na element światła, niespolaryzowana pod wpływemoświetleniastajesięźródłemprądu).
TranzystorTranzystor jest to element o regulowanym elektrycznie przewodzeniu prądu (oporze), częstowykorzystywanydowzmacnianiasygnałówlubjakoprzełącznikelektroniczny.
NPN,PNP,JFET,MOSFET,...
NPNPrąd przepływający pomiędzy kolektorem aemiterem jest funkcją prądu przepływającegopomiędzy bazą a emiterem: IC = βIB . Napięciepomiędzy kolektorem a emiterem wynosi:UCE = Uzasi lania − IC ⋅ Rload . Napięcie to nie możejednakspaśćponiżejwartościminimalnejwynoszącejokoło 0.2V, gdy z powyższych zależności wynikałbytaki spadek to tranzystor pracuje w stanemnasyceniaiUCE ≈ 0.2V .
PNPPodobnie jak w NPE tyle że prąd przepływający pomiędzy emiterem a kolektorem jest funkcjąprąduprzepływającegopomiędzyemiteremabazą.
SpadeknapięciapomiędzybaząaemiteremUBE wtranzystorzeNPN(międzyemiteremabaząwPNP)wynosi nie więcej niż około 0.7V. Utrzymanie takiej wartości spadku napięcia podowduje powstanieokreślonegoprądubazy.Jeżelispadektenwynosidużomniej(np.zero),toprądbazyniepłynie,awięctranzystornieprzewodzi.
ZatemwukładzieprzedstawionymobokzmianaVster spowodujetakązmianęprądubazy IB abynaRbodłożyłosięnapięcieVster − 0.7V .Z tegoteżwzględukonieczne jeststosowanierezystancjipomiędzybaząanapięciamisterującymiinnymiodnapięciaemitera.
N-JFETPrąd przepływający pomiędzy drenem (drain) a źródłem (source) jest funkcją napięcia pomiędzybramką(gate)aźródłem(potencjałubramkiwzględemźródła-UGS ),prądbramkimożnauznaćzapomijanie mały. Tranzystor ten przewodzi tylko gdy napięcie pomiędzy bramką a źródłem jest
Rload
Vzasilania
Vster(<=0)
RloadVzasilania
Vster(>=Vzasilania)
G
D
S
N−JFET
G
D
S P−JFET
RloadVzasilania
Vster
Rload
Vzasilania
Vster
G
D
S
N−MOSFETenhancement
G
D
S
P−MOSFETenhancement
G
D
S
N−MOSFETdepletion
G
D
S
P−MOSFETdepletion
większe od napięcia odcięcia (UGSoff < 0), przewodzonyprąd wzrasta wraz ze wzrostem UGS , a maksimum jestosiąganedlaUGS = 0.
Gdy tranzystor jest spolaryzowany tak aby UDS > 0 orazUGS > UGSoff towzależnościodwartości spadkunapięciana tranzystorze UDS oraz wartości napięcia nasyceniaUsat = UGS −UGSoff wyróżniasiędwatrybypracy:
1. liniowy(gdyUDS > Usat ),wktórymID = β ⋅ Usat22. nasycenia (gdy UDS ≤ Usat ), w którymID = β ⋅ UGS ⋅ 2Usat −UDS
gdzieβ = IDSSUGSoff
2
P-JFETPodobnie jak N-JFET tyle że: prąd przepływa pomiędzy źródłem a drenem, przewodzony prądwzrastawrazzezmniejszaniemUGS (odUGSoff > 0dozera).
N-MOSFETPrądprzepływającypomiędzydrenem(drain) a źródłem (source) jestfunkcją napięcia pomiędzy bramką(gate) a źródłem (potencjału bramkiwzględemźródła -UGS ),bramka jestizolowana(niepłynieprzezniąprąd).
Wkierunkudren→źródłotranzystorten przewodzi gdy UGS > UGS( th) ,natomiast w przeciwnym kierunkuprzewodzi zawsze. Dla tranzystorówN-MOSFET z kanałem wzbogacanym(enhancement)UGS( th) > 0,azkanałemzubożonym(depletion)UGS( th) < 0.
Konkretna wartość UGS( th) zależna jest od konkretnego modelu tranzystora, innym istotnymparametrem związanym z sterowaniem tranzystorem jest maksymalna i minimalna dopuszczalnawartośćnapięciaUGS .
P-MOSFETPodobniejakN-MOSFETtyleże:
1. regulowane jest przewodzenie w kierunku źródło → dren (a w kierunku dren → źródłoprzewodzizawsze),
2. przewodzeniewkierunkuźródło→drenmamiejscegdyUGS < UGS( th) ,
3. dla tranzystorów z kanałem wzbogacanym (enhancement) UGS( th) < 0, a z kanałemzubożonym(depletion)UGS( th) > 0.
Przykłady:BC846(NPN,65V,0.1A),BC337(NPN,50V,0.8A),BD139(NPN,80V,1.5A);BC327(PNP,50V,0.8A),BD140(PNP,80V,1.5A);BS170(N-MOSFET,60V,5Ohm,0.5A),IRF540N(N-MOSFET,100V,44mOhm,33A),IRFZ44N(N-MOSFET,55V,17.5mOhm, 49A); IRF9Z34N (P-MOSFET, 55V, 100mOhm, 19A), IRF5210 (P-MOSFET, 100V, 60mOhm, 40A), IRF5305 (P-MOSFET,55V,60mOhm,31A);BF245(N-JFET)iwieleinnych
(inne)elementymocy
Tyrystor
Jestelementemprzewodzącymwyłączniew jednymkierunku (odanodydokatody).Przewodzeniemusizostaćzainicjowanepodaniem(dodatniegowzględemkatody)napięcianabramkę.Wyzwolony(raz przyłożonym napięciem bramki) tyrystor przewodzi do momentu spadku prądu poniżejminimalnejwartościprzewodzenialubwystąpieniaodwrotnejpolaryzacji.Zasadędziałaniatyrystoraobrazujeprzedstawionyobokdwu-tranzystorowymodel.
Triak
Jestelementemodwukierunkowymprzewodzeniuinicjowanymimpulsemnapięciowympodanymnabramkę. Zasadę jego działania obrazuje schemat zastępczy złożony z dwóch połączonych anty-równolegletyrystorów.Używanyjestjakoelektronicznyprzełącznikprąduprzemiennego.
Przykłady:BTA16
G
A
K G
A
KTYRYSTOR
<=>G
A2
A1
G<=>
A2
A2TRIAK
C
E
G
IGBT
G
C
E
<=>
TranzystorIGBT
Jest to tranzystor bipolarny z izolowanąbramką. Z punktu sterowania należy patrzećna niego jak na tranzystor typu N-MOSFET.Stosowany do przełączania w układach dużejmocy.
transoptory
Poprzezpołączeniewjednejobudowiediodyświecącejzfototranzystorem,fotodiodą(niekiedywrazztranzystoremdobramkiktóregojestpodłączona), fototriakiemlubpodobnymelementem(toznaczytakim którego przewodność zależy od padającego na niego oświetlenia) uzyskuje się elementnazywany transoptorem. W układzie może być zawarty także dodatkowy stopień wyjściowydostosowującynapięciadopoziomówwymaganychprzezjakiśstandard.
Transoptor zapewniaon izolację (typowo rzędu tysięcywoltów)galwanicznądwóchczęści obwodu.Pozwalatom.in.naodbiórsygnałówwysokonapięciowychprzezniskonapięciowączęśćukładu(diodaLEDmożebyćsterowananp.znapięcia230V,atranzystormożesterowaćukładem3.3V).Ponadtotransoptorzabezpieczaczęśćodbiorczą(podłączonądoswojegowyjścia)przedprzepięciamiw części sterującej diodą LED. Jednak ze względu na fizyczną bliskość diody i elementu foto-elektrycznego przy napięciu przekraczającym wartość izolacji może zdarzyć się przebicie (pełnąizolacjęoptycznązapewniaużyciepołączeńświatłowodowych).
Przykłady: 4N25 (analogowy), 4N35 (analogowy), 6N136 (cyfrowy), 6N137 (cyfrowy), MOC3023 (optotriak), MOC3063(optotriak)
Klucztranzystorowy
Klucz jest układem przełączającym wykorzystującym dwa skrajne stany pracy tranzystora - zatkania(tranzystornieprzewodzi),nasycenia(tranzystorprzewodzizminimalnymiograniczeniami).
kluczNPN
Abywprowadzić tranzystorNPNwstanzatkanianależypodaćna jegobazępotencjałmniejszy lubrównypotencjałowiemitera(zakładamyżepotencjałkolektorajestniemniejszyniżemitera-comamiejscewtypowychwarunkachpolaryzacjitranzystoraNPN),czyliUBE ≤ 0.AbywprowadzićtranzystorNPNwstannasycenianależynajegobazęwprowadzićpotencjałwiększyodpotencjałówemiteraikolektora,uzyskujesiętopoprzezwprowadzeniedotranzystoraprądubazyIB ≫
Uzasi laniaβRload
.
kluczPNP
Aby wprowadzić tranzystor PNP w stan zatkania należy podać na jego bazę potencjał większy lubrównypotencjałowiemitera(zakładamyżepotencjałemiterajestniemniejszyniżkolektora-comamiejscewtypowychwarunkachpolaryzacjitranzystoraPNP),czyliUBE ≥ 0.AbywprowadzićtranzystorPNPwstannasycenianależynajegobazęwprowadzićpotencjałmniejszyodpotencjałówemiteraikolektora,uzyskujesiętopoprzezwyprowadzenieztranzystoraprądubazyIB ≫
Uzasi laniaβRload
.
kluczJFET
Aby wprowadzić w stan zatkania tranzystor N-JFET należy podać UGS ≤ UGSoff , a dla tranzystora P-JFETnależypodaćUGS ≥ UGSoff .AbywprowadzićwstanprzewodzeniatranzystorN-JFETnależypodaćUGS ≥ 0} ,adlatranzystoraP-JFETnależypodaćUGS ≤ 0.
kluczMOSFET
AbywprowadzićtranzystorMOSFETwstanzatkanianależypodaćUGS < UGS( th) .Dlatranzystorów:
N-MOSFET z kanałem wzbogaconym i P-MOSFET z kanałem zubożonym wystarczy obniżyć
G
D
SQ1
IRF5305
IRF5210
R11 75k
R31
330k G
D
S
Q2
IRFZ44N
IRF540N1
3
2
Q3
BC846
R12 75k
12
Z21
10V
12
Z11
10V
S1
Load
mostekH
S3
S2 S4
STER0V/5V
1
3
2
Q4
BC846R41
330k
R21 150k
OUT
STER==0V=>OUT=GND
STER==5V=>OUT=+12V
+12V+12V
+12V
+12V+12V
potencjałbramkidowartościniewielewyższejniżpotencjałźródłaP-MOSFETzkanałemwzbogaconymiN-MOSFETzkanałemzubożonymmusitobyćwartośćponiżejpotencjałuźródła.
AbywprowadzićtranzystorMOSFETwstanprzewodzenianależypodaćUGS ≫ UGS( th) .
(pół)mostekH
Mostek H jest to układ (oparty o 4 przełączniki,których rolę mogą pełnić klucze tranzystorowe)pozwalający na zmianę polaryzacji zasilaniapodłączonego do niego odbiornika. Układ takizłożony jest zdwóch identycznychgałęzi (S1+S2oraz S3 + S4, każda włączona pomiędzy dwomabiegunami zasilania). Pojedyncza taka gałąźnazywana jest pół-mostkiem i składa się z dwóchkluczy które powinny być sterowaneprzeciwstawnie (aby wyeliminować możliwośćzwarcia zasilania z masą). Układ pół-mostka możebyć wykorzystywany także samodzielnie jakouniwersalny układ klucza pozwalającego nazałączanie odbiornika zarówno od strony napięciadodatniego jak i od strony masy (w zależności odsposobu jego podłączenia) lub przełączania dwóchodbiorników (jednego umieszczonego pomiędzyzasilaniemawyjściemmostka,adrugiegopomiędzywyjściemamasą).
Na schemacie umieszczonym obok przedstawiona jest także przykładowa realizacja pół-mostka woparciuodwakluczenatranzystorachMOSFETisterującenimikluczeNPN.ZastosowaniekluczyNPN(tranzystoryQ3iQ4)pozwalanasterowaniezużyciemnapięcianiższegoodnapięciaprzełączanego.
WstaniezatkaniaQ3iQ4:potencjałbramkiQ1równyjestpotencjałowizasilania(czylitakżepotencjałowiźródła),zatemQ1(P-MOSFETwzbogacony)nieprzewodzi;potencjałbramkiQ2ustaladzielnikzłożonyzR21iZ21(jestonwyższyodpotencjałuźródła,minimalnie o wartość napięcia zasilania, a maksymalnie o wartość spadku na Z21) i jest onwyższy o conajmniej UGS( th) od potencjału źródła, zatem Q2 (N-MOSFET wzbogacony)przewodzi.
Wstanienasycenia(pzewodzenia)Q3iQ4:potencjałbramkiQ1ustalany jestprzezdzielnikR11 iR12albo(jeżelinapięciezasilania jestodpowiednio wysokie) przez dzielnik Z11 i R12 i jest on niższy o conajmniej UGS( th) odpotencjałuźródła,zatemQ1przewodzi;potencjałbramkiQ2jestrównypotencjałowimasy(czylitakżepotencjałowiźródła),zatemQ2nieprzewodzi.
ZastosowaniediodZeneraZ1iZ2zabezpieczatranzystoryMOSFETprzedpodaniemnabramkęzbytdużego(codowartościbezwzględnej)napięciawstosunkucodoźródła.Niestetywiążesiętotakżezzastosowaniem to zastosowaniem rezystora R12, który (tworząc dzielnik) powoduje iż układ niebędziedziałałpoprawniedlaniskichnapięćzasilaniatoruprądowego-napięciemusibyćwiększeod2UGS( th) zamiast od UGS( th) . Ponadto wymaga to zastosowania osobnych gałęzi sterujących dlaposzczególnych tranzystorów MOSFET (dwóch kluczy NPN), ponieważ obecność Z21 w gałęzisterującejP-MOSFETem(Q1)przywyższymnapięciuzasilaniapowodowałabyprzepływprąduprzeztągałąźniezależnieodQ3comogłobyprowadzićdoprzewodzeniaQ1.
Wzmacniaczsygnałupunktpracy
Aby móc wykorzystać tranzystor do wzmacniania sygnału konieczne jest wstępne ustalenie punktupracytranzystorawtensposóbabyniewchodziłwstanynasyceniaizatkaniaorazabyukładposiadałustalonewzmocnienie.
WprzypadkutranzystorówNPNiPNPmożnabypróbowaćustalićgozużyciemokreślonejwartościprądubazy(pokazanypowyżejukładzrezystorembazyirezystancjąobciążenia),jednakzewzględuna znaczny rozrzut wartości współczynnika β pomiędzy egzemplarzami układ taki cechowałby sięmałąpowtarzalnością.Wzwiązkuztymstosujesiępokazanyobokukładzestałympotencjałembazyiopornikiememiterowym,gdzieIE =
UB − 0.6VRe
,IB =IEβ + 1 ,IC = IE − IB ,β ≫ 1,zatemIC = IE
ββ + 1 ≈ IE .
Rc
VccVcc
Rb1
Rb2
Re
Cin
Cout
Cb
VccVcc
Rb1
Rb2 Re
Cin
Coutin
out
out
in
wspolnykolektor wspolnabaza
B
C
E
B
C
E
Rc
VccVcc
Rb1
Rb2 Re
Cin
Cout
Ce
in
out
B
C
E
B
C
ET1
B
C
E T2
out1 out2
RC2RC1
Vcc Vcc
in1 in2
−Vee
Ree
B
C
E T1
B
C
ET2
in out
RLR1
Vcc Vcc
wspólnyemiter
Przedstawiony układ jest także przykładem jednego z 3podstawowych układów pracy tranzystora bipolarnego (NPN,PNP) w funkcji wzmacniacza określanym "wspólny emiter".Układ tego typu charakteryzuje się wejściem sygnału na bazętranzystora(napięciebazywstosunkucodonapięciaemitera/masy dla układów NPN) i wyjściem wzmocnionego sygnału zkolektora (napięcie kolektorem w stosunku co do napięciaemitera/masydlaukładówNPN).
Wprzypadkupolaryzacjistałymprądembazyemiterwukładzietymmapotencjałmasy.Wprzypadkuprzedstawionejpolaryzacjistałym potencjałem bazy aby w układzie tym móc uzyskaćwzmocnienie konieczne jest zwarcie emitera do masy dlasygnałów zmiennych, realizowane przy pomocy kondensatoraCe.
wspólnykolektoriwspólnabaza
Kolejnymi dwoma z 3podstawowych układówpracy są układy wspólnegokolektoraiwspólnejbazy.
W układzie wspólnegokolektora sygnał wejściowypodawanyjestmiędzybazęakolektor, natomiastwzmocniony sygnałodbierany jest z pomiędzyemitera i kolektora.Wzmacniacz w układziewspólnego kolektora nieposiada wzmocnienianapięciowego (napięcie wyjściowe jest wręcz pomniejszone o spadek na złączu PN), natomiastposiadaznacznewzmocnienieprądu.Układczęstookreślanyjestjakowtórnikemiterowy.
W układzie wspólnej bazy sygnał wejściowy podawany jest między emiter a bazę, natomiastwzmocnionysygnałodbieranyjestzpomiędzykolektoraibazy.
UkładytranzystoroweLustroprądowe
T1iT2musząmiećzapewnionątąsamątemperaturę(najlepiejbyćwykonanewramach jednegoukładu scalonego.T1pracuje jakodioda (stosujemy tranzystoraby zapewnić taką samą charakterystykę jak T2), która wraz z R1 tworzysprzężony termicznie z T2 dzielnik sterujący tranzystorem T2. Układ tensterowany prądem płynącym przez R1 powoduje przepływ (niemalże) takiegosamegoprądupoprzezRL.
Wzmacniaczróżnicowy
Wprzypadkuukładuz tranzystoramiNPN"bardziej"przewodzićbędzietranzystornawejściuktóregojestwiększenapięcie(niżnatymdrugim).Fakt tego że on przewodzi powoduje ustalenie się potencjału w węźlełączącym emitery obu tranzystorów na wartość napięcia jego bazypomniejszonego o spadek na przewodzącym złączu PN. W sytuacji gdynapięcia baz obu tranzystorów są odpowiednio bliskie przewodzić będąoba,zakrestenokreślasięstrefąprzejściową.
Układtenmożepełnićrolękluczaprądowego(gdypodanysygnałnatyledużyaby zatkać jeden z tranzystorów) lubwzmacniacza (gdypracowaćbędąobatranzystory.Układjestczułynaróżnicęnapięćprzyłożonychdoin1 i in2.Reepełni rolę źródłaprądowego (ipowinienbyć takdobranyaby wraz z wartością -Vee zapewnić jego stabilność). Zastosowanieregulowanego źródła prądowego (tranzystor) zamiast Ree (realnie - wszereguzRee)pozwalanaregulacjęwzmocnieniategoukładu.
B
C
ET1
B
C
E T2
RC2RC1
in1
R1
Ree
AK
D1
Up
B
C
E
T1B
C
E
T2
RC2
RC1
outRB1
RB2
inC1
B
C
E
T1B
C
E
T2
RC2
RC1
Vcc
in2
out2RB1RB2
out1
AK
D2
in1A
K
D1
B
C
E
T1B
C
E
T2
RC2
RC1
out2
RB1
RB2
out1C1 C2
ASTABILNY
BISTABILNY
MONOSTABILNY
SHMITTA
−Vee
−Vee
Vcc Vcc Vcc Vcc Vcc
VccVcc
VccVccVcc
R1 R2in
out
wzmacniaczodwracającyR1
R2
inout
wzmacniacznieodwracający
U1+12V U1
R2RsVin2
out
U1
R1Vin1
sumatornapięćR1=R2=...=Rs...
+12V
+12V
-12V
-12V
-12V
Przerzutniki
PrzerzutnikbistabilnyUkład ten służy do zapamiętaniastanu binarnego. Może byćprzełączony poprzez podaniekrótkiego sygnału na którejś zwejść lub zwarcie któregośwyjścia do masy. powoduje torozpoczęcie przewodzenia przezwybrany z tranzystorów, coprowadzi do spadku napięcia nabazie drugiego tranzystora,prowadząc do jego zatkania itrwałego ustalenia stanuwysokiego na bazie wybranegotranzystora.
PrzerzutnikmonostabilnyUkładsłużydogeneracjiimpulsutrwającego ustaloną długość.Działa on podobnie jakprzedstawiony przerzutnikbistabilny, z taką różnicą iżkrótkotrwałe zwarcie wejścia domasy powoduje obniżeniepotencjałubazyT2onapięciedojakiegozostałnaładowanyC1(wnormalnymstanieUCC −UBE ).Powoduje to zatkanie T2 i przewodzenie T1, następuje także ładowanie C1 z stopniowymzwiększaniemnapięcianabazieT2ażdoosiągnięciasytuacjipierwotnej.Należyzwrócićuwagęże po zatkaniu T1 (zaprzestaniu generowania sygnału wyjściowego) układ nie osiągnął jeszczegotowościdogeneracjinastępnegoimpulsugdyżmusinastąpił ładowanieC1przezRC1(należyodczekać t≳5τ = 5RC1C1). Wadą takiego rozwiązania są duże ujemne napięcia na bazachtranzystorówwchwiliprzerzutu,co(przywiększychnapięciachzasilania)możedoprowadzićdoichprzebicia.
PrzerzutnikastabilnyPrzerzutnik ten służy do generacji sygnału prostokątnego o zadanym wypełnieniu. Działanieukładu jest podobne do opisanego przerzutnika montostabilnego z tym że po (ponownym)nasyceniu drugiego tranzystora powstały spadek napięcia rozpoczyna taki sam proces dlapierwszego tranzystora i kondensatora podłączonego do jego bazy. Dodatkową wadą tegorozwiązania jest problem startu przy wypełnieniu 1/2 (jednakowych elementach) i łagodnymwłączaniu.
PrzerzutnikShmittaSłużyoddouzyskaniahisterezy-większenapięciepowodujeprzejściewstanwysoki,amniejszeod niego w stan niski. Pozwala to m.in. na odszumianie sygnałów. Idea działania polega nazmianie potencjału drugiego wejścia wzmacniacza różnicowego zależnie od jego stanu.PrzesuwnikpoziomówzrealizowanynaD1orazR1służydodostosowanianapięciawyjściowegodozakresuhisterezy(wynosionUCC −Up =wartośćgórna,UCC − IEERC1−Up =wartośćdolna).
Wzmacniaczoperacyjny
Jest toukład służącydowzmacnianiabardzowiele razyróżnicy napięć wejściowych, oparty na układziewzmacniacza różnicowego z lustrem prądowym. Nastopniuwejściowymposiadaonwzmacniaczróżnicowyzlustrem, dalej jest układ wzmacniający o dużymwzmocnieniu, a na stopniu wyjściowym wtórnikemiterowy. Charakteryzuje się dużą rezystancjąwejściowąibardzodużąwartościąwzmocnienia.
Jako iż wzmocnienie wzmacniaczy operacyjnych jestbardzo duże nie da się w praktyce wykorzystać ichbezpośrednio do wzmacniania sygnału. Robi się to zwykorzystaniem sprzężenia zwrotnego, czyli podaniemprzeskalowanegosygnałuwyjściowegonawejście.Dziękiwykorzystaniuujemnegosprzężeniaukładzachowujesięstabilnie dążąc do utrzymania różnicy napięćwejściowych bliskiej zeru oraz posiada bardzo małą(prawie zerową) rezystancję wyjściową. Wzmocnieniezależy od parametrów dzielnika występującego w pętli
1 +3out
2 -Vin1
Vin2
Vcc
Vout
Podstawowyukładpracy: Vin1>Vin2=>Vout=0 Vin1<Vin2=>Vout=Vccpozwalanakonwersjępoziomów-możemyporównywaćnapięciaoinnychpoziomach(takżewyższych)niżpoziomnapięciawyjściowego
1 +3out
2 -
R3
Vcc
Vout
R2 zhisterezą
Vin1
Vin2
R1
dyskryminatorokienkowy
1 +3out
2 -Vin
Vref1
Vcc
Vout1 +
3out2 -
Vref2
sprzężeniazwrotnegoidlawzmacniaczaodwracającegofazęwynosiku = −R2R1
,adlawzmacniaczanie
odwracającegofazyku = 1 +R2R1
(abyuzyskaćwtórnikR2należyzastąpićzwarciem,aR1rozwarciem).
W wzmacniaczu odwracającym rezystancja wejściowa Rwe = R1, natomiast w odwracającym jest tozasadniczo tylko rezystancję sumacyjnąwzmacniacza różnicowego (różnicowejpraktycznieniewidaćbo dzięki sprzężeniu zwrotnemu napięcie na niej bliskie zeru). Częstotliwość graniczną oblicza się zzależnościfg =
fT1 + R2R1
.
Niekiedystosujesię takżetzw"R3"podłączonydonieodwracającegowejściawzmacniacza,matonaceluminimalizacjęwpływuprądówwejściowych(niewpływananapięcieniesymetryczności,którejestcechąsamegowzmacniacza),wtedyR3=R1||R2gdysprzężenieDC,lubR3=R2gdysprzężenieAC(źródło sygnału oddzielone kondensatorem). Ze względu na stosowanie sprzężenia zwrotnego niemożnanaukładtakipodawaćsygnałuktóregoprzesunięciefazowenawzmacniaczubyłobywiększeniż135°, aby nie doprowadzić do wzbudzania się układu. Uzyskuje się to poprzez zapewnieniewzmocnienia mniejszego od jedności dla częstotliwości przy których byłoby takie lub większeprzesunięciefazowe.
W oparciu o wzmacniacz operacyjny w układzie odwracającym można zrealizować sumator napięćwejściowych. Suma prądów wpływających przez rezystory R1, R2, R3, itd, ze względu na dużąrezystancjęwejściowąwzmacniaczamusibyćrównaprądowiwypływającemuprzezRs.NapięcienaRfmusibyćrównenapięciuwyjściowemu(wejścienieodwracającepodłączonedomasy,aukładdążydozerowego napięcia różnicowego na wejściach wzmacniacza). ZatemU1R1+ U2R2
+… = − UwyRs⟺Uwy = −Rs
U1R1+ U2R2
+… co przy równych wartościach rezystancji daje:
Uwy = U1+U2+… .
Przykłady:LM358;TL081
Komparatoranalogowy
Jest to układ służący doporównywania dwóch napięćwejściowych, oparty (podobnie jakwzmacniacz operacyjny) naukładzie wzmacniacza różnicowegoz lustrem prądowym.Charakteryzujesiędużąrezystancjąwejściową(małympoboremprąduzwejść), szybką i stromą zmianąwyjścia w odpowiedzi na zmianęsygnału wejściowego. Opróczpodstawowego układu pracykomparator może być stosowanym.in.wukładach:
zhisterezą:dzielnik R1, R3zapewnia sprzężeniezwrotne,R3≫ R1(rzędu
megaomów),wartośćhisterezydanajestzależnością:VH = VccR1
R1+R3rezystorR2zapewnia jednakowerezystancjęobuwejśćkomparatora iwynosićpowinien:R2 ≈ R1
dyskryminatorokienkowy:układ złożony z dwóch komparatorów wykrywający to iż napięcie znajduje się w przedzialepomiędzy Vref1 a Vref2, jeżeli Vref1 > Vref2 to znajdowanie się napięcia w zakresie będziesygnalizowanestanemwysokim,wprzeciwnymraziestanemniskim.
detektoraprzejściaprzezzero:zasadniczo dowolny układ (podstawowy, z histerezą, ...) wtedy gdy napięciem z którymporównujemyjestpotencjałzerawoltów(masa)
Przedstawione schematy są dla komparatora z wyjściem NPN (zwierającym do masy). Dlakomparatorówzinnymtypemwyjściamogąwymagaćpewnychmodyfikacji.
Przykłady:LM239;LM393;LM311
CyfrowaAlgebraBoole'aisystemdwójkowypodstawoweoperacjeielementyneutralne
sumalogiczna(OR,+,|) aOR1=1 aOR0=a aORa=a
iloczynlogiczny(AND,*,&) aAND1=a aAND0=0 aANDa=a
negacja(NOT,~,^,!) NOT1=0 NOT0=1 NOT(NOTa)=a
własnościdziałań
łączność (aORb)ORc=aOR(bORc) (aANDb)ANDc=aAND(bANDc)
przemienność aORb=bORa aANDb=bANDa
rozdzielność aAND(bORc)=(aANDb)OR(aANDc)
aOR(bANDc)=(aORb)AND(aORc)
absorpcja aAND(bORa)=a aOR(bANDa)=a
negacjasumyiiloczynu
NOT(aORb)=(NOTa)AND(NOTb)
NOT(aANDb)=(NOTa)OR(NOTb)
pochłanianie aOR(NOTa)=1 aAND(NOTa)=0
dodatkoweoperacje
alternatywawykluczająca(XOR)
aXORb=(aAND(NOTb))OR(bAND(NOTa))
aXOR0=a
aXORa=0
aNANDb=NOT(aANDb) (aNANDb)NAND(cNANDd)=(aANDb)OR(cANDd)
aNORb=NOT(aORb) (aNORb)NOR(cNORd)=(aORb)AND(cORd)
aXNORb=NOT(aXORb)=aXANDb
tabliceprawdy
a b aORb aANDb aNORb aNANDb aXORb aXNORb NOTa
0 0 0 0 1 1 0 11
0 1 1 0 0 1 1 0
1 0 1 0 0 1 1 00
1 1 1 1 0 0 0 1
reprezentacjaliczb
Pojedynczą cyfrę systemu dwójkowego (przybierającą wartość 0 albo 1) określa się mianem bitu,liczbyreprezentowanesąjakociągitakichcyfr.Terminembajtokreślasięzazwyczajciągodługości8bitów(alewniektórychsystemachciągoinnejdługości).
Podstawowymsposobemzapisyliczbcałkowitychnieujemnychwsystemiedwójkowymjestnaturalnykod binarny (NKB), w którym np. 4 bitowy ciąg a3 a2 a1 a0 reprezentuje liczbę20 ⋅ a0+ 21 ⋅ a1+ 22 ⋅ a2+ 23 ⋅ a3.
Podstawowymsposobemzapisyliczbcałkowitych(zeznakiem)jestkoduzupełnieńdodwóch(U2)wktórym n-bitowa liczba reprezentowana przez ciąg an-1 ... a3 a2 a1 a0 będzie miała wartość20 ⋅ a0+ 21 ⋅ a1+ 22 ⋅ a2+ ... + 2n − 2 ⋅ an − 2− 2n − 1 ⋅ an − 1.Jakożenajstarszybitwchodzizujemnąwagą,jegoustawieniena1oznaczaliczbęujemną(aleniejesttokodznaku).WartozauważyćkompatybilnośćzNKB.
Liczby zapisywane w tych kodowaniach systemu dwójkowego oznacza się często przy pomocyprefiksu "0b" albo sufiksu "b", np. 0b101 = 101b reprezentuje liczbę 5 w systemie dziesiętnym (
Vdd
Pull−up
Outctrl1 ctrl2
U1 U2
<=>ctrl1
ctrl2Out
AND
NAND
BUFOR
BUFOR3statezzanegowanymsygnałemaktywacji
BUFOR3state
NORNOT
OR
XNOR
XOR
bramki(AND,OR,XOR,NAND,NOR,XNOR)mogąwystępowaćtakżewwariantachwielo-wejściowych
wwariancie3stanowymmogąwystępowaćtakżewszystkiepozostałeelementy
20 ⋅ 1 + 21 ⋅ 0 + 22 ⋅ 1 = 5).
Opróczpodanychistniejejeszczekilkastosowanychsposobówzapisuliczbbinarnychtakichjak(dlaliczbbezznaku):kod"1zn",kodGraya,kodJohnsona,(dlaliczbzeznakiem):kodznak-moduł,koduzupełnieńdojedności(U1).Odmiennymzagadnieniemjestkodowanieliczbzmiennoprzecinkowych.
zapishexalny(szesnastkowy)
Celem skrócenia zapisu liczb binarnych często zapisuje się je w postaci szesnastkowej, jest onwygodniejszyoddziesiątkowegogdyżkażdacyfrasystemuszesnastkowegorozkładasięnadokładnie4 bity, co pozwala na niezależne konwertowanie poszczególnych cyfr szesnastkowych / ciągów 4bitowychiichłączeniewdłuższeciągi.
Cyfryowartościachpowyżej9zapisujesięjakokolejnemałelubwielkieliterya,b,c,d,e,f.Liczbyzapisywanewsystemieszesnastkowymoznaczasięprzypomocyprefiksu "0x" lub "#"albosufiksu"h" np. 0xc7 = #c7 = c7h reprezentuje liczbę 199 w systemie dziesiątkowym (160 ⋅ 7 + 161 ⋅ 12 = 199).Konwersjanasystembinarnymożeodbywaćsięniezależniedlakażdejcyfry,jakoże:0xc=0b1100oraz0x7=0b0111to0xc7=0b11000111.
reprezentacjaelektryczna
Typowologicznej1odpowiadastanwysoki(napięciedodatnie),alogicznemu0stanniski(potencjałmasy).Wprzypadkulogikiodwróconej(ujemnej)logicznej1odpowiadastanniskialogicznemuzeruwysoki.
Bramki
Bramki są układami elektronicznymi realizującymipodstawowe, opisane powyżej funkcje logiczne. Obokzostały przedstawione podstawowe symboleposzczególnychbramekwwarianciedwuwejściowym,spotkaćsięmożnatakżezsymbolamizzanegowanymiwejściami - w takiej konwencji np. bramka ANDreprezentowana jest przez NOR z zanegowanymiwejściami. Bramki (z wyjątkiem buforów oraz bramkiNOT), mogą występować także w wariantach wielo-wejściowych (ze względu na łączność podstawowychoperacji nie ma wątpliwości co don wyniku jakipowinnadawaćnp.8wejściowabramkaOR).Naogółw pojedynczym układzie scalonym znajduje się kilkajednakowychbramek.
trój-stanowe
Typowabramkawymusza(wsposóbsilny)naswoimwyjściustanwysoki lubniski,couniemożliwiabezpośredniełączeniewyjśćbramek.Bramkitrój-stanowemająmożliwośćskonfigurowaniawyjściawstanwysokiej impedancji czyli nie wymuszania żadnej jego wartości. Sterowanie załączeniem bądźwyłączeniem wyjścia (przełączeniem w stan wysokiej impedancji) odbywa się przy pomocyzewnętrznegosygnałusterującego"outputenabled" ("OE"), sygnał tenmożewystępowaćwpostaciprostejizanegowanej.Pozwalatonapodłączaniedojednejliniiwielubramekidecydowaniuktóraznichbędzieniąsterować.
opencollector/drain
Sąkolejnymrodzajembramekktórychwyjściamożna podłączać do wspólnej linii. Układy teposiadają wyjście w postaci tranzystorazwierającego linię wyjściową do masy, z tegowzględu samodzielnie zapewniają jedynie stanniski wyjścia (są w stanie wymusić stan niski,aleniemająmożliwościwymuszeniastanuwysokiego).
Stanwysokimusizostaćzapewnionyzewnętrznymrezystorempodciągającym.Pozwala tostosowaćnatakiejliniiinnypoziomstanuwysokiegoniżnawejściachtakiejbramkiorazpozwalanasterowaniewspólnejliniiprzezwielebramek(czyliłączeniewyjśćbramek,jednakwodróżnieniuodbramektrój-stanowychniewymagadodatkowychsygnałówsterujących).
Na schemacie obok przedstawiono dwa układy (U1 i U2) typu open-drain sterujące wspólną liniąwyjściową w układzie suma na drucie. Jeżeli jeden z podłączonych do linii układów będzie miałwewnętrznewyjście("ctrlX")wstaniewysokimtojegowyjścieOCbędziezwartedomasy(negacjanatranzystorzeN-MOSlubNPN),wtedyteżcałaliniabędziewstanieniskim.
Vdd
input output
NOT NAND
Vdd
input1 output
input2
Vdd
input1output
input2
NOR TRANSMISYJ NA(bufor3stanowy)
input outputVdd
ster
notster
budowawewnętrzna
Przedstawionypowyżejukładsumynadruciejestbardzo prostą (jedno tranzystorową) realizacjąbramkilogicznejrealizującąfunkcjęlogicznąNOTOR (z punktu widzenia wejść ctrl1 i ctrl2 orazwyjścia Out). W podobny sposób możnazrealizować bramkę AND (negując wejścia, np.przy pomocy jednego traznzystora). Jeszczebardziej uproszczoną realizację można uzyskaćstosując diody pozwalające na wpływanie prądudo węzła (funkcja OR) lub wypływanie z niego(funkcjaAND).
Poprawejprzedstawionezostałyschematyideoweinwertera, dwóch podstawowych bramek (NOR iNAND) oraz bramki transmisyjnej (bufora 3stanowego)wtechnologiiCMOS.
Działanie tych bramek (za wyjątkiemtransmisyjnej)poleganaotwieraniu tranzystorówpodłączonychdonapięciaktórechcemyotrzymaćna wyjściu, a zamykaniu prowadzących donapięcia przeciwnego. W szczególności bramkaNOT stanowi pół-mostek H pomiędzy stanemwysokim a stanem niskim. Dzięki zastosowaniutranzystorówPMOSpolaryzowanychVddorazNMOSpolaryzowanychGNDobiegałęzieoperująnatymsamymsygnalewejściowym(niejestwymaganajegonegacja).Szeregowełączenietranzystorówzapewnia że należy otworzyć oba aby otworzyć daną drogę, a równoległe że otwarcie danej drogipowodowane jest otwarciem pojedynczego tranzystora. Dzięki zastosowaniu technologi MOS ipodłączaniu wejść bramki tylko do bramek tranzystorów wejścia praktycznie nie pobierają prądu(istotnymwyjątkiemjestchwilazmianysygnału).
Działanie bramki transmisyjnej polega na przepuszczaniu lub nie (w zależności od stanu wejściasterującego) sygnału z wejścia na wyjście. Bramka taka nie regeneruje sygnału. Ponadto wuproszczonym (jedno tranzystorowym) rozwiązaniu prowadzi ona do degradacji sygnału wartość wprzybliżeniurównąnapięciuprogowemutranzystora.Dlatego teżnaogółwystępujewrazzbramkąNOT (bufor 3 stanowy z negacją) lub dwiema szeregowo połączonymi bramkami NOT (bufor 3stanowybeznegacji).
wejścieSchmitta
Układy z wejściem Schmitta zapewniającym histerezę sygnału wejściowego stosowane są wprzypadku mało stromych, zaszumionych sygnałów dla których układy z normalnym wejściemmogłybyzmienićkilkukrotniestanwyjścianajednymzboczusygnałuwejściowego.
Przykłady:74HC00 (4x2-inputNAND);74HC1G00 (1x2-inputNAND);74HC20 (2x4-inputNAND);74HC30 (1x8-inputNAND);74HC03(4x2-inputNAND,open-drain);74HC132(4x2-inputNAND,Schmitt);74HC04(6xNOT);74HC1G04(1xNOT);74HC14(6xNOT,Schmitt);74HC1G14(1xNOT,Schmitt);74HC02(4x2-inputNOR); 74HC1G02 (1 x 2-inputNOR); 74HC08 (4 x 2-inputAND); 74HC1G08 (1 x 2-inputAND); 74HC32 (4 x 2-inputOR);74HC1G32 (1 x 2-input OR); 74HC86 (4 x 2-input XOR); 74HC1G86 (1 x 2-input XOR); 74HC7226 (4 x 2-input XNOR);74HC7014(6xSchmitt);
Przerzutnikiirejestryprzerzutnik/zatrzaskRS
RS Flip-flop (RS Latch) jest podstawowym układem służącym do zapamiętania jednego bituinformacji.Posiadaondwawejścia(setireset)idwawyjścia(QiNOTQ),wejściamogąreagowaćnastanwysoki(oznaczanejakoSiR)lubniski(oznaczanejakowejściazanegowane~Si~R), jednozwyjść może być jedynie wewnętrzne (nie wyprowadzone na zewnątrz układu). Podanie stanuwysokiego na wejście S (niskiego na ~S) powoduje wystawienie stanu wysokiego na wyjściu Q, apodanie stanu wysokiego na wejście R (niskiego na ~R) powoduje wystawienie stanu niskiego nawyjściu Q. Stan na wyjściu Q nie zmienia się po zmianie wejść S i R na stan niski (zostajezapamiętany).
Na schemacie przedstawiono dwubramkową budowę przerzutnika RS zarówno w wariancie zwejściaminiezanegowanymijakiwwarianciezwejściamizanegowanymi.
zatrzaskaprzerzutnik
Zatrzask jest elementem reagującym na poziom sygnału na wejściu "enable" (E). W przypadku niezanegowanego wejścia E, jeżeli jest ono w stanie wysokim sygnał na wyjściach (Q i NOT Q) jestfunkcją sygnałówwejściowych,natomiast stanniskiwejściaEblokuje zmianę sygnałuwyjściowego
Q
~Q
E
J
K
Q
~Q
~S
~R
<=>
~S
~R
Q
~Q
R
S
R1
S2
Q 3
Q 4
R1
S2
Q 3
Q 4<=> <=>
Przerzutnik/zatrzaskRS PrzerzutnikRSzwejsciamizanegowanymi
Zatrzask(latch)J K
D1
CLK2
Q 3
Q 4
R5
S6
D1
E2
Q 3
Q 4
R5
S6
D1
E2
Q 3
Q 4
R5
S6
Q
~QCLK
D<=>
PrzerzutnikD
D1
E2
Q 3
Q 4
R5
S6
J1
E2
K3
Q 4
Q 5
R6
S7
J1
E2
K3
Q 4
Q 5
R6
S7
D Q
~QE
Zatrzask(latch)D
<=>Q
~Q
E
D
~S
~R
<=>
(zostajeonzapamiętany).
Przerzutnik jest elementemreagującym na zboczesygnału na wejściu "clock"(CLK). W zależności odkonstrukcji może reagowaćna zbocze narastające,opadającealbonaoba(wtedyna jednym realizuje odczytwejść a na drugim zmianęstanuwyjść).
zatrzaskiprzerzutnikJK
Posiada dwa wejściasygnałowe(JiK)orazwejście"enable" (E) w przypadkuzatrzasku lub wejście "clock"(CLK) w przypadkuprzerzutnika. Może takżeposiadać asynchroniczne(niezależne od stanu wejściaE / CLK) wejścia reset i set(zanegowanelubproste).
J K Qn+1 Opis
0 0 Qn brakzmiany
0 1 0 reset
1 0 1 set
1 1 NOTQn zmianawyjścianaprzeciwny
Stan wejść J = K = 1 dozwolony jest tylko w przypadku przerzutnika, gdyż wtedy sygnał CLKdecyduje o momencie zmiany wyjścia Q na przeciwne. W przypadku zatrzasku, przy wysokim Ewystąpiłybyoscylacjenawyjściu.
Przykłady: 74HC73 (2 x przerzutnik JK, zbocze opadające, wejścia~R); 74HC107 (2 x przerzutnik JK, zbocze opadające,wejścia ~R); 74HC112 (2 x przerzutnik JK, zbocze narastające, wejścia ~S i ~R); 74HC112 (2 x przerzutnik JK, zboczeopadające,wejścia~Si~R)
zatrzaskiprzerzutnikD
Posiada jedno wejścia sygnałowe "data" (D) oraz wejście "enable" (E) w przypadku zatrzasku lubwejście"clock"(CLK)wprzypadkuprzerzutnika.Możetakżeposiadaćasynchroniczne(niezależneodstanuwejściaE/CLK)wejściaresetiset(zanegowanelubproste).ObniżeniesygnałuElubzboczesygnałuCLKpowodujązapamiętanie(iwystawienienawyjściuQ)stanuwejściaD.
Wprzypadkuzaprezentowanejrealizacjiprzerzutnikazdwóchzatrzaskówsygnałwejściowyzostanieodczytanynazboczuopadającymzegaraawystawionynawyjścienazboczunarastającym.
DEQ
DCLK
Q
Przykłady: 74HC74 (2 x przerzutnik D, zbocze narastające, wejścia ~S i ~R); 74HC173 (4 x przerzutnik D, zboczenarastające, sygnał input-enable, wspólny reset i clock, wyjścia Q trój-stanowe); 74HC174 (6 x przerzutnik D, zboczeopadające,wspólnyreseticlock);74HC175(4xprzerzutnikD,zboczenarastające,wspólnyreseticlock,wyjściaQiNOTQ);
rejestry
Mianem rejestru n-bitowego określa się zespół n przerzutników (rzadziej zatrzasków), często zuwspólnionymsterowaniem(sygnałyclock,set,reset,etc)służącydozapamiętanian-bitowejwartości
D1
CLK2
Q 3
Q 4
R5
S6
LOAD
IN0
D1
CLK2
Q 3
Q 4
R5
S6
SerialInput
CLK
...
...
...
INn
D1
CLK2
Q 3
Q 4
R5
S6
SerialOutput
parallel−in,serial−out,asynchronousload
Shift(NotLoad)
SerialInput
CLK...
parallel−in,serial−out,synchronousload
CLEAR
INn
...
SerialOutputD1
CLK2
Q 3
Q 4
R5
S6
D1
CLK2
Q 3
Q 4
R5
S6
IN0
...
serial−in,parallel−outCLEAR
SerialInput
CLK
D1
CLK2
Q 3
Q 4
R5
S6
SerialOutput
...
...
D1
CLK2
Q 3
Q 4
R5
S6
CLEAR
Input
OUT0 OUTn
asynchronouscounter
......
D1
CLK2
Q 3
Q 4
R5
S6
D1
CLK2
Q 3
Q 4
R5
S6
CLEARCLK
D1
CLK2
Q 3
Q 4
R5
S6OUT0 OUTn
parallel(standard)register
...
INnIN0
J1
CLK2
K3
Q 4
Q 5
R6
S7
J1
CLK2
K3
Q 4
Q 5
R6
S7
Input
CLEAR
OUT0
J1
CLK2
K3
Q 4
Q 5
R6
S7
OUT1
J1
CLK2
K3
Q 4
Q 5
R6
S7
OUT2 OUT3
...−>J ,Knextstage
...synchronouscounter
toOUTPUTregister(D0)
toOUTPUTregister(Dn)
(liczby). W zależności odsposobu zapisu i odczytumożnawyróżnić:rejestryrównoległe
Posiadają taką samąliczbęwejśćjakiwyjść,sygnałna i-tymwyjściujest bezpośredniopowiązanyzsygnałemzi-tego wejścia (jestsygnałemzapamiętanym z tegowejścia).
Przykłady: 74HC273 (8bit,zbocze narastające, sygnałreset); 74HC374 (8bit,zbocze narastające, wyjściatrój-stanowe); 74HC377(8bit, zbocze narastające,sygnał reset, sygnał input-enable); 74HCT534 (8bit,zbocze narastające, wyjściatrój-stanowe zanegowane);74HC574 (8bit, zboczenarastające, wyjścia trój-stanowe);74HC373 (8bit, zatrzaskprzeźroczysty w staniewysokim, wyjścia trój-stanowe); 74HC563 (8bit,zatrzask przeźroczysty wstaniewysokim,wyjściatrój-stanowezanegowane);74HC573(8bit,zatrzaskprzeźroczystywstaniewysokim,wyjściatrój-stanowe);
rejestryszeregoweserial-inputZ kolejnymi sygnałami zegarowymi odczytywany jest stan wejścia szeregowego, a stanpoprzedni przenoszony jest do kolejnego przerzutnika w ramach rejestru. W ten sposób po ncyklachzegaran-bitowyrejestrmazapisanąnowązawartość.Częstoposiadazespolonyznimrejestr równoległy zapobiegający zmianie stanu wyjść w trakcie ładowania danych z wejściaszeregowego przepisanie danych z rejestru przesuwnego do rejestru odpowiedzialnego zasterowaniewyjściamisterowanejestosobnymsygnałemzegarowym.
Przykłady:74HC164(8bit,bezrejestruwyjściowego);74HC194(4bit,wejścierównoległe,przesuwaniewprawoiwlewo);74HC195(4bit,wejścierównoległe);74HC594(8bit,zatrzaskwyjściowyzresetem,wyjścieszeregowe,sygnałresetu);74HC595(8bit,zatrzaskwyjściowyzwyjściamitrój-stanowymi,wyjścieszeregowe,sygnałresetu);74HC4094(8bit,zatrzaskwyjściowyzwyjściamitrój-stanowymi,wyjścieszeregowe,zatrzaskwyjściaszeregowego);
rejestryszeregoweparaller-inputserial-outputZ kolejnymi sygnałami zegarowymi na wyjście szeregowe wystawiany jest stan kolejnego zrejestrówwejściowych.Wariantasynchronicznyposiadaosobnysygnałpowodującyodczytwejśćdo rejestru (sygnał działa jak "enable" w zatrzaskach). Wariant synchroniczny posiada sygnałdecydujący o tym czy na zboczu zegara dokonywany jest odczyt wejść czy też przesuwaniezawartościrejestruumożliwiającyodczytzwyjściaszeregowego.
Przykłady: 74HC165 (asynchroniczne wczytanie danych wejściowych, wejście szeregowe, sygnał clock-enable);74HC166 (synchroniczne wczytanie danych wejściowych, wejście szeregowe, sygnał clock-enable); 74HC589(dodatkowy zatrzask wejściowy, asynchroniczne wczytanie danych wejściowych, wejście szeregowe, wyjście trój-stanowe); 74HC597 (dodatkowy zatrzask wejściowy, asynchroniczne wczytanie danych wejściowych, wejścieszeregowe,sygnałclock-enable);
licznikiZ kolejnymi sygnałami zegarowymi zwiększana jest o jeden wartość rejestru. Prostszy wbudowie licznik asynchroniczny ma większe (i w dodatku rosnące wraz z bitowością licznika)ograniczenia dotyczące szybkości zliczania od licznika synchronicznego, ze względu naopóźnieniezjakimdochodzizliczanysygnał(CLK)dokolejnychstopnilicznika.
Przykłady: 74HC93 (2x 4bit synchroniczny, zbocze opadające); 74HC161 (4bit synchroniczny, zbocze narastające,presetwartościąpoczątkową,wejście zezwoleniana zliczanie, sygnał przepełnienia); 74HC163 (4bit synchroniczny,zboczeopadające,presetwartościąpoczątkową,wejściezezwolenianazliczanie,sygnałprzepełnienia);74HC191(4bitsynchroniczny, zbocze narastające, liczącyw górę iw dół - sygnałwyboru,wejście zezwolenia na zliczanie, presetwartością początkową); 74HC192 (4bit synchroniczny, zbocze narastające, liczącyw górę i w dół - osobne zegary,wejście zezwolenia na zliczanie, preset wartością początkową, sygnał przepełnienia przy 9 - BCD); 74HC193 (4bitsynchroniczny, zbocze narastające, liczącyw górę iw dół - osobne zegary,wejście zezwolenia na zliczanie, preset
wartością początkową, sygnał przepełnienia przy 15); 74HC393 (2x 4bit asynchroniczny, zbocze opadające, sygnałresetu);74HC40103(8bitsynchroniczny);74HC4017(dekadowy-wartościodpowiadanumeraktywnegowyjścia,10wyjść); 74HC4020 (14 bitowy asynchroniczny); 74HC4040 (12 bitowy asynchroniczny); 74HC390; 74HC4024;74HC4060;74HC4518;74HC4520;
PrzetwornikiADCiDAC
Przetwornik analogowo-cyfrowe (ADC) służy do konwersji sygnału analogowego na postać cyfrową.Realizowane jest to poprzez pomiar napięcia, na ogół w regularnych odstępach czasowych (celemuzyskania przebiegu sygnału a nie tylko wartości chwilowej). Przetwornik ADC o porównaniubezpośrednim realizowany jest w oparciu o zespół komparatorów analogowych (od ich liczby zależybitowośćdanegoprzetwornika,ale ich liczbanie jestrównabitowości)któreużywająróżnychnapięćreferencyjnych (typowo uzyskiwanych z jednego napięcia referencyjnego poprzez dzielnik). Stan zkomparatorówpodawanyjestnaenkodercelemkonwersjidokodubinarnego.Innestosowanesposobyrealizacji przetworników ADC opierają się o pojedynczy komparator i podawanie na niegonarastającego napięcia referencyjnego oraz zliczanie liczby kroków podnoszenia tego napięcia bądźpodawaniu kolejnych napięć z przetwornika DAC i wyszukiwaniu tego które jest najbliższewejściowemu.
Przetwornikcyfrowo-analogowy(DAC)służydokonwersjisygnałucyfrowegonaanalogowy.Opartyjestnazasadziesumatoranapięć,któregowejściazałączanesąwzależnościodustawienialubniedanegobitu w konwertowanej wartości. Typowo zamiast stosowania różnych wartości napięć i jednakowychrezystorów(jakwsumatorze),stosujesięróżnewartościzałączanychrezystorówijednakowenapięciedoktóregosąpodłączone.
pomiarnapięciaiprądu
Pomiar napięcia realizuje bezpośrednio przetwornik ADC. W przypadku konieczności pomiaruwysokich napięć stosuje się przekładniki napięciowe, będące w istocie transformatorami o dobrzeustalonych parametrach pomiarowych. W przypadku małych napięć konieczne może okazać się ichwzmocnienienp.zużyciemwzmacniaczaoperacyjnego.
Pomiarprądumożebyćrealizowanynakilkasposobów:jako pomiar napięcia na rezystancji włączonej w mierzony obwód; umożliwia pomiar prądówzmiennychistałychpoprzez przekładnik prądowy - transformator włączony szeregowo w obwód lub toroidalnącewkęprzezktórąprzeprowadzony jestprzewodnikwktórymdokonywany jestpomiarprądu(pojedynczeuzwojeniepierwotne);stosujesiętylkodlaprądówprzemiennych(zmiennyprądwprzewodzie powoduje powstanie indukcji magnetycznej która wymusza przepływ prądu wobwodziepomiarowym)zwykorzystaniemefektuHalla (prądmożeprzepływaćbezpośrednioprzezukładpomiarowy,może płynąć pętlą ścieżki umieszczoną z drugiej strony płytki drukowanej niż czujnik efektuHalla lub może być realizowany analogicznie do toroidalnego przekładnika prądowego);umożliwiapomiarprądówzmiennychistałych
Przykłady:ACS712(czujnikprąduACiDCopartynaefekcieHallazwyjściemnapięciowym,opornośćtorupomiarowego1.2mΩ,wersje: 5A (185mV/A), 20A (100mV/A) i 30A (66mV/A); ACS770 (czujnik prądu AC i DC oparty na efekcieHalla zwyjściemnapięciowym,opornośćtorupomiarowego0.1mΩ,wersje:50A,100Ai200A);WCS1800(przekładnikprądowyzwbudowanymczujnikiemprąduACiDCopartymnaefekcieHallazwyjściemnapięciowym,czułość:66mV/A,25AAC/35ADC); WCS1600 (przekładnik prądowy z wbudowanym czujnikiem prądu AC i DC opartym na efekcie Halla z wyjściemnapięciowym,70AAC /100ADC);SS49E (czujnikefektuHalla);SS411P (czujnikefektuHalla);TLE4905L (czujnikefektuHalla);
TransmisjaSterowanieliniąbufory
Buforjesttoukładprzekazującysygnałlogicznyzwejścianawyjście.Buformożesłużyćdo:regeneracjisygnału,uniemożliwieniuwprowadzeniasygnałuzjegostronywyjściowejnawejściową,decydowaniaojegoprzepuszczeniulubnie(trój-stanowy),decydowania o kierunku przepuszczenia sygnału (dwa trój-stanowe albo trój-stanowydwukierunkowy),konwersjinalinięopen-collector/open-drain,negacjisygnału(niektórebuforyrealizująfunkcjęNOT).
Przykłady:74HC125(4bit, trój-stanowy,wyjścieaktywowaneniskim);74HC1G125(1bit, trój-stanowy,wyjścieaktywowaneniskim);74HC126 (4bit, trój-stanowy,wyjścieaktywowanewysokim);74HC1G126 (1bit, trój-stanowy,wyjścieaktywowanewysokim);74HC240(2x4bit, trój-stanowy,wyjścieaktywowaneniskim,odwracający);74HC241(2x4bit, trój-stanowy,wjednejgrupiewyjścieaktywowanewysokimwdrugiejniskim);74HC244(2x4bit,trój-stanowy,wyjścieaktywowaneniskim);
A0
B0
OE
DIR
An
Bn
...
dwukierunkowybufortrójstanowyOE==1&&DIR==0 => BdoAOE==1&&DIR==1 => AdoB
1 X1
3
A
2 X24Y
IN3
IN2
IN1
IN0
OUT1
OUT0
VALIDIN3
OUT0
OUT1
VALID
IN2
IN1
IN0
priority
encoder4to2
<=>
IN0
IN1
OE1
OE2
OUT0
OUT1
OUT2
OUT3
IN1
IN0
OUT1
OUT0decoder2to4
<=>OE1
OE2 OUT2
OUT3
jeżeliIN1,IN2traktowacjakoadres,to:-OE1możnatraktowaćjakosygnalpoprawnosci adresu(HAS_INPUTzencodera)-OE2możnatraktowaćjakolinietransmitujaca danedourzadzeniaopodanymadresie
decoder1to2IN0
OUT0
OUT1
A
X1
X2
Y<=>
multiplexer2to1
trueonlywhenusethisoutput
trueonlywhenusethisoutput
OUT0
OUT1
INPUTtrueonlywhenusethisoutput
trueonlywhenusethisoutput
OUT01 X1
3
A
2 X24Y
1 X13
A
2 X24Y
OUT1INPUT
demultiplekseropartyobufory3stanowe demultiplekseropartyomultipleksery
74HC245 (8bit, trój-stanowy, dwukierunkowy -wejście wyboru kierunku, wyjście aktywowaneniskim); 74HC367 (4bit + 2bit, trój-stanowy,wyjścieaktywowaneniskim);74HC540(8bit,trój-stanowy, wyjście aktywowane niskim, dwasygnałyaktywacji-AND,odwracający);74HC541(8bit, trój-stanowy, wyjście aktywowane niskim,dwa sygnały aktywacji - AND); 74HC7541 (8bit,trój-stanowy, wyjście aktywowane niskim, dwasygnały aktywacji - AND, wejścia Schmitta);74HC05 (6 bit, open-drain, odwracający);ULN2802A (8 bit, open-collector, odwracający,500mA);
enkodery
Enkoder "n to m" jest to układ o nwejściach, który na swoim m bitowymwyjściu wystawia numer (typowo)wejścia o najwyższym numerze, któreznajdujesięwstanieniskim.Możliwesąteż warianty wystawiające numerpierwszego (a nie ostatniego) wkolejności wejścia lub wybierającewejściezestanemwysokim.
Jako że wejścia numerowane sązazwyczaj od zera do 2m to układnajczęściej posiada dodatkowe wyjścieinformująceżektórekolwiekzwejśćjestw stanie aktywnym. Typowo numerwystawiany jest w postaci NKB, alemożliwesąinnekodowania.
Układ pozwala na redukcję ilości wejśćpotrzebnych do obsługi n-bitowegosygnału w którym tylko jeden bit możebyć ustawiony lub w którym możnapozwolićsobienaobsługękolejnychliniiz kasowaniem ich bitu (np. wektorprzerwańzpriorytetyzacją).
Przykłady:74HC148(8to3,priority,activelow);74HC147 (9 + "none" to 4 / 10 to 4, priority,activelow);
dekodery
Dekoder "m to n" jest układem odziałaniuprzeciwnymdoenkodera.Aktywujeonwyjścieonumerzeodpowiadającymwartościnam-bitowym wejściu adresowym. Typowo posiada także wejście zezwolenia na aktywację wyjść, któremoże zostać użyte do podłączenia informacji że którekolwiek z wejść enkodera było w stanieaktywnymlubdopodłączeniasygnałudanychzmultipleksowanejliniicelemjejdemultipleksacji.
Przykłady: 74HC138 (3 to 8, trzy wejścia zezwolenia, odwracający); 74HC238 (3 to 8, trzy wejścia zezwolenia,nieodwracający); 74HC137 (3 to 8 + zatrzask na adresie, odwracający); 74HC237 (3 to 8 + zatrzask na adresie,nieodwracający); 74HC259 (3 to 8 + zatrzask na wyniku, sygnał reset, nieodwracający); 74HC139 (2x "2 to 8", osobnewejściazezwolenia,nieodwracający);74HC154(4to16,dwawejściazezwolenia,odwracający);
(de)multiplekserycyfrowy
Multipleksercyfrowy(jednokierunkowy)nawyjściekopiujestanwskazanego(poprzezadrespodanyna wejście adresowe) wejścia. W przypadku braku sygnału "enable" w zależności od rozwiązaniawyjściepozostaniewstanieniskimlubwysokiejimpedancji.
Demultipleksercyfrowy(jednokierunkowy)tozazwyczajukładdekoderawktórymnawejścieenabledpodany jest sygnał z multipleksowanej linii. Nie wybrane wyjścia pozostają w stanie niskim lubwysokim (zależnie od użycia nieodwracającego lub odwracającego dekodera). Cyfrowedemultiplekseryz3stanowymwyjściemsąrzadkością.Demultipleksacjęmożnarozwiązaćtakżeprzypomocy odpowiednio sterowanych (np. z dekodera adresu) buforów trój-stanowych lub dwu-wejściowychmultiplekserów.
Przykłady:74HC151(1x"8to1",multipleksercyfrowyjednokierunkowy,wyjściaprosteizanegowane);74HC153(2x"4to1", multiplekser cyfrowy jednokierunkowy, wspólne wejścia adresowe); 74HC157 (4 x "2 to 1", multiplekser cyfrowyjednokierunkowy,wspólnewejściaadresowe);
74HC251(1x"8to1",multipleksercyfrowyjednokierunkowy,wyjściatrój-stanoweprosteizanegowane);74HC253(2x"4to 1", multiplekser cyfrowy jednokierunkowy, wyjścia trój-stanowe, wspólne wejścia adresowe, osobne wejścia output-enable); 74HC257 (4 x "2 to 1",multiplekser cyfrowy jednokierunkowy,wyjścia trój-stanowe,wspólnewejścia adresowe ioutput-enable);74LVC1G18 (1 x "1 to 2", demultiplekser cyfrowy jednokierunkowy, wyjścia trój-stanowe, można zastąpić układempołączonych74HC1G125z74HC1G126);
(de)multiplekseryanalogowy
Multiplekser analogowy (dwukierunkowy) działa na zasadzie przełącznika łączącego wskazanewejście z wyjściem, dzięki elektrycznemu "zwarciu" (na ogół rezystancja takiego zwarcia tokilkadziesiątomów)wejściazwyjściemtransmisjamożeodbywaćsięwobukierunkach.Pozwalatotakżenawykorzystanietegosamegoukładuwrolimultiplekseraidemultipleksera.
Przykłady: 74HC4053 (3 x "2 to 1 / 1 to 2",multiplekser analogowy dwukierunkowy, osobnewejścia adresowe, wspólnewejście enable, trój-stanowy); 74HC4052 (2 x "4 to 1 / 1 to 4",multiplekser analogowy dwukierunkowy,wspólnewejściaadresowe ienable, trój-stanowy);74HC4051 (1x "8 to1 /1 to8",multiplekseranalogowydwukierunkowy, trój-stanowy);74HC4067(1x"16to1"/1to16",multiplekseranalogowydwukierunkowy,trój-stanowy);74HC4066 (4 x analog switch on-off, dwukierunkowy, osobne wejścia sterujące); 74HC1G66 (1x analog switch on-offdwukierunkowy);DG212B(4xanalogswitchon-off,dwukierunkowy,osobnewejściasterujące);
Mediumtransmisyjne
Mianem medium transmisyjnego określa się nośnik informacji służący do łączności pomiędzysystemami.Wyróżnićmożnanastępującemediatransmisyjne:
przewódelektryczny,m.in.:zwykłyprzewód,naogółwielożyłowy(tzw"taśmy",przewodytelefoniczne)kabeltypuskrętka(takżewróżnychwariantachekranowania)kabelwspółosiowy(koncentryczny)kabelsymetryczny"twin-lead"
światłowód:wielomodowyjednomodowy
bezprzewodowe(zarównoradiowejakioptyczne):dookolne(izotropowe)kierunkowe(wszczególnościoptycznelinielaserowe)
W przypadku przewodów typu skrętka stosowana jest transmisja różnicowa to znaczy informacjakodowana jest w różnicy napięć pomiędzy dwoma przewodami wchodzącymi w skład pojedynczejskręconejpary.Żadenzprzewodówwchodzącychwskładparyniejestpowiązanyzpotencjałemmasy,niema teżznaczeniaróżnicapotencjałupojedynczegoprzewoduwstosunkucodomasy (ważna jesttylko wzajemna różnica potencjałów), sygnał nadawany w jednym z nich jest w przeciw-fazie dosygnału nadawanego w drugim. Służy to eliminacji zakłóceń elektromagnetycznych (zakłócenieindukujesięwobuprzewodachjednakowo,więcróżnicanieulegazmianie)orazzakłóceńwzajemnych,przesłuchów (sumaryczny prąd płynący parą jest bliski zeru). Typowo linie takie korzystają zdedykowanychukładównadawczo-odbiorczychopartychnazasadziewzmacniaczaróżnicowego.
Połączeniaświatłowodowecharakteryzująsięm.in.:pełnąseparacjągalwaniczną(opto-izolacją)pomiędzyłączonymisystemamibardzodużąodpornościąnazakłóceniadużąprzepustowościąidużąprędkościątransmisjimożliwością bezpośredniej (bez stosowania wzmacniaczy umieszczonych w środku linii)transmisjinabardzodużeodległości
Topologiapołączeńitypytransmisji
Obokprzedstawionezostałygłównetopologiepołączeń:linearbus(magistrala)
wszystkie urządzenia są podłączone do jednej linii (wspólnego medium transmisyjnego),okablowanieniewyróżniapunktucentralnego
daisychainstruktura okablowania podobna jak w magistrali, ale medium transmisyjne jest podzielone(połączenienurządzeńskładasięzn-1łączypunkt-punktpomiędzyurządzeniami)
ring(pierścień)topologiadaisychainwktórejkońcesąpołączone,uodparniatonapojedynczeuszkodzenie
star(gwiazda)wszystkie podłączenia biorą początek w węźle centralnym, w zależności od konstrukcji węzła
Dev#1
Linearbus
Dev#2 Dev#n...
Dev#1
DaisychainDev#2 Dev#n...
Dev#1
Dev#2
Dev#n
Central HUB
Star
...
Dev#1
RingDev#2 Dev#n...
Dev#1
Dev#2
Dev#4
Mesh
Dev#3
Dev#5
Dev#6
dekoderadresu
DANE/ADRES,n-bitów
Adres/NotDane
Read/NotWrite
Clock
kontrolermagistrali/master
1(TRUE)gdy
adreszgodny
DataOUT
WR
RD
sygnałyread(RD)iwrite(WR)wyrażonezpunktuwidzeniapodłączonegourządzenia: WR=zapisnamagistralę RD=odczytzmagistrali(częstoprzedstawianesazpunktuwidzeniamagistrali)
wprzypadkurozdzielonychliniidanychiadresu: -zamiastsygnału"Adres/NotData" jestm-bitowaszynaadresowa -dekoderadresuniekorzystazliniidanych tylkozszynyadresowej Da
taINŻądanieobsługi,i-bitów
Vcc
1
2
3
sygnał
przerwania
wybranyzestawbitówIRQ
ClockIN
centralnego może byćrealizowana w oparciu owspółdzielonemedium lubpołączeniapunkt-punkt
mesh(krata)każde urządzenie mabezpośrednie połączeniepunkt-punkt do każdegoinnego urządzenia(połączenie n urządzeńwymaga n(n-1)/2 połączeńpunktpunkt)
Ponadto występują topologiemieszane złożone z opisanychpowyżej: gwiazda wielokrotna(tzn. takagdzieniektórezwęzłówstanowiąpunktycentralnekolejnychgwiazd),magistrala lub ringpomiędzy punktami centralnymi gwiazd, gwiazda w której w węzłach występują magistrale lubpierścienie,itd.
Wyróżnićmożnatypytransmisji:simplex
umożliwiatylkotransmisjęjednokierunkowąhalf-duplex
umożliwiatransmisjędwukierunkową,aletylkowjednąstronęrównocześniefull-duplex
umożliwiapełnątransmisjędwukierunkową(równoczesnenadawanieiodbiór)
Magistralarównoległa
Magistrala równoległa jestzespołem linii, wraz zukładami nimi sterującymi,umożliwiającym równoległeprzesyłanie danych (wjednymczasie/takciezegarana magistrali wystawiane /przesyłane jest całe n-bitowesłowo). Można wyróżnićszyny sterującą (kierunekprzypływu, żądania obsługi,etc), adresową (adresukładuktóry ma prawo nadawać) idanych (przesyłane dane).Często szyna adresowawspółdzieli linietransmisyjnez szynądanych.Do realizacjimagistrali (celemumożliwiania podłączeniawielu układów) stosuje sięzazwyczaj bufory trój-stanowe, a do zapewnienia współdzielonej szyny żądania obsługi (interruptrequest)częstoukładytypuopen-collector.
Typowyukładrealizacjimagistralihalf-duplexzewspółdzielonymiliniamidanychiadresuprzestawionyzostałnaschemaciezamieszczonymobok.Zadaniem dekodera adresu jest ustalenie czy wystawiony na magistrali adres (w trakcie wysokiegostanulinii"Adres/NotDane")jestadresemdanegourządzeniaizapamiętanietejinformacjidoczasuwystawienia nowego adresu. Informacja ta jest wykorzystywana do sterowania dwukierunkowymbuforemtrój-stanowym(jakosygnałenable).O kierunku działania bufora decyduje sygnał "Read / Not Write". Przy magistralach o ustalonymprotokole transmisyjnym sterowanie kierunkiem może być zależne od wykonywanej komendy (poustawieniu adresu urządzenie odczytuje z magistrali polecenie i w zależności od niego sterujekierunkiembufora-odczytujelubzapisujedanenamagistralę).ZastosowaniekilkuliniitypuOCdoodbieraniażądańobsługipozwala(napodstawietegoktóreztychlinii znalazły się w stanie niskim na identyfikację urządzenia lub grupy urządzeń, z której niektórezgłaszajążądanieobsługi.
W przypadku prostych urządzeń wejścia / wyjścia zamiast buforu dwukierunkowego może byćumieszczony np. jednokierunkowy bufor (lub n-bitowy rejestr) z wyjściami trój-stanowymi, którywystawiadanenamagistralęwoparciuosygnałzapisunamagistralę(WR)orazzegar(clock)albon-
dekoderadresu
DANE
Adres
Strobekontrolermagistrali/master
1(TRUE)gdyadreszgodny
rejestrprzesównyclkserial_in
Clock
buforwyjściowyclk
clkserial_in
clk
serial_out
rejestrprzesówny
buforwyjściowy
bitowyrejestrdoktóregozapisywanesądanezmagistraliwoparciuosygnałRDiClock.
Magistralaszeregowa
W magistrali szeregowej daneprzesyłane są bit po bicie wpojedynczej linii. Podobnie jak wmagistrali równoległej oprócz liniidanych mogą występować także liniesterujące. Prostą realizację magistraliszeregowej zapewniają rejestryprzesuwne.
Przykładowy układ realizacjimagistrali simplex (jednokierunkowej)z rozdzielonymi szynami danych iadresową został na schemaciezamieszczonymobok.W prezentowanym przykładzie opróczadresumasterwystawiatrzysygnały-dane,zegaristrobe.Zkażdymtaktemzegaranaliniidanychwystawianyjestkolejny bit który jest wczytywany dozespołurejestrów.Sygnałstrobesłużydoprzepisaniawartościzrejestrówprzesuwnychdorejestrówwyjściowych, takie rozwiązanie zapobiega zmianom wyjść w trakcie przesyłania nowych danychpoprzezszynęszeregową,jestonojednakopcjonalne.
Wzależności odkonstrukcji dekoderaadresu szynaadresowamożebyć równoległa (wnajprostszymprzypadku-przezcałątransmisjędodanegourządzeniajegoadresmusibyćwystawionynaszynieadekoder jestukładembramekNOTiwielowejściowejbramkiAND) lubszeregowa(wtakimwypadkupowinna posiadać własny zegar lub sygnał informujący o nadawaniu adresu z taktami zegaragłównego,adekoderpowinienbyćwyposażonywrejestrprzesuwnydoodebrania iprzechowywaniaaktualnego adresu z magistrali). Natomiast jeżeli magistrala byłaby oparta tylko na połączonychszeregoworejestrach(wyjścieserial-outdowejściaserial-in)toszynaadresowaniejestpotrzebna,alekoniecznemożebyćkażdorazowewpisaniewszystkichwartościnaszynę(czaszapisurośniezilościąpodłączonychrejestrów).
Standardoweinterfejsy
Istnieje wiele zestandaryzowanych interfejsów zarówno szeregowych jak i równoległych, wśródnajważniejszychnależywymienić:SPI(SerialPeripheralInterface)
jest to szeregowa magistrala full-duplex działająca w układzie master-slave złożona z liniizegarowej (SCLK), nadawania przez mastera (MOSI), odbioru przez mastera (MISO) oraz liniisłużącychdoaktywacjiurządzeniaslave(SS/CS).
I2C(TWI)jest to szeregowa magistrala half-duplex złożona z linii sygnałowej (SDA) i zegara (SCL)posiadającazdefiniowanyformatramkiwrazzadresowaniem.Zwyjątkiembitustartuistopustanliniidanychmożezmieniaćsię tylkoprzyniskimstanie liniizegarowej.Nadajnikisą typuopen-drainprzezcorealizowanyjest iloczynnadrucie,copozwalanawykrywaniekolizji (jeżelidanynadajniknienadajezeraaliniajestwstaniezeratonadajetakżektośinny).Pozwalatotakżenauzyskanie układów multimaster, pomimo iż typowo na magistrali takiej występuje tylko jedenukładmaster(nadającysygnałzegaraiinicjującytransmisję).
1wire(one-wire)jest to szeregowamagistralahalf-duplex złożona z jedynie z linii sygnałowej (któramoże takżesłużyć do zasilania urządzeń) posiadająca zdefiniowany format ramki wraz z adresowaniem.Standardowenadawaniejestrealizowanejakoopen-drain(wyjątkiemjestnadawanietzwpower-byte).
USARTjest to uniwersalny synchroniczny i asynchroniczny nadajnik i odbiornik, umożliwia realizacjęszeregowej transmisji synchronicznej (zgodnie z zegarem) lub asynchronicznej (wykrywaniepoczątku ramki na podstawie linii danych). Interfejs korzysta z rozdzielonych linii nadajnika iodbiornika(wyjściedanychTxDorazwejściedanychRxD,coumożliwiarealizacjętransmisjifull-duplex) oraz może korzystać z dodatkowych sygnałów sterujących (wyjście RTS informujące ogotowości do odbioru oraz wejście CTS informacji o gotowości odbioru / zezwolenia nanadawanie).Niekiedydostępnejesttakżewyjściezałączenianadajnikaużywanedopracywtrybiehalf-duplex(linieTxDiRxDpołączonebuforemtrój-stanowymnadajnika).
Interfejs ten najczęściej wykorzystywany jest w trybie asynchronicznym jako UART. WpołączeniachUARTzarównonadajnikjakiodbiornikmusząmiećustawionetakiesameparametry
transmisji(szybkość,znaczenie9bitu(typowobitparzystości,alemożetakżeoznaczaćnp.poleadresowe), itp). Głównymi standardami elektrycznymi dla UART są: poziomy napięć układówelektronicznych używających tych portów (3.3V, 5V), RS-232 (w pełnym wariancie używasygnałówkontroliprzepływu,poziomlogiczny1wynosiod -15Vdo -3V,apoziomlogiczny0od+3V do +15V), RS-422 (transmisja różnicowa full-duplex pomiędzy dwoma urządzeniami) i RS-485 (transmisja różnicowahalf-duplexwoparciuo szynę łączącąwieleurządzeń, kompatybilnyelektryczniezRS-422),możliwiajestteżtransmisjaświatłowodowaibezprzewodowa.
CANjest to dwu przewodowa magistrala multi-master działająca na zasadzie rozgłoszeniowej,obsługująca11-tolub29-bitoweidentyfikatorykomunikatów(niesątoadresyodbiorców),bazujenaniejwieleprotokołówkomunikacyjnych(np.CANopen).
Ethernetjest to interfejs szeregowy przeznaczony dla sieci komputerowych, występuje w różnychodmianach od których zależy wykorzystywane medium transmisyjne oraz topologia połączeń.Posiadaustalonyformatramki(niezależnyododmiany)wrazzadresacją(ramkazawierazarównoMACadresnadawcy,jakiodbiorcy).
W przypadku połączeń przewodowych (zarówno elektrycznych jak i optycznych) najczęściejstosowane są połączenia punkt-punkt w topologii gwiazdy, można się także spotkać z układemtypuring.Pętlewtopologiifizycznejsązabronioneiwprzypadkuichwystąpieniakoniecznejeststosowanieprotokołuichwykrywaniairozłączania(dotyczytotakżepołączeniatypuring).
Typowo połączenia fizyczne realizowane są z wykorzystaniem switchy odpowiedzialnych zaprzesyłanierameknaodpowiednieportywoparciuoadresyMAC.Wtymceluswitchpamiętazktórego portu przychodzą ramki z danym adresem źródłowym i tam wysyła ramki z takimadresemdocelowym, jeżeliswitchnieposiada informacjigdziewysłaćdanąramkęwysyła jąnawszystkieswojeporty.
ISAmagistralarównoległastworzonadlaarchitekturyPC(x86),początkowoz8-bitowąszynądanychiniezależną 20 bitową szyną adresową, następnie rozszerzona do 16 bitowej szyny danych i 24bitowejszynyadresowej,wariancie16bitowymtaktowanazegarem8Mhz(wcześniej4.77Mhz,anastępnie6Mhz).W skład magistrali wchodzą m.in. następujące sygnały sterujące związane z szyną adresową iszynądanych:
ALE-poleceniezatrzaśnięciaadresu/adrespoprawny(wystawianeprzezCPU)IOR/IOW-odczyt/zapiswprzestrzeniIO(2osobnesygnaływystawianeprzezCPU)MEMR/MEMW-odczyt/zapiswprzestrzenipamięci(2osobnesygnały,wystawianeprzezCPU)IOCHRDY-rządanieopóźnieniawobsłudzeodczytu/zapisu(wystawianeprzezkartę)IOCS16/MEMCS16-informacjaoobsłudzewtrybie16bitowym(wystawianeprzezkartę)DRQ*,DACK*,AEN,TC-sygnałyDMA
Ponadto złącze magistrali zapewnia dostęp do 6 (w podstawowej 62 stykowej części złącza) +dodatkowych 5 (w rozszerzającej do 16 bitów 36 stykowej części złącza) linii przerwań IRQ*,sygnału MASTER pozwalającego na przejęcie sterowania nad systemem przez procesorumieszczonynakarcie oraznapięć zasilających+12V, -12V,+5V, -5V, kilku liniimasy (GND) izegarasystemowegoorazzegarasynchronizowanegozzegaremprocesora.
Magistrala (w innej postaci złącza) obecna jest także w standardzie PC/104. Standard EISAokreślarozszerzoną,kompatybilnąwdół(takżepodwzględemgniazda),wersjęz32bitowąszynądanych.
PCImagistralarównoległawystępującawodmianie32i64bitowej,kilkasygnałówzwiązanychz arbitrażem prowadzonych jest do każdego gniazda / urządzenia PCI bezpośrednio zkontroleramagistrali,linie przerwań są poprzeplatane między slotami, specyfikacja dopuszcza też przerwaniasygnalizowanewramachkomunikatu(przesyłanegoszynądanych);stosowanie mostków PCI pozwala na rozgałęzianie / łączenie magistrali (zarównoszeregowojakirównolegle);często spotykane są karty PCI o niepełnych wymiarach (prawie zawsze krótsze odmaksymalnej dopuszczalnej długości, często także niższe), magistrala PCI jest takżespotykanawramachinnychtypówzłącz-takichjakMini-PCI,czyPCMCIA
PCIExpressszeregowy interfejs różnicowy full-duplex do połączeń punkt-punkt, w zależności od
wariantuzłożonyz1,4,8lub16zestawówparnadawaniaiodbioru;stosowanie mostków pozwala na rozgałęzianie / łączenie magistrali oraz np. podłączanieklasycznychmagistralPCI;standardowe złącze zapewnia także m.in. sygnał zegara referencyjnego, resetu, sygnałySMBus(I2C);standardwystępujenakilku rodzajachzłącz (oprócz standardowego) takżem.in.miniPCIExpress,SATAExpress,M.2,Thunderbolt/USB-C.
IDE,ATA,P-ATAwywodzącysięzmagistraliISAstandardsłużącyzapewnieniukomunikacjizurządzeniamipamięcimasowejtakimijakdyskitwarde,czynapędyoptyczne;określatakżepełnyprotokółkomunikacjizurządzeniami;stosowanytakże(zniewielkimizmianami)wkartachCompactFlash.
SATAszeregowy interfejs różnicowy full-duplexdopołączeńpunkt-punkt, złożony z jednejparynadawczej,jednejparyodbiorczejorazliniiGND;służący do podłączania urządzeń pamięci masowej takich jak dyski twarde, czy napędyoptyczne;standardSATAokreślatakżepełnyprotokółkomunikacjizurządzeniami;standard występuje na kilku rodzajach złącz - oprócz standardowego także m.in. eSATA(zewnętrzne),mSATA,SATAExpress,M.2.
USBszeregowy interfejs różnicowy half-duplex do połączeń punkt-punkt posiadający (wwersjachdo2.0włącznie)jednąparęużywanazarównodonadawaniajakiodbioru;pozwalanatworzenietopologiigwiazdyzwykorzystaniemhub'ówUSB;stosujekilkarodzajówzłączorazwystępujewramachzłączinnychstandardów(np.wM.2).
TMDS,HDMI,DVITMDS jest standardem jednokierunkowej różnicowej transmisji szeregowej, stosowany winterfejsachHDMIiDVI-D;korzystazosobnejparyróżnicowejdlakażdegokoloruskładowegoRGB(lubYCbCr)orazosobnejparydladanychzegarowych;pomocniczo (dla dwukierunkowego przekazywania parametrów kontrolnych/sterującychzwiązanych z trybem wyświetlania) wykorzystywany jest także dwuprzewodowy interfejsDDCopartynaI2C;danewkanałachTMDSprzesyłanesąwpostaci (zakodowanychprzypomocy8b/10b)10bitowychciągów,któremogąbyć interpretowane jako8bitowawartośćkoloru,2bitowawartość sterująca (na kanale zerowym wykorzystywane do synchronizacji poziomej ipionowej);złącze DVI pozwala na przesyłanie dwóch kanałów cyfrowego wideo (6 kanałów TMDS)oraz przesyłanie analogowego sygnału VGA (RGB, Hsync, Vsync), standard DVI zakładawykorzystaniełączTMDSdoprzesyłaniawyłącznieobrazuRGB;standardHDMIpozwalanaprzesyłaniezużyciemTMDSobrazuRGBabloYCbCr,ponadtostandard HDMI korzystając z bitów sterujących transmisji TMDS i kodowania 4b/10pozwala na przesyłanie poprzez TMDS dźwięku oraz danych sterujących CEC, ponadtozłączeHDMIpozwalanaprzesyłanie (osobnąparą) zwrotnegosygnałuaudio lub sygnałuEthernetowego;
DisplayPortinterfejs złożony z 1 do 4 szybkich jednokierunkowych kanałów różnicowej transmisjipakietowejoraz1dwukierunkowegokanałupomocniczego(takżeztransmisjąróżnicową)wersja"Dual-mode"(DisplayPort++)pozwalanaprzesyłaniesygnałówzgodnychzHDMI/jednokanałowymDVI-DwystępujetakżewzłączuThunderbolt/USB-C
UkładyprogramowalneUkładyprogramowalnemożnapodzielićnadwarodzaje:układyoprogramowalnejstrukturze(PLD)
toukładywktórychprogramowanyjestukładbramek,przerzutników,itp."umieszczanych"wkościorazichpołączeń.Programdla takichukładów tworzony jestwHardwareDescriptionLanguage (najczęściejVHDLlub Verilog) i zamiast wykonywanego kodu opisuje strukturę układu logicznego (połączenia
bramek,tabliceprawdy,etc),któranastępniejestprogramowanawfizycznejkości.
Najprostszym przykładem układu o programowalnej strukturze logicznej jest układ pamięci 2n
bitowejzn-bitowąszynąadresowąadresującąpojedynczebity-pozwalaonnarealizacjędowolnejfunkcjilogicznejonwejściachipojedynczymwyjściu.
Dokategoriitejzaliczająsięukładytypu:SPLD
PLE-programowalnamatrycabramekORPALiGAL-programowalnamatrycaANDzdodatkowymibramkamiOR(częstotakżeobudowanarejestramiimultiplekseraminawyjściach)PLA-programowalnematryceANDiOR
CPLDFPGA-programowalnyelementpamięciowy(możliwośćzdefiniowaniadowolnej-naogół4wejściowej - funkcji w każdym elemencie logicznym, programowalne połączenia międzyelementamilogicznymiipinami,itd)
systemyprocesorowetosystemyrealizująceciąginstrukcjipobieranychzjakiejśpamięci.System taki składa się z procesora odpowiedzialnego za interpretację i wykonywanie kolejnychinstrukcjiorazpamięcizktórejpobieranesąinstrukcjeidane(możetobyćjednapamięć,mogątobyć rozdzielone pamięci). Do kategorii tej zaliczają się zarówno typowe systemy komputerowe,systemyobliczeniowejakiróżnegorodzajuprogramowalnemikrokontrolery.
Procesor pracuje w cyklach rozkazowych, w ramach których przetwarza pojedynczą instrukcję.Cykltakimożetrwaćod1dokilkulubwięcejcyklizegarowychitypowoskładasięznastępującychkroków:
1. pobranie instrukcji z pamięci - realizowane jest poprzez wystawienie na szynę adresowązawartości licznika programu (zawierające adres instrukcji do wykonania) orazwygenerowanie cyklu odczytu z pamięci, po wykonaniu odczytu danych następuje ichzapamiętaniewrejestrzeinstrukcjiorazzwiększeniewartościlicznikaprogramuojeden;(zawartość rejestru licznikaprogramu po resecieprocesoraokreśla skądpobieranabędziepierwszainstrukcja,podtakimadresemzazwyczajumieszczanajestjakaśpamięćtypuROMlubflash)
2. dekodowanie instrukcji - układ dekodera (np. oparty o PLA) dokonuje zdekodowaniainstrukcji znajdującej sięwrejestrze instrukcji ikonfiguracjiprocesorawzależnościod jejkodui(opcjonalnie)jejargumentów;możetobyćnp.:
odpowiednie ustawienie multiplekserów pomiędzy rejestrami a jednostką ALU orazwystawienie odpowiedniego kod operacji dla ALU (celem wykonania operacjiarytmetycznejnawartościachrejestrów)wystawienie zawartości wskazanego rejestru na szynę adresową, podłączeniewskazanego rejestru do szyny danych oraz skonfigurowanie operacji odczytu/zapisu(celemwykonaniaodczytulubzapisuwartościrejestruz/dopamięci)
3. wykonanie instrukcji - realizacja wcześniej zdekodowanej instrukcji zgodnie z ustawionąkonfiguracjąprocesora
Instrukcje skoku polegają na załadowaniu nowej wartości do licznika programu, w przypadkuskokówwarunkowych jest touzależnioneod stanu rejestru flag, któreustawiane sąwoparciuowynikostatniejoperacjiwykonywanejprzezALU.Przedstawionymodeldziałaniajestprzykładowymiwrzeczywistymprocesorzemożetowyglądaćodmiennie-np.długośćinstrukcjimożebyćwiększaniżdługośćsłowaużywanegoprzezprocesor/szerokość szyny danych co rozbudowuje fazę pobierania instrukcji z pamięci, mogą występowaćinstrukcjebardziejzłożone(np.operacjewykonywanezargumentempobieranymzpamięcianierejestru),możetakżewystępowaćwięcejfaz(np.poprzezwydzieleniefazdostępudopamięci,czyzapisywaniawynikówdziałania instrukcji).Procesormoże takżedziałaćpotokowo,czylinakładaćnasiebiekolejnefazywykonywaniaróżnychinstrukcji(np.wczasiewykonywaniajednejinstrukcjirealizowaćpobieraniekolejnej).
Mikrokontrolery
Mikrokontrolerjestukłademtypu"SystemonChip"zawierającymwjednymukładzieprocesor,pamięćRAM, układy wejścia-wyjścia (np. GPIO, porty szeregowe typu USART, SPI, I2C, przetworniki ADC),pamięćtypuFlash(dlaprogramu).
Przykłady:ATmega8A(ADC(6-8ch),3xTimer,I2C,USART,SPI,28-32pin,8kBFlash,1kBRAM,8bit,16MHz),STM32F072V8(1xADC(12ch),1xDAC(2ch),12xTimer,2xI2C,4xUSART,2xSPI,CAN,USB,100pin,64kBFlash,16kBRAM,32bit,48MHz),STM32F103VC(3xADC(21ch),2xDAC,11xTimer,2xI2C,5xUSART,3xSPI,CAN,USB,100pin,256kBFlash,48kBRAM,32bit,72MHz)iwieleinnych
ProgramowanieZagadnieniasą ilustrowaneprzykładowymikodamiwjednymlubkilkuzpośródnastępujących języków:C++(niekiedyzpodziałemnapodejściewstyluCiwstyluC++),Python,Bash,PHPiJavaScript.Wybórtakiegozbiorujęzykówwynikazodmiennychcechkażdegoznich:
C++/Csąnajpopularniejszymijęzykamikompilowanymidokodumaszynowego(ajeżelitraktowaćje łącznie to najpopularniejszymi językami w ogóle), pozwalają na stosowanie niskopoziomowychmechanizmów (łącznie z wstawkami asemblerowymi), są użyteczne do bezpośredniegoprogramowania sprzętu (bez warstwy systemu operacyjnego) czy też tworzenia systemówoperacyjnychPython -najpopularniejszy język skryptowy,wygodny (wmiarę łatwy / szybki)wpisaniu i nauce,oferujebardzowielegotowychbibliotek,pozwalanadośćprostąintegracjęzkodemC/C++Bash - najpopularniejsza powłoka tekstowa, stanowiąca jednocześnie (specyficzny) językprogramowaniaPHP-popularnyiwygodnyjęzykdotworzeniaserwisówwwwJavaScript-najpopularniejszyjęzykskryptowydlaWWW,elementHTML5
Ponadto każdy z tych języków wykorzystywany jest w wielu projektach (od jądra Linuxa do systemuMediaWiki)iichprzynajmniejzgrubnaznajomośćmożeokazaćsięprzydatna.
Język C++ oraz C są językami kompilowalnymi to znaczy (po zmodyfikowaniu źródeł) przeduruchomieniemprogramukoniecznejestdokonanietłumaczeniakoduźródłowegonakodmaszynowyprzypomocyodpowiedniegoprogramu(np.clang++ lubg++).KompilacjaC iC++przebiegakilkuetapowo.Wpierwszej kolejności wywoływany jest preprocesor, który jest odpowiedzialny za włączanie plikówokreślonychpoprzez#include (jestto literalnewłączeniezawartościwskazanegoplikuwdanymmiejscu,obsługę rozwijania stałych makr preprocesora (definiowanych z użyciem #define) oraz kompilacjęwarunkowązwykorzystaniempoleceńtakich jak#ifdefczy#if.Kompilatorypozwalająnauzyskanienietylko wynikowego pliku binarnego, ale także plików po przetworzeniu przez preprocesor czy też pokonwersjinaassembler.
Python,BashiPHPsąjęzykamiinterpretowanymi,czyliuruchamianiupodlegabezpośredniokodźródłowyktóry jest analizowany i wykonywany przez interpreter danego języka. Mogą one uruchamiać kod zpodanegoplikulubinteraktywniewprowadzanywkonsoliinterpretera.Kodwprowadzanyinteraktywniemoże być wykonywany bezpośrednio po jego wprowadzeniu (tzn. wprowadzeniu znaku nowej linii, a wprzypadku bloków instrukcji - zakończenia takiego bloku). W Bashu i Pythonie jest to zachowaniedomyślne,natomiastwprzypadkuPHPwymagapodaniaopcji-a (jejpodaniezakładażepodawanykodjest tylko częścią ujętą w <?php i ?>, bez tej opcji kod zostanie zinterpretowany i wykonany dopiero powczytaniuznakukońcapliku,którymożnawprowadzićCtrl+D).
Zarównokompilatoryjakiinterpreterymogągenerowaćbłędylubostrzeżeniadotycząceprzetwarzanegokodu,przyjegopoprawianiuważnejestichczytaniezpróbązrozumienia(niekiedypotrafiąbyćdziwneiodnosićsięniedotegocojestprzyczynąproblemu).Rozwiązującproblemnależyskupićsięnapierwszymbłędzie,gdyżkolejnemogąbyćjegowynikiem(jesttoszczególnieważnewprzypadkukompilacjiC++/C,gdzie możemy uzyskać bardzo wiele błędów). Programy mogą także generować błędy typu "run timeerror" w trakcie działania, przykładami takich błędów są rzucane i nie obsługiwane wyjątki oraz błędyzwiązanezodwołaniamidopamięci (np.przekroczeniemzakresutablicywC)komunikowanezazwyczajjako"Segmentationfault".
Pamięćdanych-zmienneWszelkiedanenaktórychoperujeprogramkomputerowyprzechowywanesąwjakimśrodzajupamięci-najczęściej jest topamięćoperacyjna.Wpewnychsytuacjachniektóredanemogąbyćprzechowywanenp.tylkowrejestrachprocesoralubrejestrachurządzeńwejścia-wyjścia.
Wprogramowaniunapoziomiewyższymodkodumaszynowegoiasembleraużywasiępojęciazmienneji(niemal zawsze) pozostawia kompilatorowi/interpretatorowi decyzję o tym gdzie ona jestprzechowywana.Oczywistymwyjątkiemsągrupyzmiennych,czyteżbuforyalokowanewsposóbjawnywpamięci.Zewzględunaograniczonąliczbęrejestrówprocesorawiększośćzmiennych(wszczególnościtychdłużej istniejącychiwiększych)będzieznajdowałasięwpamięci ibędąprzenoszonedorejestrówcelemwykonaniajakiśoperacjinanichpoczymwynikbędzieprzenoszonydopamięci.
Zkażdązmiennąprzechowywanąwpamięcizwiązanyjestadrespamięcipodktórymsięonaznajduje.Niektóre z języków programowania pozwalają na odwoływanie się do niego poprzez wskaźnik nazmienną lubreferencjędozmiennej (odwołaniadoadresuzmiennejmogąwymusićumieszczenie jejwpamięcinawetgdybynormalnieznajdowałasiętylkowrejestrzeprocesora).
Wszystkiedanesązapisywanewpostaciliczblubciągówliczb.Typzmiennej(jawnylubnie)informujeotymjakiejdługościjestdanaliczbaijaknależyjąinterpretować(jaknależyinterpretowaćciągliczb).
intmain(){ //liczbacałkowitazeznakiem intliczbaA=-34; //liczbarzeczywista(pojedynczejprecyzji) floatliczbaB=673.1; //8bitowaliczbacałkowitabezznaku uint8_tliczbaC=0xf3; //zmiennanapisowa"CNULL-endstring" char*napisA="qwe"; //zmiennanapisowatypu"C++string" std::stringnapisB="abc";}
#dynamicznetypowanie-typokreślanyjest#napodstawiewartościzapisywanejdozmiennej
zmiennaA=-91.7zmiennaB="qaz"
#dynamicznetypowanie-typokreślanyjest#napodstawiewartościznajdującejsięwzmiennej##zasadniczowszystkiezmiennesąnapisami,ainterpretacja#mamiejsceprzyichużyciuanieprzytworzeniu
#obsługiwaneliczbycałkowiteoraznapisy#brakobsługiliczbzmiennoprzecinkowych##brakspacjipomiędzynazwązmiennejaznakiemrówności#woperacjiprzypisaniajestwymogiemskładniowym
zmiennaA=-91zmiennaB="qaz"zmiennaC=98.6#tobędzietraktowanejakonapisanieliczba
<?php
#dynamicznetypowanie-typokreślanyjest#napodstawiewartościzapisywanejdozmiennej
$zmiennaA=-91.7$zmiennaB="qaz"
?>
vara=13.3varb="qaz"
Kodprogramu-instrukcje,...Program komputerowy składa się z instrukcji wykonywanych kolejno przez procesor. Instrukcje temożnapodzielićna:
instrukcjeprzenoszeniadanych(m.in.pomiędzypamięciąirejestramiprocesora),instrukcjemodyfikującedane(wykonującenanichjakieśoperacjearytmetyczne,logiczneitp.),instrukcjęmodyfikującesterowaniewprogramie.
Dwie pierwsze kategorie instrukcji odpowiadają za modyfikowanie wartości zmiennej na skutekprzypisań wartości oraz operacji wykonywanych na zmiennych. Trzecia kategoria to instrukcjeodpowiedzialnezawarunkowelubbezwarunkowemodyfikowanielicznikprogramu.Mogąwystępowaćtakże instrukcjezłożonerealizującezadaniaz różnychgrupwramach jednej instrukcji (np. instrukcjewykonywanewarunkowo).
Podstawoweoperacjearytmetyczne,bitoweilogiczne
Z punktu widzenia procesora (kodu maszynowego) podstawowymi operacjami wykonywanymi nadanych(opróczprzenoszenia)sątypoweoperacjearytmetyczneilogiczneorazoperacjebinarne.Wiele
///PrzykładC++
###PrzykładPython
###PrzykładBash
///PrzykładPHP
///PrzykładJavaScript
architekturposiada także bardziej złożone instrukcje (np.wykonywane niena pojedynczych liczba acałychwektorachliczblubteżwykonującychjakąśbardziejzłożonąoperacjęmatematycznąwsposóbsprzętowy),któreodgrywająistotnąrolęwoptymalizacjikodunadanąarchitekturę.
Zpunktuwidzeniajęzykówprogramowanianajczęściejzapodstawoweoperacjeuważasię:operacje arytmetyczne: dodawanie, odejmowanie, mnożenie, dzielenie całkowite, dzieleniezmiennoprzecinkowe,obliczanieresztyzdzielenia,niekiedypodnoszeniedopotęgioperacje logiczne: AND, OR, NOT, niekiedy XOR, porównania (równość, nierówność, większe,mniejsze,większerówne,mniejszerówne)operacjebitowe(wykonywaneniezależnienakażdymbicieargumentów):AND,OR,NOT,XOR,przesunięciabitowe
Dośćistotnymwyjątkiemsąniektórejęzykiskryptowe(takiejakbash),którychgłównymzadaniemjesturuchamianieinnychprogramówitojestoperacjąpodstawowąwtychjęzykach.
#include<stdio.h>
intmain(){ doublea=12.7,b=3,c,d,e; intx=5,y=6,z; //dodawanie,mnożenie,odejmowaniezapisujesię //idziałająonetakjakwnormalnejmatematyce: e=(a+b)*4-y; //dzieleniezależyodtypówargumentów d=a/b;//będziedzieleniemzmiennoprzecinkowymboaibsątypufloat c=x/y;//będziedzieleniemcałkowitymboziysązmiennymitypuint b=(int)a/(int)b;//będziedzieleniemcałkowitym a=(double)x/(double)y;//będziedzieleniemzmiennoprzecinkowym //resztazdzielenia(tylkodlaargumentówcałkowitych) z=x%y; //wypisaniewyników printf("%d%f%f%f%f%f\n",z,e,d,c,b,a); //operacjelogiczne: //((awiększerówneod0)AND(bmniejszeod2))OR(zrówne5) z=(a>=0&&b<2)||z==5; //negacjalogicznaz x=!z; printf("%d%d\n",z,x); //operacjebinarne: //bitowyOR0x0fz0x11iprzesunięciewynikuo1wlewo x=(0x0f|0x11)<<1; //bitowyXOR0x0fz0x11 y=(0x0f^0x11); //negacjabitowawynikubitowegoAND0xfffi0x0f0 z=~(0xfff&0x0f0); printf("%x%x%x\n",x,y,z); //uwaga:powyższyprogrammożeniewykonywaćobliczeńwczasiedziałania //zewzględunaoptymalizacjęifaktiżwynikiwszystkichoperacji //sąznanewmomenciekompilacjiprogramu}
a=12.7b=3x=5y=6
#dodawanie,mnożenie,odejmowaniezapisujesię#idziałająonetakjakwnormalnejmatematyce:e=(a+b)*4-y
#dzieleniezmiennoprzecinkowec=x/y
#dzieleniecałkowite
///PrzykładC++
###PrzykładPython
b=a//b
#resztazdzieleniaz=x%y;
#wypisaniewynikówprint(e,c,b,z)
#operacjelogiczne:#((awiększerówneod0)AND(bmniejszeod2))OR(zrówne5)z=(a>=0andb<2)orz==5;#negacjalogicznazx=notz;
print(z,x);
#operacjebinarne:#bitowyOR0x0fz0x11iprzesunięciewynikuo1wlewox=(0x0f|0x11)<<1;#bitowyXOR0x0fz0x11y=(0x0f^0x11);#negacjabitowawynikubitowegoAND0xfffi0x0f0z=~(0xfff&0x0f0);
print(hex(x),hex(y),hex(z&0xffff));#wypisujączmusimyokreślićjegobitowość
#wieloargumentowaoperacjaprzypisania#możebyćużytadozamianywartościpomiędzydwomazmiennymi#bezjawnegoużywaniazmiennejtymczasowejprint(a,b)a,b=b,aprint(a,b)#oczywiściemożnawjejramachużywaćwięcejniżdwóchzmiennych
a=12;b=3;x=5;y=6
#abywykonaćdziałaniaarytmetycznenależy#umieścićjewewnątrz$((i))
#dodawanie,mnożenie,odejmowaniezapisujesię#idziałająonetakjakwnormalnejmatematyce:e=$((($a+$b)*4-$y))
#dzieleniecałkowitec=$(($x/$y))
#wypisaniewyników#(zwróćuwagęnawynikwypisanianiezainicjalizowanejzmiennejz)echo$e$c$z
#operacjelogiczneobsługiwanesąkomendątest#luboperatorem[]wynikzwracanyjestjakokodpowrotu#należyzwrócićuwagęnaescapowanieodwrotnymukośnikiem#nawiasówinatożespacjemająznaczenie
#((awiększerówneodzera)AND(bmniejszeoddwóch))OR(zrówne5)[\($a-ge0-a$b-lt2\)-o$z-eq5];z=$?
#negacjęrealizuje!,alewynikiemnegacjądowolnejliczbyjestFALSE#więcniedasięzanegowaćzjakwpozostałychprzykładach
echo$z#bashstosujelogikęodwróconą0==TRUE,cośniezerowegotoFALSE
#bashnieobsługujeliczbzmiennoprzecinkowychanioperacjibitowych#nieobsługiwaneoperacjemożnawykonaćzapomocąinnegoprogramunp:a=`echo'print(3/2)'|python3`b=$(echo'3/2'|bc-l)echo$a$b
#ujęciepoleceniawznaki`powodujepodstawieniewtymmiejscu#standardowegowyjściategopolecenia(wtymwypadkuzapisaniago#dozmiennej),alternatywnąskładniąjest$(polecenie)#pokazanynaprzykładziezmiennejb
###PrzykładBash
vara=12.7,b=3,c=13,d,e;
//dodawanie,mnożenie,odejmowaniezapisujesię//idziałająonetakjakwnormalnejmatematyce:e=(a+b)*4-c;
//dzieleniezawszejestzmiennoprzecinkowed=a/b;c=b/c;
//wypisaniewynikówconsole.log( "e="+e+"\n"+ "d="+d+"\n"+ "c="+c+"\n");
//operacjelogiczne://((awiększerówneod0)AND(bmniejszeod2))OR(crówne5)varz=(a>=0&&b<2)||c==5;//negacjalogicznaza=!z;
console.log( "z="+z+"\n"+ "a="+a+"\n");
//operacjebinarne: //bitowyOR0x0fz0x11iprzesunięciewynikuo1wlewo a=(0x0f|0x11)<<1; //bitowyXOR0x0fz0x11 b=(0x0f^0x11); //negacjabitowawynikubitowegoAND0xfffi0x0f0 c=~(0xfff&0x0f0);console.log( "a=0x"+a.toString(16)+"\n"+ "b=0x"+b.toString(16)+"\n"+ "c=0x"+(c&0xffff).toString(16)+"\n");
Przepływsterowaniawprogramie-skoki,warunki,pętle,funkcje
Licznikprogramu(programcounter,instructionpointerlubinstructionaddressregister)jestrejestremprocesora który określa adres następnej (w niektórych architekturach aktualnej) instrukcji która mazostaćprzetworzonaprocesor.
Skoki bezwarunkowe, instrukcje warunkowe, pętle, wywołania funkcji są realizowane poprzezmodyfikację licznika programu. W przypadku wywołań funkcji dodatkowo wykonywane są operacjezwiązanezobsługąstosu(zachowywaniemstanurejestrów,umieszczaniemargumentównastosie,...).Instrukcja goto (realizująca skok bezwarunkowy) jest pełnoprawną instrukcją skoku, jedyną wadą jejstosowania jest to że przy niewłaściwym / zbyt częstym wykorzystywaniu (zamiast wywołań funkcji,warunkówipętli)kodprogramustajesięmniejczytelny.
Wwiększościprzypadkówpętlerealizowanesąnapoziomiekodumaszynowegojakozestawinstrukcji(np. inkrementacji zmiennej, sprawdzaniawarunku, skoku), jednakwniektórychrozwiązaniachpętle(np.typu"powtórznrazy")mogąbyćrealizowanesprzętowoprzypomocypojedynczejinstrukcji.
#include<stdio.h>
intmain(){ inti,j,k; //instrukcjawaunkowaif-else if(i<j){ puts("i<j"); }elseif(j<k){ puts("i>=jANDj<k"); }else{ puts("i>=jANDj>=k"); }
///PrzykładJavaScript
///PrzykładC++
//podstawoweoperatorylogiczne if(i<j||j<k) puts("i<jORj<k"); //innymioperatoramilogicznymisą&&(AND),!(NOT) //pętlafor for(i=2;i<=9;++i){ if(i==3){ //pominięcietegokrokupętli continue; } if(i==7){ //wyjściezpętli break; } printf("a:%d\n",i); } //pętlawhile while(i>0){ printf("b:%d\n",--i); } //pętlado-while do{ printf("c:%d\n",++i); }while(i<2); //instrukcjawyboruswitch switch(i){ case1: puts("i==1"); break; default: puts("i!=1"); break; } gotoETYKIETA; puts("tosięnigdyniewykona"); puts("bowcześniejrobimybezwarunkowegoto"); ETYKIETA: puts("atosięwykona");}
i=k=j=0
#instrukcjawaunkowaif-elseifi<j: print("i<j")elifj<k: print("i>=jANDj<k")else: print("i>=jANDj>=k")
#podstawoweoperatorylogiczneif(i<jorj<k) puts("i<jORj<k");#innymioperatoramilogicznymisąandoraznot
#pętlaforforiinrange(2,9): ifi==3: #pominięcietegokrokupętli continue; ifi==7: #wyjściezpętli break; print("a:",i);else: #niewejdzietutajbopętlakończy #sięzużyciembreak print("elsewpętli");
###PrzykładPython
#pętlawhilewhilei>0: i=i-1; print("b:",i);else: #wejdzietugdywaruneki>0 #niebędziespełniony #zarównoprzypierwszym #jakikolejnychsprawdzeniach print("elsewpętli");
#pętlaforfor((i=0;$i<=20;i++));do echo$i;done
#wbardziej"shellowym"stylu:foriin`seq020`;do echo$i;done
#pętlaforpoliścierozdzielanejspacjami#wypisanienazwwszystkichplikówz/tmpfornazwain/tmp/*;do echo$nazwa;done
#pętlawhilezread(poliniachpliku)cat/etc/fstab|whilereadsloworeszta;do echo$reszta;done#powyższapętlawypiszepokoleiwszystkie#wierszeplikuprzekazanegoprzezstdin#(catnazwa_pliku|)zpominięciem#pierwszegosłowa(którewczytywanebyłodo#zmiennejslowo)#domyślnymseparatorempóldlakomendyread#jestdowolnyciągbiałychznaków(spacjii#tabulatorów)możnagozmienićprzypomocy#zmiennejIFS:IFS=:whilereadabcd;do echo$cdone</etc/passwdunsetIFS
#instruikcjaif-elseif["$xx"="kot"-o"$xx"="pies"];then echo"kotlubpies";elif["$xx"="ryba"];then echo"ryba"else echo"cośinnego"fi
#spacjewokółiwewnątrznawiasówkwadratowych#przywarunkusąistotneskładniowo,zawartość#nawiasówkwadratowychtotaknaprawdę#argumentydlakomendytest,zatemwywołanie:#if["$xx"="ryba"];then#jestrównoważne:#iftest"$xx"="ryba";then#awięcejnatematwarunkówmożnaznaleźćw:#mantest
#jakowarunekmożewystąpićdowolnepolecenie#wtedysprawdzanyjestjegokodpowrotu#0oznaczaprawdę/zakończeniesukcesem#wartośćniezerowafałsz/błądifgrep'^root:'/etc/passwd>/dev/null;then echo/etc/passwdzawieraużytkownikaroot;fi
#istniejemożliwośćskróconegozapisuwarunków
###PrzykładBash
#zużyciemłączeniainstrukcjiprzypomocy:#&&wykonajinstrukcjęwystępującapoprawej#gdypoprzedniazwróciłazero(true)#||(wykonajinstrukcjęwystępującapoprawej#gdypoprzedniazwróciłaniezero--false["$xx"="ryba"]&&echo'$xx=toryba'grep'^root:'/etc/passwd>/dev/null&&\echo/etc/passwdzawieraużytkownikaroot;
#instrukcjacase#(wodróżnieniuodswitchzCobsługujenapisy)case$xxin kot|pies) echo"kotlubpies" ;; ryba) echo"ryba" ;; *) echo"cosinnego" ;;esac
<?php
$i=$j=$k=0;
//instrukcjawaunkowaif-elseif($i<$j){ echo("i<j\n");}elseif($j<$k){ echo("i>=jANDj<k\n");}else{ echo("i>=jANDj>=k\n");}
//pętlaforfor($i=2;$i<7;++$i){ if($i==$j){ //pominięcietegokrokupętli continue; } printf("a:%d\n",$i);}
//pętlawhilewhile($i>0){ if($i==$k){ //wyjściezpętli break; } printf("b:%d\n",--$i);}
//pętlado-whiledo{ printf("c:%d\n",++$i);}while($i<2);
//instrukcjawyboruswitchswitch($i){ case1: echo("i==1\n"); break; default: echo("i!=1\n"); break;}
?>
vari,j,k;
//instrukcjawaunkowaif-elseif(i<j){
///PrzykładPHP
///PrzykładJavaScript
console.log("i<j\n");}elseif(j<k){ console.log("i>=jANDj<k\n");}else{ console.log("i>=jANDj>=k\n");}
//podstawoweoperatorylogiczneif(i<j||j<k) console.log("i<jORj<k\n");//innymioperatoramilogicznymisą&&(AND),!(NOT)
//pętlaforfor(i=2;i<=9;++i){ if(i==3){ //pominięcietegokrokupętli continue; } if(i==7){ //wyjściezpętli break; } console.log("a:",+i+"\n");}
//pętlawhilewhile(i>0){ console.log("b:"+--i+"\n");}
//pętlado-whiledo{ console.log("c:"+++i+"\n");}while(i<2);
//instrukcjawyboruswitchswitch(i){ case1: console.log("i==1\n"); break; default: console.log("i!=1\n"); break;}
Typowo funkcja przyjmuje określoną ilość argumentów (może ich nie posiadać) i zwraca pojedyncząwartość.Istniejemożliwośćzwracaniaprzezfunkcjęstrukturyzłożonejzkilkuwartości,jednaknaogółodebranie z funkcji dodatkowych wyników działania odbywa się poprzez argument typuwskaźnikowego,wskazującynazmiennąwktórejmajązostaćzapisane.Wiele językówpozwalatakżenadefiniowaniefunkcjiprzyjmującychdowolnąilośćargumentów.
#include<stdio.h>
#include<stdarg.h>//potrzebnedlaobsługidowolnejilościargumentów
//funkcjabezargumentowaniezwracającawartościvoidf1(){ puts("ABC");}
//funkcjadwuargumentowazwracającawartośćintf2(inta,intb){ returna*2.5+b;}
//funkcjazjednymargumentemobowiązkowym//ijednymopcjonalnymfloatf3(inta,intb=1){ puts("F3"); returna*2.5+b;}
///PrzykładC++
//funkcjazdwomaargumentamiwymaganymi//idowolnąilościąargumentówopcjonalnychfloatf4(inta,intb,...){ floatret; va_listvl; va_start(vl,b); //wtymmiejscupotrzebujemyznaćilość //oraztypyargumentów for(inti=0;i<a;i++){ ret+=b*va_arg(vl,double); } va_end(vl);
returnret;}
intmain(){ f1(); inta=f2(3,6); //zwracanąwartośćmożnawykorzystać //(jakwyżej)lubzignorować: f3(0); floatb=f4(2,1,2.8,3.5); printf("%d%f\n",a,b);}
#funkcjabezargumentowa,zwracającawartośćdeff1(): print("AA") return5
a=f1()print(a)
#funkcjaprzyjmującajedenobowiązkowy#argumentorazdwaopcjonalnedeff2(a,b=2,c=0): print(a**b+c)
f2(3)f2(3,3)#możnapominąćdowolnezargumentówzwartością#domyślnąodwołującsiędopozostałychnazwamif2(2,c=1)#możnapodawaćargumentywdowolnejkolejności#odwołującsiędonichnazwamif2(b=3,a=2)
#nieokreślonailośćargumentówpozycyjnychdeff(*a): foraaina: print(aa)
f(1,"y",6)#alenie:f(1,"y",u="p")
#nieokreślonailośćargumentównazwanychdeff(**a): foraaina: print(aa,"=",a[aa])
f(a="y",u="p")#alenie:f(1,u="p")
#nieokreślonailośćargumentówpozycyjnychinazwanychdeff(*a1,**a2): print(a1) print(a2)
f(1,"y",6)
###PrzykładPython
f(a="y",u="p")f(1,"y",u="p")
#możnateżwymusićileśargumentówjawnychdeff(x,*a1,y="8",**a2): print(x,y) print(a1) print(a2)
f(1,"y",6)f(1,"y",u="p")f(1,"z",y="y",u="p")#alenie:f(a="y",u="p")
#wbashukażdafunkcjamożeprzyjmować#dowolnąilośćparametrówpozycyjnych#(widentycznysposóbobsługiwanesą#argumentyliniipoleceńdlacałegoskryptu)f1(){ echo"wywołanoz$#parametrami" echo"parametryto:$@" [$#-lt2]&&return; #możnaodwoływaćsiędopojedynczychparametrów echo"drugi:$2" echo"pierwszy:$1" #albokolejnychwpętli forain"$@";doecho$a;done #lubzużyciempoleceniashift foriin`seq1$#`;do echo$1 shift#powodujezapomnienie$1 #iprzenumerowaniepozostałych #argumentówpozycyjnycho1 #wpływanawartości$@$#itp done #funkcjamożezwracaćtylkowartośćnumeryczną #tzwkodpowrotu return83}
#wywołanie-takjakkomendy,czylibeznawiasów,#aargumentyrozdzielanebiałymznakiem(spacją)f1aaa3t56
#kodpowrotuostatniowywołanejkomendylubfunkcji#uzyskujesiępoprzez$?:echo$?
#częstofunkcje(takjakwielekomend)wynikswojego#działaniazwracająpoprzezstandardowewyjście
f2(){echo"Uwolnićmrożonetruskawki$1";}
#pozyskaćgomożnapoprzez``lub$()a=`f2'!!!'`echo$a
b=$(f2'!')echo$b
#wjednolinijkowymzapisiedefinicjifunkcji(jak#miałotomiejscedlaf2)spacjepo{iprzed}są#obowiązkowe,podobniejakśrednikipoinstukcjach
<?php
#funkcjabezargumentowa,zwracającawartośćfunctionf1(){ print("AA\n");
###PrzykładBash
///PrzykładPHP
return5;}
$a=f1();print($a);print("\n");
#funkcjaprzyjmującajedenobowiązkowy#argumentorazdwaopcjonalnefunctionf2($a,$b=2,$c=0){ print($a**$b+$c); print("\n");}
f2(3);f2(3,3);
#nieokreślonailośćargumentówpozycyjnychfunctionf3(){ $num=func_num_args(); print("ilośćargumentów:\n"); print($num); print("\n"); for($i=0;$i<$num;++$i){ print("argument$i:"); print(func_get_arg($i)); print("\n"); }}
f3();f3("a",1,"c",5);
#jedenwymagany,jedenopcjonalny#inieokreślonailośćdodatkowychfunctionf4($a,$b="16"){ #tablicazwszystkimiargumentami #jestalternatywnąmetodądostępu #dowszystkichargumentówwstosunku #codopokazanejwf3() $args=func_get_args(); print_r($args);}
f4("a",1,"c",5);
?>
functionf1(){ console.log("ABC\n");}
//funkcjadwuargumentowazwracającawartośćfunctionf2(a,b){ returna*2.5+b;}
//funkcjazjednymargumentemobowiązkowym//ijednymopcjonalnymfunctionf3(a,b=1){ console.log("F3\n"); returna*2.5+b;}
//funkcjazdowolnąilościąargumentówfunctionf4(){ varret=0; for(vari=0;i<arguments.length;i++){ ret+=arguments[i]; } returnret;}
///PrzykładJavaScript
f1();//zwracanąwartośćmożnawykorzystać:vara=f2(3,6);//lubzignorować:f3(0);varb=f4(2,1,2.8,3.5);
console.log("a="+a+"b="+b+"\n");
Punktstartu
Jako że program komputerowy jest sekwencją wykonywanych instrukcji musi rozpoczynać się odokreślonegomiejsca.Wprzypadkujęzykówinterpretowanychjesttonaogółpoczątekplikuzkodemprogramu.Częstowpierwszejliniiznajdujesięspecjalnykomentarz(postaci#!/ścieżka/do/programu)stanowiącyinformacjędla programu uruchamiającego skrypt jakiego interpretera ma użyć w celu wykonania koduzawartegowpliku(niekiedyzawierateżopcjezjakiminależyuruchomićinterpreter).NatomiastwprzypadkuskompilowanegokoduC/C++punktemstartujestfunkcjamain.Zakończenietejfunkcjioznaczazakończenieprogramu,awartośćprzezniązwracanaodpowiedzialnajestzatzw.kodpowrotuprzekazanyprocesowiwywołującemuprogram.
Rekurencja
Rekurencjajestmechanizmem,polegającymnawywoływaniufunkcjiprzezsamąsiebie,którymanacelu implementację niektórych algorytmów. Może być zastosowana chyba w każdym językupozwalającym na definiowanie funkcji. Ograniczeniem jest maksymalna ilość wywołań funkcjizwiązanazwielkościąstosu -wprzypadkuzbytwieluwywołańkolejnych funkcjiprogramzakończysiębłędem.Każdyalgorytmzapisywanyrekurencyjniemożezostaćzamienionynaalgorytmiteracyjny(wykorzystującypętle).
#obliczaniesilnizużyciemrekurencjidefsilnia(n): #każdarekurencjamusimiećwarunekkońca ifn==1: return1 else: returnn*silnia(n-1)
silnia(20)
#iteracyjneobliczaniesilnidefsilnia(n): s=1 foriinrange(2,n+1): s=s*i returns
silnia(20)
Więcejo(bardziejzłożonych)zmiennychGrupowaniezmiennychStrukturyiklasy
Struktura jest złożonym typem danych służącym do grupowania powiązanych ze sobą logiczniezmiennych. Zmienne wchodzące w skład struktury (pola) identyfikowane są nazwami i mogą byćróżnychtypów.Strukturazajmujeciągłyobszarpamięci,wktórymumieszczanesąwartościkolejnychpól.
Klasa opróczpólmożezawierać także funkcje (metody) - zarównooperującena tychpolach jak i zniminiepowiązane.Wniektórychprzypadkachtakżestrukturymogązawieraćmetody-np.wC++niemasilnegorozróżnieniapomiędzystrukturamiaklasami(różniąsiętylkodomyślnąwidocznościąpólimetod).
Zmiennektórychtypemjestjakaśklasaczęstookreślasięjakoobiektdanejklasy.Niekiedymówisiętakżeoinstancjidanejklasy(reprezentowanejprzezzmienną).
Niektóre z języków pozwalają na definiowanie w ramach struktury lub klasy pól i/lub metodstatycznych,któreniesąpowiązanezżadnymistniejącymegzemplarzemdanejstrukturyczyklasy-
###PrzykładPython
###PrzykładPython
sąwspólnedlawszystkichimożnasiędonichodwoływaćbezistnieniaobiektu.
#include<iostream>#include<stdint.h>
structNazwaStruktury{ //polaskładowe inta; std::stringd; //zmiennastatyczna //wspólnadlawszystkichobiektówtejklasy staticintx; //stała staticconstinty=7; //polabinarne(jednoitrzybitowe) uint8_tmA:1; uint8_tmB:3; //metodyskładowe voidwypisz(){ std::cout<<"a="<<a<<"d="<<d<<"\n"; } //deklaracjametody //definicjamusibyćpodanagdzieśindziej intgetSum(intb); ///metodystatyczna staticvoidinfo(){ std::cout<<"INFO\n"; } //konstruktoridestruktor NazwaStruktury(intaa=0){ std::cout<<"konstruktor\n"; a=aa; d="abc..."; } ~NazwaStruktury(){ //potrzebnygdyklasatworzyjakieś //obiektyktórenalezyusuwać,itp std::cout<<"destruktor\n"; }};
//definicjazmiennejstatycznejznadaniemjejwartości//jesttoniezbędneabybyłaonawidoczna...intNazwaStruktury::x=13;
//wcześniejzdeklarowanemetody//możemydefiniowaćtakżepozadeklaracjąklasyintNazwaStruktury::getSum(intb){ returna+b;}
intmain(){ //korzystaniezestruktur NazwaStrukturys; s.a=45; s.wypisz();
//korzystaniezmetodstatycznych NazwaStruktury::info(); //atakżepoprzezobiektdanejklasy s.info();}
classNazwaKlasy: #polaskładowe a=0 d="alamakota"
///PrzykładC++
###PrzykładPython
#metodyskładowe defwypisz(self): print(self.a+self.b) #wartozauważyćjawnyargument #wpostaciobiektutejklasy #wC++takżewystępujealeniejest #jawniedeklarowany,aninietrzeba #sięnimjawnieposługiwać #metodystatyczna @staticmethod definfo(): print("INFO") #konstruktor(zjednymargumentem) def__init__(self,x=1): print("konstruktor",self.a,self.d) #ikolejnysposóbnautworzenie #polaskładowegoklasy self.b=13*x
#korzystaniezklasyk=NazwaKlasy()k.a=67k.wypisz()
#dometodmożnaodwoływaćsiętakżetak:#(jawneużycieargumentuwpostaciobiektuklasy)NazwaKlasy.wypisz(k)
#korzystaniezmetodstatycznychNazwaKlasy.info()
print("kjesttypu:",type(k))print("natomiastk.ajesttypu:",type(k.a))
#obiektymożnarozszerzaćonoweskładoweifunkcje:k.b=k.a+10print(k.b)
<?php
classNazwaKlasy{ public$a; public$d="tekst"; #metodyskładowe publicfunctionwypisz(){ echo"a=".$this->a."d=".$this->d."\n"; } #wartozauważyćjawneodwołaniadoskładowych #poprzezzmienną$this #metodystatyczna publicstaticfunctioninfo(){ echo"INFO\n"; }}
//korzystaniezklasy$k=newNazwaKlasy;$k->a=87;$k->wypisz();
//korzystaniezmetodstatycznychNazwaKlasy::info();//atakżepoprzezzmiennąprzechowującąnazwęklasy$t="NazwaKlasy";$t::info();
?>
Metodywchodzącewskładstrukturyorazpolastatyczneniewpływająnarozmiarobiektówktórychjesttypem.
///PrzykładPHP
Tablice
Tablica jest strukturą danych w której elementy (takiego samego typu) są ułożone w porządkuliniowym i są dostępne za pomocą indeksów (kluczy). Typowo tablica indeksowana jest liczbamicałkowityminieujemnymiorazzajmujeciągłyobszarpamięci.Dostępdoelementówtablicyodbywasięwoparciuoobliczanieichadresunapodstawiezależności:AdresElementu=AdresPoczatkuTablicy+IndexElementu*RozmiarElementu.
#include<iostream>#include<vector>
intmain(){ //klasycznatablica intt[4]={1,8,3,2}; std::cout<<t[2]<<"->"; t[2]=55; std::cout<<t[2]<<"="<<*(t+2)<<"\n"; //jestonapodobniejakstrukturaciągłymobszarempamięci, //możliwejestzatemtraktowanietakiejtablicyjakostruktury structStruktura{ inta,b,c,d; }; Struktura*tt=(Struktura*)t; std::cout<<tt->a<<""<<tt->c<<"\n"; //dynamiczniealokowanatablicaC++STL std::vector<int>v(4); v[3]=21; std::cout<<v[3]<<"\n";}
a[0]="abc"a[1]=123a[2]=zza[3]=qq
x=1echo"wybraneelementytablicy:"${a[$x]}${a[0]}echo"całatablica:"${a[@]}echo"ilośćelementówwtablicytablica:"${#a[@]}
vart=['abc',8,3,2];
console.log( "pierwszyelement:"+t[0]+"\n"+ "długośćtablicy:"+t.length+"\n");
//usuwamy2elementyodpozycji1t.splice(1,2)
//dodajemynoweelementyt[5]="pp";t[7]="ww";
//wypisaniewszystkichelementówfor(vari=0;i<t.length;++i){ console.log("t["+i+"]="+t[i]+"\n");}
//zapomocąfor..infor(variiint){ console.log("t["+ii+"]="+t[ii]+"\n");}
Listy
Listajeststrukturądanychwktórejelementysąułożonewporządkuliniowymnazasadziepoprzedni-
///PrzykładC++
###PrzykładBash
///PrzykładJavaScript
następny.Wyróżnialisty:jednokierunkowe
wktórychwoparciuoelement listymożnauzyskaćtylkoelementnastępny lubustalićże jestostatni-możnaprzemieszczaćsiępotakiejliścietylkowjednymkierunku
dwukierunkowew których w oparciu o element listy można uzyskać następny i poprzedni, lub ustalić że jestpierwszym lub ostatnim - umożliwia to przemieszczanie się po elementach listy w obukierunkach
cykliczne(zarówno jedno idwukierunkowe)wktórychostatnielementwskazuje jakonastępnypierwszyelement, a (w przypadku dwukierunkowych) pierwszy element wskazuje ostatni jako swojegopoprzednika
#include<iostream>#include<list>
intmain(){ std::list<int>l; //dodanieelementunakońcu l.push_back(17); l.push_back(13); l.push_back(3); l.push_back(27); l.push_back(21); //dodanieelementunapoczątku l.push_front(8); //wypisanieliczbyelementów std::cout<<"size="<<l.size()<<"\n"; //wypisaniepierwszegoiostatniegoelementu std::cout<<"first="<<l.front()<<"last="<<l.back()<<"\n"; //usuniecieostatniegoelementu l.pop_back(); //posortowanielisty l.sort(); //odwróceniekolejnościelementów l.reverse(); //usunieciepierwszegoelementu l.pop_front(); for(std::list<int>::iteratori=l.begin();i!=l.end();++i){ //wypisaniewszystkichelementów std::cout<<*i<<"\n"; //możliwejesttakże: //-usuwanieelementuwskazanegoprzeziterator //-wstawianieelementuprzedwskazanymprzeziterator }}
l=[3,5,8]
#wstawienieelementunakoniecl.append(1)
#wstawienieelementunapozycje2l.insert(2,13)
print("liczbaelementów=",len(l))print("pierwszy=",l[0])
#wypisaniewszystkichelementówforeinl: #możemymodyfikowaćzmienną"e", #aleniebędziemaiłotowplywunalistę print(e)
///PrzykładC++
###PrzykładPython
#alternatywneiterowaniepoelementach#(pozwalanaichmodyfikowanie)foriinrange(len(l)): l[i]=l[i]+1 print(l[i])
#możemyteżuzyskaćlistęwoparciuowykonaniejakiś#operacjinadanejliściewformiejednolinijkowca:l=[a*2forainl]#listętakąmożemyprzypisaćdoinnej#lub(jakwyżej)dotejsamejzmiennej
#pobranieiusuniecieostatniegoelementuprint("ostatnimbył:",l.pop())print("ostatnimbył:",l.pop())
#pobranieiusuniecieelementunawskazanejpozycjiprint("drugimelementembył:",l.pop(1))
#wypisaniecałejlistyprint(l)
#niekiedyzamiasttworzenialistylepszemożebyć#uzyskiwaniejejkolejnychelementów"nażywo"#funkcjonalnośćtakąwpythoniezapewniajągeneratory:
deff(l): a,b=0,1 foriinrange(l): r,a,b=a,b,a+b yieldr
#użyciegeneratorawpętliforforiinf(16): print(i)
#możnatakżetworzyćgeneratorynieskończonedefff(): a,b=0,1 whileTrue: r,a,b=a,b,a+b yieldr
#pobieraniekolejnychelementówa=iter(ff())print(next(a))print(next(a))
Listyumożliwiająłatwąimplementacjęm.in.:kolejkitypuFIFO(FirstInFirstOut)
poprzezdodawanieelementównakonieclisty,apobieraniezpoczątkulistystosu,czylikolejkitypuLIFO(LastInFirstOut)
poprzezdodawanieelementównakonieclistyipobieranietakżezkońcalisty
Listyniemuszązajmowaćciągłegoobszarupamięci-każdyzelementówmożebyćalokowanyosobnoitylkozawieraćwskaźnikinanastępnyiew.poprzednielement.Utrudnia(wydłuża)todostępdon-tegoelementulisty,aleusprawniadodawanieiusuwanieelementów(zarównozpoczątku,środkajakikońcalisty).
Tabliceasocjacyjna(mapy)
Tablicaasocjacyjna(nazywanatakżemapąlubsłownikiem)podobniedozwykłejtablicyjestzbioremparklucz-wartość,ztymżekluczeniemuszątutajbyćkolejnymiliczbamicałkowitymizaczynającymisię od zera a mogą być dowolnymi wartościami (napisami, wskaźnikami, etc). Często (np. C++)tablice takie implementowane są jako posortowane drzewa binarne, dzięki czemu dostęp doszukanegoelementurealizowanyjestwczasielogarytmicznym.
#include<iostream>#include<map>
intmain(){
###PrzykładPython
///PrzykładC++
std::map<std::string,int>m; m["a"]=6; m["cd"]=9; std::cout<<m["a"]<<""<<m["ab"]<<"\n"; //wyszukanieelementupokluczu std::map<std::string,int>::iteratoriter=m.find("cd"); //sprawdzenieczyistnieje if(iter!=m.end()){ //wypisaniepary-kluczwartość std::cout<<iter->first<<"=>"<<iter->second<<"\n"; //usunięcieelementu m.erase(iter); } m["a"]=45; //wypisaniecałejmapy for(iter=m.begin();iter!=m.end();++iter) std::cout<<iter->first<<"=>"<<iter->second<<"\n"; //jakwidaćmapajestwewnętrznieposortowana}
m={"ab":11,"cd":"xx"}x="e"m[x]=True;
#pobraniesamychkluczyforkinm: print(k,"=>",m[k])
#sprawdzenieistnieniaif"ab"inm: print("jestab") #usunięcieelementu delm['ab']
#modyfikacjawartoscim["cd"]="oi"
#pobranieparkluczwartoscfork,vinm.items(): print(k,"=>",v)
<?php
$a=array('ab'=>True,'cd'=>'xx');$a['efg']=15;$a['cd']="yu";
#sprawdzenieistnieniaif(isset($a['ab'])){ //uwaga:gdy$a['ab']=null //toissetzwróciFALSE //patrzarray_key_exists() echo"jestab"; #usunięcieelementu unset($a['ab']);}
while(list($k,$v)=each($a)){ echo"a[$k]=$v\n";}
?>
//pseudoodpowiednik//tablicyasocjacyjnej
varo={a:1,b:2,c:3};
//dodanieelementu
###PrzykładPython
///PrzykładPHP
///PrzykładJavaScript
o.ab="pp";
//usunięcieelementudeleteo.b;
for(varkino){ console.log( `o.${k}=${o[k]}\n` );}
W standardowej mapie klucz jest unikalny (tzn. nie mogą występować elementy z takim samymkluczem),zapewniatojednoznacznośćodwołańpoprzezoperatortablicowy[].WC++jeżelichcemymiećkilkajednakowychkluczyzróżnymiwartościamimożnaskorzystaćstd::multimap<>.
Strukturamizbliżonymiwdziałaniudomapysązbiory(std::set<>istd::multiset<>zC++orazset([k1,k2, ...]) z Pythona). Różnią się one od map tym że nie przechowują one wartości a jedynie sameklucze.
Wskaźnikiireferencje
Wskaźnik jest zmienną, któraprzechowujeadrespamięci, podktórymznajdują się jakieśdane (innazmienna).Jakożewskaźnikjestzmiennąktórateżjestumieszczonagdzieśwpamięcimożnautworzyćwskaźnikdowskaźnikaitd.Nawskaźnikachmożnawykonywaćoperacjearytmetyczne(najczęściejjestto dodawanie offsetu). Na wskaźniku można wykonać operację wyłuskania czyli odwołania się dowartości zmiennej pod adresem na który wskazuje, a nie do zmiennej wskaźnikowej (zawierającejadres).
Wskaźniki pozwalają na operowanie dużymi zbiorami danych (duże struktury, napisy, etc) bezkonieczności ich kopiowania przy przekazywaniu do funkcji, umieszczaniu w różnych strukturachdanych, sortowaniu, itd (kopiowaniuulega jedyniewskaźnikczyli adres)oraznawspółdzielenie tychsamychdanychpomiędzyróżnymiobiektami.
Wskaźnikmożewskazywaćnaniewłaściwyadreswpamięci(np.naskutekzwolnieniategofragmentulub błędu w operacjach matematycznych na wskaźnikach - wyjściu poza dozwolony zakres), typowowskaźnikowi który nic nie wskazuje przypisuje się wartość NULL (zero). Wyłuskania wskaźników owartościNULL lubwskazującychniewłaściwyobszarpamięciprowadządobłędówprogramu,częstodozakończeniaprogramuzpowodunaruszeniaochronypamięci("Segmentationfault").
Referencjajestzbliżonadowskaźników(wzasadzie jesttowskaźniktrochęinaczejtraktowanyprzezkompilator) - także pozwala na unikanie kopiowania dużych danych. W odróżnieniu od wskaźnikaodwołania do referencji zawsze skutkują wyłuskaniem, nie jest możliwa arytmetyka wskaźnikowa nareferencjach,referencjamusiteżwskazywaćnapoprawnyobszarpamięci(minimalizacjaryzykabłęduodwołania do niewłaściwego adresu). Możliwa jest referencja na wskaźnik a także wskaźnik doreferencji.
#include<stdio.h>#include<iostream>
voidf1(int*b){ *b=2**b;}
voidf2(int(*f)(constchar*s)){ f("Uwolnićmrożonetruskawki!!!");}
structkl{ //polaskładowe inta; intgetSum(intb){ returna+b; }};
intmain(){ //zmiennatypuintiwskaźniknazmiennatypuint inta=5678; int*b=NULL; //pobranieadresuzmiennejdowskaźnika
///PrzykładC++
b=&a; std::cout<<"amaadres"<<b<<"\n"; //modyfikacjawartościnaktórawskazujewskaźnik *b=3456; std::cout<<a<<"="<<*b<<"\n"; //referencja int&c=a; c=6543; std::cout<<a<<"="<<c<<"\n"; //wskaźnikinaobiekty std::pair<int,int>p=std::make_pair(2,5); std::pair<int,int>*q=&p; //dostępdoskładowychpoprzezwskaźniknastrukturę (*q).first=7; q->second=8; std::cout<<p.first<<""<<p.second<<"\n"; //wskaźniknaskładową b=&(q->second); *b=3; std::cout<<p.first<<""<<p.second<<"\n"; //przekazywaniewskaźnikadofunkcji: //1.(podobniejaktrzymaniewskaźnikównaobiekty, //zamiastobiektówwlistachitp)pozwalana //przekazywaniewiększychobiektówbezichkopiowania //2.pozwalanamodyfikowaniewartościargumentów: f1(b); std::cout<<p.first<<""<<p.second<<"\n"; //wskaźnik"fun"nafunkcjeprzyjmującą //wskaźnikconstcharizwracającąint int(*fun)(constchar*s); //przypisanieadresufunkcjiputsdozmiennejfun fun=&puts; //użyciewskaźnikanafunkcjęjakofunkcji fun("aaa"); //wskaźniknafunkcjęmożebyćprzekazywany //doinnychfunkcjijakoargument f2(fun); //wskaźnikiatablice //wCtablicatowskaźniknapierwszyelement //at[x]jestrównoważne*(t+x) shortt[4]={11,22,33,44}; short*tt=t; std::cout<<"t[2]="<<t[2]<<"="<<*(t+2)<<"\n"; std::cout<<"t[0]="<<*tt<<"@"<<tt<<"\n";++tt; std::cout<<"t[1]="<<*tt<<"@"<<tt<<"\n"; //wskaźniknametodęskładowąjakiejśklasy //(zwyjątkiemmetodstatycznych) //wymagaokreśleniatyputejklasy, //gdyżjestontypemniejawnegoargumentujejmetod int(kl::*fun2)(int)=&kl::getSum; //abyskorzystaćtrzebamiećobiektdanejklasy //(lubwskaźnikdoniego) klo1; o1.a=2; kl*o2=&o1; std::cout<<(o1.*fun2)(3)<<""<<(o2->*fun2)(3)<<"\n";}
a,b=5,[1,2,3]
defpinfo(x,xx): print( "id(x)=",hex(id(x)), "=="ifid(xb)==id(xx)else"!=",
###PrzykładPython
"id(xx)=",hex(id(xx)) )
#utworzeniekopiizmiennejoznaczautworzenie#nowejreferencjiwskazującejnadalnatensam#obiektwpamięciaa=apinfo(id(a),id(aa)bb=bpinfo(id(b),id(bb)
#przypisanienowegoobiektupodzmienną#powodujezmianę(adresu)obiektuktóry#wskazuje:aa=5pinfo(id(a),id(aa)bb=[9,11,13]pinfo(id(b),id(bb)
#alemodyfikacjaobiektów"immutable"#(takichjakliczby,napisy)niejestmożliwa#zatemzawszetworzonyjestnowyobiektaa=aaa+=1pinfo(id(a),id(aa)
#jeżelidostaregoobiektuniemainnych#referencjimożeonzostaćusunięty#anowymożebyćumieszczonywjegomiejscu#(wtakimprzypadkuwynikidsięniezmieni)
#natomiastmodyfikacjaobiektów"mutable"#(takichjaklistyisłowniki)#nietworzynowegoobiektutylkomodyfikuje#istniejący(wynikidsięniezmieni)zatem#wszystkiereferencjewskazująnazmodyfikowany#obiekt:bb=bbb[0]=17print("bb=",bb,"b=",b)pinfo(id(b),id(bb)
#abyuzyskaćkopięnależyskorzystać#zodpowiedniejmetodybb=b.copy()
print("bb=",bb,"b=",b)
bb[0]=99print("bb=",bb,"b=",b)pinfo(id(b),id(bb)
#uwagakopiowanietakiejestpłytkie:jeżeliw#liściemamyobiekty"mutable"obie(niezależne#podwzględemzbioruelementów)kopielisty#będąwskazywaćnatesameobiekty
#usuwaniezmiennejb=None#mapowaniezmiennej"b"zostałozmienione#niewskazujejużnalistętylkona#obiekttypuNoneType
bbb=bbdelbb#nazwa"bb"zostałausunięta#aledodanychmożemydostawaćsięprzez"bbb"
#dopieropousunięciuwszystkichreferencji#nadanyobiekttoPythonmożegousunąć(ale#niemusiwykonaćtegonatychmiast)
#pythontakżeumożliwiaprzekazywaniefunkcji#jakoargumentudoinnejfunkcjidefa(z):
print(z*3)
defb(x,y): x(y+2)
b(a,1)
#ponadtofunkcjamożetakżezwracaćfunkcję:defaa(y): deft(x): returny*x returnt
b=aa(3)b(2)
#możnateż:aa(3)(4)
#wBashuniemaoperacjinawskaźnikach#alepodobnąfunkcjęwpewnychwypadkach#możepełnićzmiennazawierającanazwę#innejzmiennej
A='tekstdowypisania,$HOME,`ls`';B="A";
#prostepodejścietypuecho${$B}#(działającenp.wPHP)niezadziała,#alemożnatozrobićnakilkainnychsposobów:
C=${!B};#tametodaniedziaławczystymshecho$C
exportAC=$(echo"\$$B"|envsubst)#tametodawymagazewnętrznegopolecenia#envsubstiwyeksporotwaniazmiennychecho$C
C=$(eval"echo\$$B")echo$C
#zużyciemwiększejliczbypoleceńevalmożemy#zapewnićtakżepodstawieniekolejnegopoziomu#zmiennychlubwykonaniewpisanychwnichpoleceńC=$(evaleval"echo\$$B")echo$C
#zmiennamożeprzechowywaćkomendę/nazwę#funkcjidowykonaniax=ls
$x/tmp
<?php
//wPHPkorzystanieznazwyzmiennej//przechowywanejwinnejzmiennej//jestjeszczeprostsze:$a="12";$b="a";$c="b";
echo"$a$b$c\n"echo"${$b}${$c}\n"echo"${${$c}}\n"
//możliwejesttakżeużywaniezmiennych//zawierającychnazwyfunkcjioraz//przekazywanieichdoinnychfunkcjifunctionfa($z){ print($z*3); print("\n");
###PrzykładBash
///PrzykładPHP
}
$c="fa";$c(2);
functionfb($x,$y){ $x($y+2);}
fb("fa",1);
?>
Zasięgzmiennej
Często (np. C / C++) zasięg zmiennych (widoczność i istnienie) jest limitowany do bloku w którymzostały zadeklarowane, zmienne z bloków wewnętrznych mogą przesłaniać zmienne zadeklarowanewcześniej.Wniektórychjęzykach(np.Pythonie,Bash'u)mechanizmtenniejeststosowany(utworzeniezmiennejwewnątrzif'alubpętlipowodujejejwidocznośćpozatymblokiem).
Wywołaniefunkcjipowodujerozpoczęcienowegokontekstuwktórymzmiennezblokuwywołującegofunkcję nie są widoczne (ale nadal istnieją). Typowo argumenty do funkcji przekazywane są przezkopiowanie,więcfunkcjaniemamożliwościmodyfikacjizmiennychzblokująwywołującegonawetdoniejprzekazanych(wyjątkiemjestprzekazanieprzezreferencjęlubwskaźnik).
W przypadku manualnej alokacji pamięci lub tworzenia obiektów poprzez new limitowana jestwidoczność i istnienie otrzymanego wskaźnika, ale nie zaalokowanego bloku pamięci. Zatemograniczona jest widoczność takich zmiennych ale nie czas ich istnienia, dlatego też przed utratąwskaźnikananienależyjeusunąć(zwolnićzaalokowanąpamięć).
#include<iostream>
intfunA(inta){ a=a*2; returna;}
intfunB(int&a){ a=a*2; returna;}
intmain(){ inta=57,b=23; std::cout<<++a<<""<<++b<<"\n"; //wypisze5824 { inta=b; std::cout<<++a<<""<<++b<<"\n"; //wypisze2525 //boaztegobloku(==24)przesłoniłowcześniejszazmiennąa(==58) } std::cout<<++a<<""<<++b<<"\n"; //wypisze5926 //boazwcześniejszegoblokujużnieistniejeinieprzesłanianaszegoa(==58) std::cout<<funA(a)<<""<<funB(b)<<"\n"; //wypiszewartościzwracaneprzezfunkcjeczyli118(59*2)i52(26*2) std::cout<<a<<""<<b<<"\n"; //wypiszeaktualnewartościargumentu: //a=59boprzekazanieprzezwartośćifunkcjaoperowałanawłasnejkopii //b=52boprzekazaneprzezreferencjęifunkcjaoperowałanatejsamejkopii}
a,b,d=5,12,[1,2,3]
deff1(c): returnc+b
deff2(c): b=2 returnc+b
///PrzykładC++
###PrzykładPython
#f1korzystazzmiennejglobalnejb#f2przysłaniasobiezmiennąglobalnąbpoprzezswojązmiennąlokalnąprint("f1(a)=",f1(a),"f2(a)=",f2(a),"alebnadajwynosi:",b)
deff3(c): globalb b=16 returnc+b
#f3dziękitemużejawniedeklarujeiżużywaglobalnegob#możemodyfikowaćzmiennąglobalnąprint("f3(a)=",f3(a),"terazbwynosi:",b)
deff4(c): c=2*c returnc
#argumentyfunkcjisązmiennymilokalnymiprint("f4(a)=",f4(a),"aleanadajwynosi:",a)
deff5(c): c[0]="xx" returnc
print("f5(d)=",f5(d),"tymrazemduległomodyfikacji:",d)
ifd[1]==2: x="ABC"else: x=22
print("zmiennaxjestwidocznapozablokiemwktórymzostałautworzona",x)
Kolejnośćbajtów
#include<inttypes.h>#include<stdio.h>intmain(){ //danejakotablicaliczb16bitowych uint16_taa[4]={0x1234,0x5678,0x9abc,0xdeff}; //wypisujemyją printf("A0:%x%x%x%x\n",aa[0],aa[1],aa[2],aa[3]); //chybanikogoniezaskoczywynikpowyższegoprintf:A0:123456789abcdeff //wypisujemydwiepierwszeliczbyrozłożonenaczęści8bitowe(poszczególnebajty) printf("A1:%x%x%x%x\n",(aa[0]>>8)&0xff,aa[0]&0xff,(aa[0]>>8)&0xff,aa[0]&0xff); //efektteżjestoczywisty:A1:12341234 //każemynatesamedanepatrzećjakonaliczby8bitowe(poszczególnebajty) uint8_t*bb=(uint8_t*)aa; printf("B0:%x%x%x%x\n",bb[0],bb[1],bb[2],bb[3]); //czegosięterazspodziewamy? //-wypiszenamtylkopołowęoryginalnejtablicy //-aledokładnywynikzależyodarchitekturynaktórejuruchamiamyprogram: //*nalittleendian(np.x86)będzieto:B0:34127856 //*nabigendian(np.sparc)będzieto(bardziejnaturalnedlaczłowieka):B0:12345678}
Fakt, że różne komputery ten sam ciąg zero-jedynkowy mogą interpretować jako różne liczby (wzależności od architektury big endian vs little endian), powoduje że przy wymianie danych międzysystemami konieczne jest ustalenie sposobu tej interpretacji (np. protokoły sieciowe takie jak IPużywająbigendian)lubzawarcietejinformacjiwwymienianychdanych(kodowaniaUnicodeUTF-16iUTF-32zawierająnapoczątkudanychznacznikBOM).
Napisy
Napisy są to ciągi liczb, w których kolejne liczby (pojedynczo lub grupami) interpretowane są jakokolejneznaki (litery).Wprzypadkukodowańoustalonejdługościznaku(np.UTF-32,ASCI)każdan-bitowaliczbaodpowiadajednemuznakowinapisu(przyczymitakmogąsięonegraficznienakładać,
ale każdy jest integralną całością). W przypadku kodowań o zmiennej długości znaku długość znakukodowana jest w ramach tego znaku (np. w UTF-8 długość wynosi od 1 do 4 bajtów, informacja odługościzakodowanajestwpierwszymbajcie,adodatkowebajtymająustawionenajstarszebityna10cojednoznacznieidentyfikujejejakouzupełniające).
Mogąonebyćprzechowywane jako tablica lub lista tablic (ułatwia tooperowaniedużymizmiennyminapisowymi - unikanie relokacji i przepisywania dużej ilości danych). Możliwe jest kilka sposobówprzechowywanianapisuwtablicyróżniącychsięmetodąuzyskiwaniainformacjiokońcunapisu-możeto być osobna zmienna przechowująca długość napisu (lub adres jego końca) albo znacznik końcaprzechowywanywsamymnapisie(wtejrolistosowanejest0wtzw.NULL-endstringachzjęzykaC).
Wprzetwarzaniunapisówbardzoczęstostosowanesąwyrażeniaregularnesłużącedodopasowywanianapisówdowzorcaktóryopisują,wyszukiwaniu/zastępowaniutegowzorca.Dotypowej,podstawowejskładniwyrażeńregularnychzaliczasięm.in.następująceoperatory:
.-dowolnyznak[a-z]-znakzzakresu[^a-z]-znakzpozazakresu(abymiećzakresz^należydaćgonienapoczątku)^-począteknapisu/linii$-koniecnapisu/linii
*-dowolnailośćpowtórzeń?-0lubjednopowtórzenie+-jednolubwięcejpowtórzeń{n,m}-odndompowtórzeń
()-pod-wyrażenie(możebyćużywanedlaoperatorówpowtórzeń,atakżedlareferencjiwstecznych)|-alternatywa:wystąpieniewyrażeniapodanegopolewejstroniealbowyrażeniapodanegoprawejstronie
#include<stdio.h>#include<iostream>
#include<string>#include<string.h>#include<bitset>#include<regex>#include<sstream>
intmain(){ //napisywstyluC //czylitaknaprawdętablicebajtów(znaków) constchar*x="abcdefg"; //wypisaniedługościnapisu printf("%d\n",strlen(x)); //wypisaniepod-napisuod2dokońca puts(x+2); //wyszukiwanie //pod-napisu"cd"wxodpozycji1 constchar*cd=strstr(x+1,"cd"); printf("%d\n",cd-x); //3znakowypod-napisnapisux //rozpoczynającysięodcd charbuf[16]; strncpy(buf,cd,3); buf[3]=0;//NULLend puts(buf); //porównywanie if(strcmp(x,"a")==0) puts("x==\"a\""); if(strncmp(x,"a",1)==0) puts("pierwsze1znakówxto\"a\""); //napisywstyluC++ std::stringxx(x); std::stringy="aabbccbbddbbee"; //wypisaniedługościnapisu std::cout<<xx.size()<<"\n"; //.size()totosamoco.length()
///PrzykładC++
//uzyskanienapisywstyluC puts(xx.c_str()); //wypisaniepod-napisuod2dokońca std::cout<<xx.substr(2)<<"\n"; std::cout<<xx.substr(2,std::string::npos)<<"\n"; //iod0(początku)do3 std::cout<<xx.substr(0,3)<<"\n"; //wyszukiwaniepod-napisu"bb"wyodpozycji5 std::cout<<y.find("bb",5)<<"\n"; //porównywanie if(xx=="a") std::cout<<"x==\"a\"\n"; if(xx.compare(0,1,"a")==0) puts("pierwsze1znakówxto\"a\""); if(std::regex_match(xx,std::regex(".*[dz].*"))) puts("xzawieradlubz"); //regex_matchdopasowujecałośćnapisudowyrażeniaregularnego //dopasowanieczęściowewrazzopcjonalnymuzyskaniem //pasującejczęściumożliwia:std::regex_search() //modyfikowaniestd::string xx="Alamapsa"; //wstawianie-insert(pozycja,co) xx.insert(6,"kotai"); std::cout<<xx<<std::endl; //zastępowanie-replace(pozycja,ile,czym); xx.replace(4,2,"miałasamochód",0,6); //mogłobyteżbyćxx.replace(4,2,"miała");iparęinnychwariantów... std::cout<<xx<<std::endl; //usuwanie-erase(pozycja,ile); xx.erase(9,1);//9zamiast8boUTF-8iłmadwaznaki std::cout<<xx<<std::endl; //zastępowaniezużyciemwyrażeńregularnych std::cout<<std::regex_replace(y,std::regex("[bc]+"),"XX")<<"\n"; //zastępowaniezużyciempodstawienia //$2zostaniezastąpionewartościądrugiepod-wyrażenia, //czylifragmentuujętegownawiasach std::cout<<std::regex_replace( y,std::regex("([bc]+)([bc]+)"),"X-$2-X" )<<"\n"; //konwersjaliczbnanapiswsystemach: //dwójkowym,ósemkowym,dziesiętnymiszesnastkowym std::cout<<std::bitset<8>(7)<<""; std::cout<<std::oct<<0xf<<""; std::cout<<std::dec<<010<<""; std::cout<<std::hex<<0b11<<"\n"; //liczbypodawanedowypisywaniasąwodpowiedniosystemach: //dziesiętnym,szesnastkowym,ósemkowymidwójkowym //wskazanejesttoprzezbrakprefixuiprefixy"0x""0""0b" //alternatywniewstyluprintf,alebezdwójkowego printf("0o%o%d0x%x\n",0xf,010,0b11); //wypisywanieznakówunicodu puts("\u21c4=⇄"); //strumienienapisowe std::ostringstreamzzz; zzz<<xx<<"cpp\n"; zzz<<34.6<<""<<std::oct<<0xf<<""; //konwersjadostd::string xx=zzz.str(); std::cout<<xx<<"\n";
}
importre
x="abcdefg"y="aabbccbbddbbee"z="qw=rt"
#wypisaniedługościnapisuprint(len(x))
#wypisaniepod-napisuod2dokońca#iod0(początku)do3print(x[2:],x[0:3])
#wypisanieostatniegoi3ostatnichznakówprint(x[-1],x[-3:])
#wypisanieco3ciegoznakuznapisuoraznapisuodtyłuprint(y[::3],x[::-1])
#wyszukiwanie#pod-napisu"bb"wyodpozycji5print(y.find("bb",5))
#porównywanieifx=="a": print("x==\"a\"")
ifre.search("[dz]",x): print(x,"zawieradlubz")
#sprawdzanieczyjestpod-napisemif"ab"inx: print("abjestpod-napisem:",x)
#sprawdzanieczyjestpod-napisemif"ba"inx: print("bajestpod-napisem:",x)
#zastępowanieprint(re.sub('[bc]+',"XX",y,2))print(re.sub('[bc]+',"XX",y))
#zastępowaniezużyciempodstawienia#\\2zostaniezastąpionewartościądrugiepod-wyrażenia,#czylifragmentuujętegownawiasachprint(re.sub('([bc]+)([bc]+)',"X-\\2-X",y))
#mamyteżwpływnazachłannośćwyrażeńregularnych:
print(re.sub('bb(.*)bb',"X\\1X",y))#"bb(.*)bb"dopasowałonajdłuższymożliwyfragment,czyli:ccbbdd
print(re.sub('.*bb(.*)bb.*',"\\1",y))#"bb(.*)bb"dopasowałojedynie"dd",bonajdłuższymożliwy#fragmentzostałdopasowanyprzezpoprzedzające".*"
print(re.sub('.*?bb(.*)bb.*',"\\1",y))#"bb(.*)bb"mogłoidopasowałonajdłuższymożliwyfragment,#gdyżbyłopoprzedzoneniezachłannąodmianądopasowania#dowolnegonapisu,czyli:.*?
#Pokażdymzoperatorówpowtórzeń(.?+{n,m})możemydodać#pytajnik(.???+?{n,m}?)abywskazaćżemaondopasowywać#najmniejszymożliwyfragment,czylimadziałaćniezachłannie.
#niedasięmodyfikowaćnapisuzużyciemodwołańx[numer]np.#x[2]="X"#niezadziała
#można(gdydużotegotypumodyfikacji)przepisaćdolisty:l=list(x)#alternatywniemożnamanualnie:# l=[]
###PrzykładPython
# forcinx:# l.append(c)#albotak:# l=[cforcinx]
l[1]="X"l[3]="qqq"dell[5]print("".join(l))
#albotak(gdymniejmodyfikacji)print(x[:2]+"XXX"+x[3:])
#możnatakżemodyfikowaćpokoleiidodawaćdonowegonapisus=""forcinx: ifc=="a": s+="AA" else: s+=c
print(s)
#przypomocymetodysplit()napismożemypodzielić#nalistęnapisówprzypomocydowolnegoseparatoraprint(y.split(""))print(y.split("cc"))
#konwersjaliczbnanapiswsystemach:#dwójkowym,ósemkowym,dziesiętnymiszesnastkowymprint(bin(7),oct(0xf),str(0o10),hex(0b11))
#liczbypodawanedowypisywaniasąwodpowiedniosystemach:#dziesiętnym,szesnastkowym,ósemkowymidwójkowym#wskazanejesttoprzezbrakprefixuiprefixy"0x""0o""0b"
#alternatywniewstyluprintf,alebezdwójkowegos="0o%o%d0x%x"%(0xf,0o10,0b11)print(s)
#wypisywanieznakówzużyciemichnumeruwunikodzie#-funkcjachr()zwracanapiszłożonyzeznakuopodanymnumerze#wramachnapisówmożnateżużyć\uNNNNgdzieNNNNjestnumeremznaku#lubpoprostuumieścićdanyznakwplikukodowanymUTF8print(chr(0x21c4)+"==\u21c4==⇄")
#funkcjaord()umożliwiakonwersjęnapiszłożonego#zpojedynczegoznakunanumerunicodowyprint(hex(ord("⇄")),hex(ord("\u21c4")),hex(ord(chr(0x21c4))))
#PythonużywaUnicodedlaobsługinapisów,jednakprzed#przekazaniemnapisudoświatazewnętrznegokonieczne#możebyćzastosowaniekonwersjidookreślonejpostaci#bytowej(zastosowanieodpowiedniegokodowania)#służydotegometodaencode()np.a="aąbcć...⇄"inUTF7=a.encode('utf7')inUTF8=a.encode()#luba.encode('utf8')print("'"+a+"'wUTF7to:"+str(inUTF7))print("ijesttypu:"+str(type(inUTF7)))
#obiektytypu'bytes'mogązostaćzdekodowanedonapisuprint("zdekodowanyUTF7:"+inUTF7.decode('utf7'))
#lubzostaćpoddanedalszejkonwersjinp.kodowaniubase64:importcodecsb64=codecs.encode(inUTF8,'base64')print("napiswUTF8pozakodowaniubase64to:"+str(b64))
<?php
$x="abcdefg";$y="aabbccbbddbbee";$z="qw=rt";
#wypisaniedługościnapisu
///PrzykładPHP
echostrlen($x)."\n";
#wypisaniepod-napisuod2dokońcaechosubstr($x,2);#iod0(początku)3kolejneznakiechosubstr($x,0,3)."\n";
#wyszukiwanie#pod-napisu"bb"w$yodpozycji5echostrpos($y,"bb",5)."\n";
#porównywanieif($x=="a") echo"$x==a\n";
if(substr_compare($x,"de",3,2)){ echo"2znakowypod-napisod"; echo"pozycji3w$xto\"de\"\n";}
if(preg_match("/[dz]/",$x)){ echo"$xzawieradlubz\n";}
#zastępowanieechostr_replace("bb","BB",$y)."\n";echopreg_replace('/[bc]+/',"XX",$y,2)."\n";echopreg_replace('/[bc]+/',"XX",$y)."\n";
#zastępowaniezużyciempodstawienia#$2zostaniezastąpionewartościąpierwszegopod-wyrażenia,#czylifragmentuujętegownawiasachechopreg_replace('/^([^=]*)=.*$/','$1',$z);echo"=";echopreg_replace('/^[^=]*=(.*)$/','$1',$z);echo"\n";
#wypisywaniewróżnychsystemachliczbowychprintf("0b%b0o%o%d0x%x\n",7,0xf,010,0b11);
?>
#${zmienna:-"napis"}zwrócinapisgdy#zmiennaniejestzdefiniowanalubjestpusta#${zmienna:="napis"}zwrócinapis#orazwykonapodstawieniezmienna="napis"gdy#zmiennaniejestzdefiniowanalubjestpusta#${zmienna:+"napis"}zwrócinapisgdy#zmiennajestzdefiniowanainiepustaa="";b="";c=""echo${a:-"aa"}${b:="bb"}${c:+"cc"}echo$a$b$ca="x";b="y";c="z"echo${a:-"aa"}${b:="bb"}${c:+"cc"}echo$a$b$c
#${#str}zwrócidługośćnapisuwzmiennejstr#${str:n}zwrócipod-napis$strodndokońca#${str:n:m}zwrócipod-napis$strodnodługościmx=abcdefgecho${#x}${x:2}${x:0:3}${x:0:$((${#x}-2))}
#${str#"ab"}zwróci$strzobciętym"ab"zpoczątku#${str%"fg"}zwróci$strzobciętym"fg"zkońcaecho${x#"abc"}${x%"efg"}echo${x#"ac"}${x%"eg"}#wnapisachdoobcięciamożliwejeststosowanieshellowych#znakówuogólniających,czyli*,?,[abc],itd#operator#i%dopasowująminimalnynapisdousunięcia#operatory##i%%dopasowująmaksymalnynapisdousunięciax=abcd.e.fgecho${x#*.}${x##*.}${x%.*}${x%%.*}
#${str/"n1"/"n2"}zwróci$strzzastąpionym
###PrzykładBash
#pierwszymwystąpieniemn1przezn2#${str//"n1"/"n2"}zwróci$strzzastąpionymi#wszystkimiwystąpieniamin1przezn2y="aabbccbbddbbee"echo${y/"bb"/"XX"}echo${y//"bb"/"XX"}
#polecenieexprmatch$x'wr1\(wr2\)wr3'#zwróciczęść$xpasującądowyrażeniaregularnegowr2#wyrażeniaregularnewr1iwr2pozwalająna#określanieczęścinapisudoodrzucenia#alternatywnąskładniąjestexpr$x:'wr1\(wr2\)wr3'z="ab=cd"exprmatch$z'^\([^=]*\)='expr$z:'^[^=]*=\(.*\)$'
#możliwejestteżsprawdzaniedopasowańwyrażeń#regularnychpoprzez(uwaganabrakcytowania):[["$z"=~^([^=]*)=]]&&echo"OK"
#wypisywaniewróżnychsystemachliczbowychprintf"0o%o%d0x%x\n"0xf0103
#dobardziejzaawansowanychoperacji#mogąbyćprzydatnetakżepolecenia:#grepdiffsedawk#joincommpaste
#należyteżpamiętaćoróżnicywdziałaniuecho"$a"i#echo$awprzypadkugdyzmiennaazawieraznakinowejlinii:#-wpierwszymwypadkubędątraktowanejakoznakinowejlinii#-wdrugimjakospacje
#obsługanapisówwbash'uprzypomocystandardowychkomendPOSIXa
#jakożewiększośćoperacjibashowychwiążesięz#uruchamianiemzewnętrznychprogramówtotakże#przetwarzanienapisówmożebyćrealizowanewtensposób
a="aąbcć123"
#obliczaniedługościnapisuwznakach,wbajtachiilościsłówwnapisieecho-n$a|wc-mecho-n$a|wc-cecho-n$a|wc-w
#obliczanieilościlinii(dokładniejilościznakównowejlinii)wc-l</etc/passwd
#wypisanie5pola(rozdzielanego:)zpliku/etc/passwdzeliminacją#pustychliniiorazliniizłożonychtylkozespacjiiprzecinkówcut-f5-d:/etc/passwd|grep-v'^[,]*$'#komendacutwybierawskazanepola,opcja-dokreślaseparator
#alternatywnepodejściezużyciemAWKawk-F:'$5!~"^[,]*$"{print$5}'/etc/passwd
#awkdajedużemożliwościprzyprzetwarzaniutegotyputekstowychbaz#danych...możemynp.wypisywaćwypisywaćpierwszepolewoparciu#owarunkinałożonenainne:awk-F:'$5!~"^[,]*$"&&$3>=1000{print$1}'/etc/passwd
#jakwidaćwpowyższychprzykładachdoposzczególnychpólodwołujemy#siępoprzez$n,gdzienjestnumerempola,$0oznaczacałyrekord
#programdlakażdegorekorduprzetwarzakolejneinstrukcjepostaci#"warunek{komendy}",instrukcjitakichmożebyćwielewprogramie#(przetwarzanesąkolejno)komenda"next"kończyprzetwarzaniedanegorekordu
#separatorpolaustawiamyopcją-F(lubzmiennąFS)domyślnymseparatorem#polajestdowolnyciągspacjiitabulatorów(wodróżnieniuodcut#separatormożebyćwieloznakowymnapisemlubwyrażeniemregularnym)#domyślnymseparatoremrekordujestznaknowejlinii#(możnagozmienićzmiennąRS)
#awkjestprostymjęzykiemprogramowaniaobsługującympodstawowepętle
###PrzykładBash
#iinstrukcjewarunkoweorazfunkcjewyszukująceimodyfikującenapisyecho"abaaabbabbaabbabba"|awk'{ for(i=1;i<=NF;++i){#dlakażdegopolawrekordzie if(i%2==0)#jeżelijegonumerjestparzysty gsub("b+","B",$i);#zastąpwszystkieciągibpojedynczymB ii=index($i,"B")#wyszukajpozycjępod-napisuB if(ii)#jeżeliznalazłtowypiszpozycjęipod-napis printf("#%d%s\n",ii,substr($i,ii))#odtejpozycjidokońca } print$0}'
#AWKobsługujetakżetabliceasocjacyjnepozwalatonp.policzyć#powtórzeniasłówecho"aabbaaeeddaadd"|awk' BEGIN{RS="[\t\n]+";FS=""} {slowa[$0]++} {printf("rekord:%ddone\n",NR)} END{for(sinslowa)printf("%s:%s\n",s,slowa[s])}'#podobnyefektmożemyuzyskaćstosując"uniq-c"(którywypisujeunikalne#wierszewrazzichilością)naodpowiednioprzygotowanymnapisie#(spacjezastąpionenowąlinią,alinieposortowane)echo"aabbaaeeddaadd"|tr'''\n'|sort|uniq-c#jednakrozwiązanieawkmożnałatwozmodyfikowaćabywypisywałopierwsze#wystąpienieliniibezsortowaniapliku
#innąbardzoprzydatnąkomendąjestsedpozwalaonam.innazastępowanie#wyszukiwanegonapodstawiewyrażeniaregularnegotekstuinnymecho"aabbccbbddbbee"|sed-e's#\([bc]\+\)\([bc]\+\)#X-\2-X#g'
#sedowepoleceniesprzyjmuje3argumenty(oddzielanemogąbyćdowolnym#znakiemktórywystąpizas),pierwszytowyszukiwanewyrażenie,drugi#tekstktórymmazostaćzastąpione,atrzecigdyjestgtopowoduje#zastępowaniewszystkichwystąpieńanietylkopierwszego
#należyzwrócićuwagęnaróżnicęwskładniwyrażeniaregularnegopolegającą#napoprzedzaniu(,)i+odwrotnymukośnikiemabyMIAŁYznaczeniespecjalne
#sedzopcją-iiwskazaniemplikumodyfikujezawartościtegopliku#pozwalatonałatwestworzeniefunkcjirekurencyjnegozastępowania:rreplace(){ if[$#-ne2];then echoUSAGE:$1str1str2 return fi grep-R"$1".|cut-f1-d:|uniq|whilereadf;do [-L$f]||sed-e"s#$1#$2#g"-i$f; done;}
varx="abcdefg";vary="aabbccbbddbbee";varz="qw=rt";
//podstawianiewartościzmiennychwnapisieconsole.log(`x=${x}y=${y}z=${z}\n`)
functionecho(a){ //łączenienapisów(lubnapisuiczegoś //comożnaskonwertowaćnanapis) //zużyciemoperatora+ console.log(a+"\n");}
//wypisaniedługościnapisuecho(x.length);
//wypisaniepod-napisuod2dokońcaecho(x.substr(2));//iod0(początku)3kolejneznakiecho(x.substr(0,3));
//wyszukiwanie
///PrzykładJavaScript
//pod-napisu"bb"w$yodpozycji5echo(y.indexOf("bb",5));
//porównywanieif(x=="abcdefg") echo("x==abcdefg");
if(x.search(/[dz]/)>0){ echo("xzawieradlubz");}
//zastępowanieecho(y.replace("bb","BB"));echo(y.replace(/[bc]+/g,"XX"));
//zastępowaniezużyciempodstawienia//$2zostaniezastąpionewartością//pierwszegopod-wyrażenia,//czylifragmentuujętegownawiasachconsole.log( z.replace(/^([^=]*)=.*$/,'$1')+ "="+ z.replace(/^[^=]*=(.*)$/,'$1')+ "\n");
vara=7,b=0xf,c=010,d=0b11;
echo("0b"+a.toString(2))echo("0o"+b.toString(8))echo(c.toString())echo("0x"+d.toString(16))
XML
Extensible Markup Language (XML) jest tekstowym formatem wymiany danych. W odróżnieniu odformatu klasycznego formatu utożsamiającego linię z rekordem złożonym z pól oddzielanychwskazanym separatorem może on w łatwy sposób opisywać bardziej złożoną (drzewiastą a nietabelkową)postaćdanych.DokumentXMLskładasięzzagnieżdżonychwsobieznaczników,każdyznich może posiadać atrybuty oraz wartość, którą jest tekst zawierający lub nie kolejne znaczniki.Kolejnośćwystępowaniaelementówwdokumenciejestznacząca.Każdyznacznikotwierającyposiadaodpowiadający mu znacznik zamykający (np. <b>aa</b>), znaczniki bez wartości mogą być samo-zamykające (np. <g />). Dokumenty HTML mogą być zgodne z wymogami formalnymi XML tymsamymstanowiącdokumentyXML.
//wymagapobraniabibliotekinagłówkowejrapidxml(http://rapidxml.sourceforge.net/)
#include"rapidxml.hpp"namespacerapidxml{namespaceinternal{ //fixbuginrapidxmlhttps://sourceforge.net/p/rapidxml/bugs/16/ template<classV,classC>Vprint_children(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_element_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_data_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_cdata_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_declaration_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_comment_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_doctype_node(V,constxml_node<C>*,int,int); template<classV,classC>Vprint_pi_node(V,constxml_node<C>*,int,int);}}#include"rapidxml_print.hpp"
#include<iostream>#include<string.h>
intmain(){ charxmlString[1024]; strncpy(xmlString, "<a>" "<b>A<h>qwe...rty</h></b>" "ABCD...HIJ..." "<cx=\"q\"w=\"pp\">EEF</c>" "<gy=\"zz\"/>"
///PrzykładC++
"<cx=\"pp\">123<drr=\"oo\">456</d>7890.</c>" "</a>", 1024 ); //utworzenieobiektudrzewaXMLowegowoparciuonapis rapidxml::xml_document<>xmlDoc; xmlDoc.parse<0>(xmlString); //pobraniegłównegowęzła rapidxml::xml_node<>*xmlRoot=xmlDoc.first_node(); std::cout<<"nazwagłównegoelementuto:"<<xmlRoot->name()<<"\n"; std::cout<<"jegozawartośćtekstowato:"<<xmlRoot->value()<<"\n"; std::cout<<"jegowartośćto:{{{{"<<*xmlRoot<<"}}}}\n"; std::cout<<"jegopotomkowieto:\n"; rapidxml::xml_node<>*xmlNode=xmlRoot->first_node(); while(xmlNode){ std::cout<<""<<xmlNode->name()<<":"; rapidxml::print(std::cout,*xmlNode,rapidxml::print_no_indenting); //rapidxml::print()możezapisywaćtakżedonapisu std::cout<<"\n"; xmlNode=xmlNode->next_sibling(); } std::cout<<"pierwszywęzełcmaatrybuty:\n"; xmlNode=xmlRoot->first_node("c"); if(xmlNode){ rapidxml::xml_attribute<>*xmlAtrib=xmlNode->first_attribute(); while(xmlAtrib){ std::cout<<xmlAtrib->name()<<"="<<xmlAtrib->value()<<"\n"; xmlAtrib=xmlAtrib->next_attribute(); } } //modyfikacjedokumentu: //zmiananazwyizawartościelementu xmlNode=xmlRoot->first_node("g"); if(xmlNode){ xmlNode->name("noweGG"); xmlNode->value("!@#$"); } //zmiananazwyiwartościatrybutu xmlNode=xmlRoot->first_node("c"); if(xmlNode){ rapidxml::xml_attribute<>*xmlAtrib=xmlNode->first_attribute(); while(xmlAtrib){ if(xmlAtrib->name()==std::string("w")){ xmlAtrib->name("uu"); xmlAtrib->value("123"); break; } xmlAtrib=xmlAtrib->next_attribute(); } } //usuwaniewszystkichpotomkówostatniego<c> xmlNode=xmlRoot->last_node("c"); xmlNode->remove_all_nodes(); xmlNode->value(""); //usuwaniewszystkichatrybutów... xmlNode->remove_all_attributes(); //sąteżfunkcjeusuwającewskazanegopotomkalubatrybut: //remove_node()iremove_attribute() //dodawanieatrybutów xmlNode->append_attribute( xmlDoc.allocate_attribute("abc","098") ); xmlNode->append_attribute( xmlDoc.allocate_attribute("qwe","...") ); //powyższametodadodajenakoniec,możnatakżedodawaćnapoczątek: //prepend_attribute()lubnawskazanąpozycjęinsert_attribute()
//dodawaniepotomków rapidxml::xml_node<>*xmlNode2; xmlNode2=xmlDoc.allocate_node(rapidxml::node_data,NULL); xmlNode2->value("ert"); xmlNode->append_node(xmlNode2); xmlNode2=xmlDoc.allocate_node(rapidxml::node_element,"kk"); xmlNode2->value("uio"); xmlNode->append_node(xmlNode2); xmlNode2=xmlDoc.allocate_node(rapidxml::node_data,NULL); xmlNode2->value("bnm"); xmlNode->append_node(xmlNode2); //podobniejakatrybutynodyteżmożemydodawaćnapoczątku //prepend_node()lubnadowolnejpozycjiinsert_node() //wypisaniezmienionegodokumentu std::cout<<xmlDoc;}
importxml.etree.ElementTreeasxml#PythonoferujetakżeinnenizElementTreemodułydoobsługiXML#takżewspierająceDOM
d="""<a> <b>A<h>qwe...rty</h></b> ABCD...&'HIJ... <cx="q"w="pp">EEFĄ</c> <gy="zz"/> <cx="pp">123<drr="oo">456</d>7890.</c></a>"""
rootNode=xml.fromstring(d)
#pobieranieinformacjizdokumentu
print("nazwagłównegoelementuto:",rootNode.tag)print("jegozawartośćtekstowato:",rootNode.text)print("jegopełnazawartośćtekstowato:","".join(rootNode.itertext()))print("jegowartośćto:{{{{",xml.tostring(rootNode,encoding="unicode"),"}}}}")
print("jegopotomkowieto:")forcinrootNode: print("",c.tag,":",xml.tostring(c,encoding="unicode"))
print("pierwszywęzełcmaatrybuty:")try: ci=rootNode.iter("c") print(next(ci).attrib)exceptStopIteration: print("[braktakiegowęzła]")
#modyfikacjedokumentu
#zmiananazwyizawartościelementutry: ci=rootNode.iter("g") cc=next(ci); cc.tag="noweGG" cc.text="!@#$"exceptStopIteration:pass
#zmiananazwyiwartościatrybututry: ci=rootNode.iter("c") cc=next(ci); delcc.attrib["w"] cc.attrib["uu"]="123"exceptStopIteration:pass
try: cc=next(ci); #usuwaniewszystkichpotomkówdrugiego<c> cc.clear()
###PrzykładPython
#jestteżremove()któreusuwawskazanyelement #usuwaniewszystkichatrybutów... cc.attrib.clear() se=xml.SubElement(cc,"kk",attrib={"aa":str(45)}) se.text="uio" se=xml.SubElement(cc,None) se.text="bnm" #możliwejestteżwstawieniewpodanymmiejscu se=xml.Element(None) se.text="ert" cc.insert(0,se)exceptStopIteration:pass
print(xml.tostring(rootNode,encoding="unicode"))
<?xmlversion="1.0"encoding="utf-8"?><!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><htmlxmlns="http://www.w3.org/1999/xhtml"xml:lang="pl"><head> <metahttp-equiv="ContentType"content="application/xhtml+xml;charset=utf-8"/></head><body>
<divid="xyz"> <p> <bid="abc">Lorem<i>ipsum</i></b>dolorsitamet,<i>consectetur</i>adipiscingelit. <ulclass="typAtypX"> <li>Sedcongue,erosquisultriciesornare,</li> <li>massasemauctorarcu,etsemperexarcuidaugue.</li> <li>Fuscepretium<i><b>turpis</b></i>massa,maximus<i>dapibus</i>sitamet.</li> <li>Nullafermentummolestiefinibus.</li> </ul>Etiamaccumsan<i>tempus</i>anteatcongue.</p> <pdata-abc="123"data-zz="0"class="az"id="q23y"> Sedfeugiatvestibulumsapienegetiaculis.<br/> Integerquismagnaneclacustemporsagittis. </p></div>
<scripttype="text/javascript">//<![CDATA[functionfff(){ console.log("wszystkieelementy<i>wdokumencie:"); vara=document.getElementsByTagName("i"); for(varj=0;j<a.length;j++){ console.log(a[j].innerHTML+"\n"); }
//modyfikacjazawartościelementuoid="abc" varb=document.querySelector("#abc"); b.innerHTML="ABC<u>ABC</u>ABC";
//potomkowierodzicawskazanegoelementu varchild=b.parentNode.firstElementChild while(child){ console.log("potomekjestwęzłem:"+child.nodeName+"\n"); if(child.nodeName=="ul"){ //jeżelijesttolista<ul> //któraposiada(wśródklasspodanychwatrybucieclass)klasę"typA" //tojąusuńidodajklasę"typB" if(child.classList.contains('typA')){ child.classList.remove('typA'); child.classList.add('typB'); } } child=child.nextElementSibling; } varc=document.querySelector("#xyz"); //drugipotomektypu<p>elementuokreślonegowzmiennejc vard=c.querySelector("p:nth-of-type(2)"); console.log("maatrybuty:") for(vari=0;i<d.attributes.length;++i){ console.log(""+d.attributes[i].name+"="+d.attributes[i].value+"\n");
///PrzykładXHTML+JavaScript
} //możnateżpytaćokonkretnyatrybut console.log("abc=>"+d.getAttribute("data-abc")); //orazustawić(zarównododaćnowyjakizmienićistniejący) d.setAttribute("data-def","tyui");}
addEventListener('DOMContentLoaded',fff,false);//]]></script>
</body></html>
JSON
JavaScript Object Notation (JSON) jest tekstowym formatem wymiany danych. Podobnie jak XMLreprezentujeondrzewiastastrukturę,jednakwodróżnieniuodXMLkolejnośćelementówwdanychwejściowychniezawszeprzekładasięnakolejnośćwdanychzinterpretowanych.Wiążesiętoztymiżwyróżniasiędwatypuelementów.Pierwszyznichobejmowanywnawiasyklamrowe i składasięzpar klucz-wartość, jest on interpretowany jako słownik / tablica asocjacyjna i w jego wypadkuidentyfikacjaelementuodbywasięwyłączniepokluczu(którymusibyćunikalny),akolejnośćniemaznaczenia.Drugijestobejmowanywnawiasykwadratoweiskładasięwyłączniezkolejnychwartości,jestoninterpretowanyjakozwykłatablicalublista.
importjsonfrompprintimportpprint
a='''{"info":"bbb","ver":31,"d":[ {"a":21,"b":{"x":1,"y":2},"c":[9,8,7]}, {"a":17,"b":{"x":6,"y":7},"c":[6,5,4]}]}'''
#interpretacjanapisujakozbiorudanychwformaciejsond=json.loads(a)
#wypisaniezbiorudanychpprint(d)#pprintładnieformatujezłożonezbiorydanych
#jakwidaćjesttozagnieżdżonastrukturalistisłowników#odpowiadająca1do1temucobyłownapisie
#dostępdoposzczególnychelementów:"popythonowemu"print(d["d"][1]["b"])print(d["d"][1]["b"]["x"])print(d["d"][1]["c"][1])
#przygotowaniemnowegozbiorudanychb={'aa':'pp','b':[3,4,5],'c':d}b['e']="test"b['f']={'a':1,'b':2}
#wygenerowaniejson-owegotekstuwoparciuoniegoc=json.dumps(b,indent=1,ensure_ascii=False)print(c)
#dlaporównania:pprint(b)
wykonywanienapisu
Częstowygodniejestmiećmożliwośćwykonaniakawałkakodudanegojęzyka,któryjestzapisanywzmiennejnapisowej.Większośćjęzykówskryptowychpozwalatozrobić.Jakożefunkcjetepozwalająnawykonywaniedowolnegokodutoszczególnąostrożnośćnależyzachowaćprzekazującdonichdanewprowadzaneprzezużytkownika.
#dlakodupythonowego
###PrzykładPython
###PrzykładPython
a="""print("ppp")b=13-17"""exec(a)print(b)
#dlawyrażeńa="9+7"b=eval(a)print(b)
#lubexec("c="+a)print(c)
#oczywiścienapismożepochodzićz#dowolnegoźródła,możebyćteż#treściącałegoskryptupythonowego:#exec(open("plik.py").read())
#dlakodubashowegoa='echo"ppp";b="ooo"'eval$aecho$b
#dlaobliczeńarytmetycznycha="13+17"b=$(($a))echo$b
#alternatywnieprzez#zewnętrznykalkulatornp.:b=`echo$a|bc`echo$b
<?php$a='echo"aaa";$b="cc";';eval($a);echo"\n".$b."\n";
$a='2+6';eval('$b='.$a.';');echo$b."\n";?>
//dlakodujavascripta="console.log('AAA');b='www';"
eval(a);console.log("bto:"+b+"\n");
//dlawyrażeńa="5+7"b=eval(a)console.log("bto:"+b+"\n");
PodstawoweI/OStandardowewejście/wyjście
Typowo program posiada trzy strumienie danych: jeden wejściowy (stdin) i dwa wyjściowe (stdout istderr).Jeżeliniezostałodokonaneprzekierowaniestrumieni(np.napliklubstrumieńinnegoprocesu)tostandardowewejście(stdin)powiązanejestzdanymiwprowadzanymiinteraktywniezklawiatury,astandardowe wyjście (stdout) i standardowe wyjście błędu (stderr) z danymi wyświetlanymi naterminalunaktórymuruchomionoprogram(itypowopóźniejwyświetlanymigdzieśnaekranie).
Standardowewejścieiwyjściemożebyćwykorzystywanedo:przekazywania między programami kolejnych etapów przetwarzania jakiegoś zbioru danych(zwykletekstowego):np.grepin.txt|sort>out.txt(grepwybieraliniespełniającekryteria,asortsortujewynik)interaktywnejobsługiprogramu:programpytaokolejneparametryipobierajezstandardowego
###PrzykładBash
///PrzykładPHP
///PrzykładJavaScript
wyjścia(podejścienależystosowaćzrozwagągdyżtakieprogramyciężkoużywasięwskryptach-lepszymrozwiązaniemjestprzyjmowanieparametrówzliniipoleceń)
#include<stdio.h>
intmain(){ // //wyjście/wyjściewstyluC // //wykorzystywanejużwcześniejfunkcje //putsiprintfkorzystajązstdout puts("Helloworld"); printf("0x%x==%d==%.3f\n",13,13,13.0); //jeżelichcemykorzystaćzinnegostrumienia //należyużyćwariantupozwalającegonapodanie //plikudoktóregomasięodbywaćzapis: //stdout-standardowewyjście //stderr-standardowewyjściebłędu fputs("Helloworld2",stderr); fprintf(stderr,"0x%x==%d==%.3f\n",13,13,13.0); //wczytanienapisuzstandardowegowejścia: charnapis[10]; fgets(napis,10,stdin); //wczytanynapisbędziemiał9znaków+NULL-end //zapominamyoreszcieinputujeżelibyłdłuższyniż9znaków if(napis[8]!='\n'){ intc; while((c=getchar())!='\n'&&c!=EOF); } //wczytanieliczbyzstandardowegowejścia: intd; fscanf(stdin,"%i",&d); fprintf(stdout,"liczba:%dnapis:\"%s\"\n",d,napis);}
#include<iostream>#include<limits>#include<iomanip>
intmain(){ // //wyjście/wyjściewstyluC++ // //standardowewyjścieistandardowe //wyjściebłędujakostrumienieC++ std::cout<<"HelloC++world\n"; std::cerr<<"HelloC++world2\n"; //strumieniepozwalająnaprostewypisywaniezmiennych, //alejeżelichcemyformatowaćwyjścieto //pisaniajestwięcejniżwprintf intd=1363; std::cout<<"d="<<d<<"d/3="<<d/3.0<<"\n"; std::cout<<std::setprecision(3)<<1.2342; std::cout<<""<<23.567<<"\n"; //wczytanienapisuzstandardowegowejścia: charnapis[10]; std::cin.getline(napis,10); if(std::cin.fail()){ //zapominamyoreszciejeżelibyła std::cin.clear(); std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); }
///PrzykładC++
///PrzykładC++
//wczytanieliczbyzstandardowegowejścia: std::cin>>d; std::cout<<"liczbato:"<<d; std::cout<<"napisto:\""<<napis<<"\"\n";}
importsys
#wypisywanienastandardowewyjścieprint("ABC:"+str(12)+"="+hex(12))
#beznowejliniinakońcuprint("abc",end='')
#wypisywanienastandardowewyjściebłęduprint("QWE",file=sys.stderr)
#odczytzwejściali=iter(sys.stdin)liniaA=next(li)liniaB=next(li)print("l1:"+liniaA+"l2:"+liniaB)
#możnateżzużyciemmetodyczytającejjednąlinięliniaA=sys.stdin.readline()liniaB=sys.stdin.readline()print("l1:"+liniaA+"l2:"+liniaB)
#należyzauważyćżedanewczytywanesą#liniamiizawierająznakkońcalinii
#możnatakżewramach:#forlinsys.stdin:##lubskorzystaćzmetodywczytującejcałyplik#jakolistęposzczególnychjegolinii:#ll=sys.stdin.readlines()#bądźpoprostujakojedennapis#napis=sys.stdin.read()
#jestteż:info=input("Wpiszcoś:")print(info)
f1(){ #wypisywanienastandardowewyjście echo"HelloWorld" printf"%d%.3f\n"12313.15686 #wypisywanienastandardowewyjściebłędu echo"HelloWorld2">/dev/stderr echo"ABC">/dev/stderr}
f2(){ #odczytzestandardowegowejścia #readwczytujedanezstdindopodanychzamiennych #wtakisposóbżedokolejnychzmiennychtrafiają #kolejnesłowa(napisyrozdzielanespacjąlub #tabulatorem),adoostatniejzmiennejresztanapisu #(dokońcaliniibezznakukońcalinii) whilereadab;do echo$(($a+$b)) done}
#przekierowaniastrumienistandardowych:
#wyjściezechoprzekierowywanejestnawejścief2echo-e"23\n16"|f2
###PrzykładPython
###PrzykładBash
#wyjściaf1doodpowiednichplikówf1>/tmp/out.txt2>/tmp/err.txt
#użycie>>zamiast>spowodujedopisywaniedopliku#zamiastnadpisywaniajegozawartości
#połączonychwyjść(normalnegoibłędu)f1dogrepf1|&grep-vHello
#standardowewyjściemożezostaćprzechwyconei#podstawionewdanymmiejscupoprzezużycie#`polecenie`lub$(polecenie)echoXXX`ls-ld/tmp`echoXXX$(ls-ld/tmp)
#częstoteżchcemyzignorowaćstandardowewyjściei/lub#standardowewejście-możemytouzyskaćprzekierowując#jedo/dev/nullnp:grep'^root:'/etc/passwd>/dev/null
#przekierowaniewyjściacatdopliku/tmp/liczby#<<EOFpowodujeżebashpodajenastandardowe#wejściekomendy(wtymwypadku"cat")daneczytane#zskryptu(lubswojegowejścia)dopókiniewystąpi#wnowejliniisłowopodanepo<<(wtym#wypadkuEOF),jeżelisłowotojestujętew''to#wprzekazywanymtekścieniesądokonywanepodstawienia#shellowe(np.rozwijanezmienne)cat<<EOF>/tmp/liczby1313994710EOF
#przekierowaniepliku/tmp/liczby#nastandardowewejścief2f2</tmp/liczby
zewzględunaspecyfikętegojęzykawszystkocojestpozaznacznikamiphpbędziewypisywanenastandardowewyjście<?php echo"sątakżefunkcje"; print("realizującewypisywanie\n"); printf("%d%.3f\n",13,45.33221);?>
Obsługaplików
Zasadniczoobsługaplikówpodwzględemoperacjiwykonywanychpomiędzyotwarciemazamknięciemplikuniewieleróżnisięodobsługistandardowego/wejściaiwyjścia.Wzdecydowanejwiększości(jeżelinawetniewewszystkich)językówinterfejsobsługistandardowegowejściaiwyjściajestzunifikowanyzinterfejsemobsługiplików.
#include<stdio.h>
intmain(){ // //obsługaplikówwstyluC // //otwieramyplikokreślonywpierwszymargumencie, //wtrybieokreślonymwdrugimargumencie: //r-odczyt,w-zapis,a-dopisywanie, //+-dwukierunkowy(używanepor,walboa) FILE*plik=fopen("/tmp/plik1.txt","w+"); //zapisujemydopliku fputs("HelloWorld!!!\n",plik); fprintf(plik,"%.3f\n",13.13131); //jakożesątooperacjebuforowanetoabymieć
///PrzykładPHP
///PrzykładC++
//pewnośćżetojestjużwplikunależywykonać //fflush(),niejesttokoniecznegdyzamykamy //plik(wtedywykonywanejestzautomatu) fflush(plik); intpoz=ftell(plik); printf("aktualnapozycjawplikuto%d\n",poz); //przewijamydopoczątku //jesttorównoważnerewind(plik); fseek(plik,0,SEEK_SET); //wczytywaniezpliku charnapis[10]; fgets(napis,10,plik); //wczytanynapisbędziemiał9znaków+NULL-end puts(napis); //powrotdopoprzedniejpozycji fseek(plik,poz,SEEK_SET); //operacjebinarne-wtensposóbmożemyzapisywać //iodczytywaćcałebuforyzpamięci,czylitakżenapisy //zapisdopliku doublex=731.54112,y=12.2; fwrite(&x,1,sizeof(double),plik); fflush(plik); //przesunieciedopozycjinaktórejzapisywaliśmy fseek(plik,poz,SEEK_SET); //iodczytzpliku... fread(&y,1,sizeof(double),plik); printf("zapisano:%f,odczytano:%f\n",x,y); //sątakżefunkcjeread()iwrite()działającewoparciuo //numerycznydeskryptorplikuuzyskiwanynp.zfunkcjiopen() //anieobiektFILEuzyskiwanyzfopen() fclose(plik);}
#include<iostream>#include<fstream>
intmain(){ // //obsługaplikówwstyluC++ // //tworzymystrumieńzwiązanyzplikiem std::fstreamplik_w; //otwieramyplikwtrybiedopisywania //alepozwalającymnamodyfikowanieobecnejtreści //abytodziałałomusibyćtostrumieńin/out plik_w.open( "/tmp/plik2.txt", std::fstream::ate|std::fstream::out|std::fstream::in ); //tworzymystrumień(typuin)związanyzplikiem... std::ifstreamplik_r; //otwieramyplikdoczytania plik_r.open("/tmp/plik1.txt"); //trybymożemybudowaćznastępującychopcji: //std::ios::in-odczyt(domyślnadlaifstream) //std::ios::out-zapis(domyślnadlaofstream) //std::ios::ate-ustawiepozycjinakoniecpliku //std::ios::app-dopisywaniebezmożliwościzmianyzawartości //std::ios::trunc-nadpisujeplik std::cout<<"PozycjawplikuOUT:"<<plik_w.tellp()<<std::endl; std::cout<<"PozycjawplikuIN:"<<plik_r.tellg()<<std::endl;
///PrzykładC++
//pisanieiczytaniedokładniejakdlacincout... plik_w<<"HelloWorld!!!"; //przesunięciena16bajtblikuwejściowego plik_r.seekg(16); //iwczytanieczegoś doublex; plik_r>>x; std::cout<<"wczytano:"<<x<<"\n"; //przesunięcieo2bajtydotyłuiwczytanie plik_r.seekg(-2,std::ios::cur); //innetrybyprzesunięćto: //ios::beg-odpoczątkupliku(domyślny) //ios::end-odkońcapliku plik_r>>x; std::cout<<"wczytano:"<<x<<"\n"; plik_w.seekp(-3,std::ios::end); plik_w<<123<<"\n"; //nmakonieczamykamypliki plik_w.close(); plik_r.close();}
importos.path
#otwarcieplikudoodczytuf=open("/etc/passwd","r")#funkcjapozwalanaokreśleniekodowaniaplikupoprzez#argumentnazwany"encoding"(np.encoding='utf8'),#domyślnekodowaniezależnejestodustawieńsystemowych#możnajesprawdzićpoprzezlocale.getpreferredencoding()##jeżeliplikmabyćotwartywtrybiebinarnymanie#tekstowymkoniecznejestpodanieflagibwramach#drugiegoargumentu
#odczytpoliniil1=f.readline()l2=f.readline()
#możnatakżeczytaćzjawnymużyciemiteratorów:li=iter(f)l3=next(li)l4=next(li)
print("l1:"+l1+"l2:"+l2+"l3:"+l3+"l4:"+l4)
#albowramachpętlii=5forlinf: print(str(i)+":"+l) i+=1
#powrótnapoczątekplikuf.seek(0)
#odczytjakotablicaliniill=f.readlines()
print(ll)
f.close()
#jeżeliplikistniejeto:ifos.path.isfile("/tmp/plik3.txt"): #otwieramywtrybiedozapisuiodczytu #iustawiamysięnakońcuplikucelemdopisywania f=open("/tmp/plik3.txt","r+") f.seek(0,2)else: f=open("/tmp/plik3.txt","w")
#pobieramyaktualnąpozycjewpliku
###PrzykładPython
#(którawtymwypadkujestrównadługościpliku)pos=f.tell()
#jeżeliplikmawięcejniż5bajtówifpos>5: #tocofamysięo3 f.seek(pos-3)
f.write("0123456789")
f.close()
#obsługaplikówbinarnych#wymaganejestdodanieflagibwflagachfunkcjiopen():f=open("/tmp/plik1.txt","rb")
#czytaniebajpobajciewhileTrue: b=f.read(1) ifb==b"": break print(b)
f.close()
Mapowanieplikówwpamięci
Możliwe jest także operowanie na plikach zmapowanych do pamięci z użyciem mmap, operacjewykonywanesąwtedynaichzawartościtakjaknatablicach/napisachC.
//programkorzystazmechanizmówsystemówPOSIX//imożeniedziałaćnaniekompatybilnychplatformach
#include<sys/mman.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>
#include<errno.h>#include<string.h>#include<stdio.h>
#define_MMAP_MODE_MAP_PRIVATE//MAP_SHARED
//MAP_PRIVATEpowodujebezwidocznościzmianwmapowanymplikudlainnychprocesów//MAP_SHAREDpozwalawspółdzielićzamapowanyobszarzinnymiprocesami,//jestwymaganeabymóczmodyfikowaćplikzużyciemmsync()
intmain(){ constchar*fname="/tmp/aaa.txt"; intfsize;
//pobieramyrozmiarpliku structstatst; if(stat(fname,&st)){ if(errno==ENOENT){ printf("plik\"%s\"nieistnieje\n",fname); fsize=0; }else{ fprintf(stderr,"Errorinstat():%s\n",strerror(errno)); //powyższezadziałajakperror() return-1; } }else{ fsize=st.st_size; }
//otwieramyplikwtrybiezapis-odczytuzyskującdeskryptor //(jeżelipliknieistniejezostanieutworzonyzprawami600) intfd=open(fname,O_RDWR|O_CREAT,(mode_t)0600); intbufSize=fsize+20; //jeżelichcemyoperowaćnawiększymbuforzeniżrozmiarplikumusimypowiększyćplik
///PrzykładC++
if(ftruncate(fd,bufSize)) perror("Errorinftruncate()"); //operacjataniemawpływunazajmowanemiejscenadysku: //intfd=open("/tmp/x",O_RDWR|O_CREAT);ftruncate(fd,100000000);close(fd); //utworzyplik/tmp/xktóregorozmiarwg`ls`będzie98MBawg`du`będzie0 //alternatywniemożna: //lseek(fd,bufSize-1,SEEK_SET);write(fd,"",1);lseek(fd,0,SEEK_SET) //mapujemyplikdopamięci...wtrybieodczytuizapisu char*buf=(char*)mmap(NULL,bufSize,PROT_READ|PROT_WRITE,_MMAP_MODE_,fd,0); if(buf==MAP_FAILED){ perror("Errorinmmap()"); return-1; }
buf[fsize]=0; printf("Długośćpliku:%d\n",fsize); printf("Zawartośćpliku:%s\n",buf);
//modyfikujemyprzedostatnibajtwpliku //(jeżelitrafimynafragmentwielo-bajtowegoznakutogopopsujemy) if(fsize>2) buf[fsize-2]='X';
fsize+=snprintf(buf+fsize,bufSize-fsize,"Alamakota\n\n"); fsize+=snprintf(buf+fsize,bufSize-fsize,"KotmaAlę\n\n"); fsize+=snprintf(buf+fsize,bufSize-fsize,"czyżby...\n\n"); //doplikuchcemyzapisać"fsize"bajtówz"buf",czyli:buf[0]...buf[fsize-1] //niechcemyzapisaćkończącegonapisznakuNULL(dodawanegoprzezsnprintf), //jeżeliniedoszłodoprzepełnieniabuforaniejestonwliczanywdługość"fsize" //iznajdujesięwbuf[fsize],zatemniemakoniecznościjawnegopomijaniago // //jeżelinatomiastdoszłodoprzepełnieniabuforajestonostatnimznakiemwbuforze, //czylibuf[bufSize-1]...zatemabygopominąćnależyustawićfsize=bufSize-1 if(fsize>=bufSize){ fprintf(stderr,"Error:przepełnieniebufora\n"); fsize=bufSize-1; } printf("Nowadługośćpliku:%d\n",fsize); printf("Nowazawartośćpliku:%s\n",buf); //ustawiamyprawidłowyrozmiarpliku if(ftruncate(fd,fsize)) perror("Errorinftruncate()");#if_MMAP_MODE_==MAP_SHARED //synchronizujemyzawartośćbuforapamięcidopliku if(msync(buf,fsize,MS_SYNC)) perror("Errorinmsync()");#else //zapisujemyzmianydopliku if(write(fd,buf,fsize)<0) perror("Errorinwrite()");#endif //odmapowanieplikuzpamięci if(munmap(buf,fsize)) perror("Errorinmunmap()"); //zamknięciepliku close(fd);}
Operacjenaplikach
Często oprócz zapisywania i czytania plików zachodzi potrzeba sprawdzenia czy plik istnieje,wylistowaniaplikówzjakiegośkatalogu,zmianynazwylubusunięciapliku.Stosownefunkcjeoferujebiblioteka standardowa C (w oparciu o nie realizowane są komendy shellowe wykonujące takieoperacje), a także większość innych języków. W przypadku C++ można korzystać z bibliotekistandardowejClubbibliotekiboost(jakwponiższymprzykładzie).
//przykompilacjikoniecznejestdodanie://-lboost_filesystem-lboost_system
///PrzykładC++
#include<iostream>#include<boost/filesystem.hpp>
intmain(){ //sprawdzenieczyplikistnieje boost::filesystem::pathpFile("/tmp/abc.txt"); if(boost::filesystem::is_regular_file(pFile)) std::cout<<"istnieje\n"; else std::cout<<"nieistnieje\n"; //listowaniekataloguisprawdzanietypów boost::filesystem::pathpDir("/tmp/"); boost::filesystem::directory_iteratorend_iter; boost::filesystem::directory_iteratoriter(pDir); for(;iter!=end_iter;++iter){ if(boost::filesystem::is_regular_file(iter->path())){ std::cout <<iter->path().filename().generic_string() <<"jestplikiem\n"; //wypisujemytylkonazwępliku }elseif(boost::filesystem::is_directory(iter->path())){ std::cout <<iter->path().generic_string() <<"jestkatalogiem\n"; //wypisuje,ypełnąścieżkę }else{ std::cout <<iter->path().generic_string() <<"jestczymśinnym\n"; } } boost::filesystem::rename("/tmp/a.txt","/tmp/b.txt"); boost::filesystem::remove("/tmp/b.txt");}
importos
#sprawdzenieczyplikistniejeifos.path.isfile("/tmp/abc.txt"): print("istnieje")else: print("nieistnieje")
#listowaniekataloguisprawdzanietypówdl=os.listdir("/tmp/")print(dl)
forfindl: ifos.path.isfile(f): print("\""+f+"\"jestplikiem") elifos.path.isdir(f): print("\""+f+"\"jestkatalogiem") else: print("\""+f+"\"jestczymśinnym")
#możnatakżerekurencyjniewrazzpodkatalogamiforcurrDir,dirs,filesinos.walk('/tmp'): print("podkatalogi\""+currDir+"\":") fordindirs: print(""+os.path.join(currDir,d)) print("plikiw\""+currDir+"\":") forfinfiles: print(""+os.path.join(currDir,f))
#zmiananazwyos.rename("/tmp/a.txt""/tmp/b.txt")
#usuwanieos.remove("/tmp/b.txt")
###PrzykładPython
###PrzykładBash
#sprawdzenieczyplikistniejeif[-f"/tmp/abc.txt"];then echo"istnieje"else echo"nieistnieje"fi
#listowaniekataloguisprawdzanietypówforfin/tmp/*;do if[-f"$f"];then echo"\"$f\"jestplikiem" elif[-d"$f"];then echo"\"$f\"jestkatalogiem" else echo"\"$f\"jestczymśinnym" #np.kolejkąluburządzeniem... fidone
#alternatywnelistowaniekataloguls/tmp|whilereadf;do echo"/tmpzawiera:$f"done
#zmiananazwymv/tmp/a.txt/tmp/b.txt
#usuwanierm/tmp/b.txt
Argumentyliniipoleceń
System pozwala na przekazanie do uruchamianego programu zbioru argumentów / opcji, któreprogrammożedowolniezinterpretowaćiwykorzystaćwswoimdziałaniu.
Od systemu program otrzymuje nie zinterpretowaną tablicę argumentów. Za podział całego zbioruargumentów, na poszczególne elementy tablicy odpowiada program tworzący nowy proces. Typowonapisprzekazanywliniipoleceńdzielonyjestnasłowa(ciągiznaków,rozdzielanebiałymiznakami)ikażde słowo stanowi osobny element tablicy, wyjątkiem są napisy ujęte w cudzysłowia któreprzekazywanesąjakopojedynczyargument(elementtablicy).
W świecie POSIXowym przyjętym standardem jest podawanie opcji jednoliterowych po pojedynczymmyślnikuzmożliwością ichgrupowania(np.ls-la totosamocols-l-a),aopcjidługichpodwóchmyślnikach. Ewentualne argumenty opcji podawane są zaraz po opcji i w przypadku opcji krótkichoddzieloneodniejspacją,awprzypadkuopcjidługichpoznakiemrówności (np.ls--color=auto).Poopcjachwystępująargumentypozycyjne(np.listaplikówktóremawyświetlićls).
Obsługę takiego stylu przekazywania opcji do programu (w oparciu o surową tablicę argumentów)zapewniająlicznebiblioteki(takżestandardowebibliotekiróżnychjęzykówprogramowania).
//przykompilacjikoniecznejestdodanie://-lboost_program_options
#include<boost/program_options.hpp>#include<iostream>
//pełnadeklaracjafunkcjimaindlasystemówPOSIX//funkcjamainotrzymuje://-liczbęelementówtablicyargumentów//-tablicęargumentów(jesttotablicanapisówtypuC)//-tablicęzmiennychśrodowiskowychintmain(intargc,char*argv[],char*envp[]){ std::cout<<"programwywołanoz"<<argc<<"argumentami\n"; for(inti=0;i<argc;++i) std::cout<<"argument"<<i<<"to:"<<argv[i]<<"\n"; //deklaracjaopcjiliniipoleceń boost::program_options::options_descriptiondesc("Programoptions"); desc.add_options() ("help,h","showhelpmessage") ("load",boost::program_options::value<std::string>(), "loadfrom\"arg\"file") ;
///PrzykładC++
//parsowanieopcjiliniipoleceńwrazzobsługąwyjątków boost::program_options::variables_mapvm; try{ boost::program_options::store( boost::program_options::parse_command_line(argc,argv,desc),vm ); boost::program_options::notify(vm); }catch(boost::program_options::error&e){ std::cerr<<"Cmdlineargserror:"<<e.what()<<"\n\n"; std::cerr<<"Use--helptoseefulloptionsdescription\n"; return2; } //przetwarzanieotrzymanychopcji if(vm.count("help")){ std::cout<<desc<<"\n"; }elseif(vm.count("load")){ std::cout<<"Loadfrom:"<<vm["load"].as<std::string>()<<"\n"; }else{ std::cout<<"Wywołanobezopcji\n"; } //jestteżfunkcjagetopt_long()zbibliotekistandardowejC //funkcjamainpowinnazwracaćkodpowrotu //typowo:gdyprogramzakończysiępowodzeniemzero //agdyzakończysiębłędem(niezerowy)kodbłędu return0;}
importargparse
#parseragumentówliniipoleceń#doargumentówmożnasięteżdostawaćbezpośredniopoprzezsys.argv:#len(sys.argv)-ilośćelementówtejtablicy#str(sys.argv[0])-napisodpowiadającynazwiewywołaniaprogramu#str(sys.argv[1])-napisodpowiadającypierwszemuargumentowiprogramu
parser=argparse.ArgumentParser(description='Opisprogramu')parser.add_argument( 'ARG',default='ABC',nargs='?', help='argumentpozycyjny(opcjonalnyzwartościądomyślną)')parser.add_argument( '-v',"--verbose",action="store_true", help='opcjatypuprzełącznik')parser.add_argument( "--input",action="store", help='opcjazargumentem')
parser.add_argument( "--vector",action="store",metavar='V',nargs='*', help='opcjazwielomaargumentami')args=parser.parse_args()
print(args)
#przetworzenieargumentówokreślonychwwywołaniugetopt#dalszeargumentydostępnesąw$1,$2,itdpozakończeniupętli#:->poprzedzającaopcjawymagaargumentu#::->poprzedzającaopcjamożemiećargument#uwagaoilewymaganeargumentymogąbyćrozdzielaneodopcjispacją#otyleopcjonalnenie(krótkienależypodawaćzarazpoopcji,#długierozdzielając=)evalset--"`getopt-oxy:z::-lopcja-x,opcja-y:,opcja-z::--"$@"`"whiletrue;docase$1in-x|--opcja-x)echo"X";shift1;;-y|--opcja-y)echo"Y,argument\`$2'";shift2;;
###PrzykładPython
###PrzykładBash
-z|--opcja-z)echo"Z,argument\`$2'";shift2;;#tuataj$2możebyćpusty(gdyniepodano),alejestzdefiniowany--)shift;break;;esacdone
#innąkomendąmogącąsłużyćprzetwarzaniuopcjiskryptujestgetopts
<?php/*możliwejestużywaniephpwtrybiecommand-linejednakzewzględunaspecyfikęipodstawowezastosowaniategojęzykajesttoprzypadekdośćegzotyczny
dlategoteżzamiastobsługiopcjiprzekazywanychzliniipoleceńwprzypadkuskryptówphpwiększysensmapokazanieobsługiopcjiprzekazywanychwżądaniuHTTP*/
//wysłanieciasteczka//musibyćprzedwysłaniem//jakiejkolwiektreści$val=time();$val="tmp$val";setcookie("Ciasteczko",$val);
echo'<pre>';echo"wysłałemciasteczko:$val\n";
//tablicazawierajacazmienne//przekazanewadresieURLecho'$_GET:';print_r($_GET);
//tablicazawierajacazmienne//przekazanewitreściżądaniaecho'$_POST:';print_r($_POST);
//tablicazawierajacazmienne//przekazanewciasteczkachecho'$_COOKIE:';print_r($_COOKIE);
echo'</pre>';
?>
ProcesyiwątkiRozgałęzienieprocesu-fork()
Abywsystemiemógłdziałaćwięcejniż1proceskoniecznajestmożliwośćutworzenianowegoprocesu(potomka)zpoziomuprocesuaktualniedziałającego(rodzica).Możliwesądwapodejścia:
utworzenie"czystego"procesuuruchamiającegopodanykodprogramuzpodanymiargumentami(spawn)utworzenie kopii aktualnego procesu, która zacznie wykonywać się niezależnie od momenturozgałęzienia(fork)
W przypadku zastosowania fork proces potomny otrzymuje kopię pamięci rodzica (ma dostęp dowszystkich jego zmiennych oraz zasobów uzyskanych przed fork(); dalsze operacje na zmiennych sąniezależne).Poutworzeniukopiprocesumożna(alenietrzeba)zastąpićwykonywanywnimprograminnympoprzezfunkcjezrodzinyexec.Cechytepowodujążemechanizmforkjestbardziejelastycznyodspawn.
#include<stdlib.h>#include<unistd.h>#include<sys/wait.h>
///PrzykładPHP
///PrzykładC++
#include<fcntl.h>#include<stdio.h>
voidgetInput(intfd,intpid);
intmain(){ //najprostsząmetodąuruchomieniainnegoprogramujestfunkcjasystem intretcode=system("ls-l"); printf("Programuruchomionyprzezsystem()zwróciłkodpowrotu:%d\n", WEXITSTATUS(retcode) ); //jeżelichcemyodebraćstandardowewyjście //(albozapisaćstandardowewejście)możnaskorzystaćzpopen FILE*p=popen("uname-a","r"); puts("Proceswypisałnaswójstdout:"); charbuf[256]; size_ts; while((s=fread(buf,sizeof(char),sizeof(buf),p))){ fwrite(buf,sizeof(char),s,stdout); } //tworzymyłączanienazwane-rury... inttoSys[2]; if(pipe(toSys)==-1){ perror("Errorinpipe(toSys)"); //perrorwypisujepodanykomunikatnastderrdodającdoniegoopis //błęduokreślonegoprzezerrno,możnateżpobraćidentyfikatorbłędu //lubjegoopis-szczegóływman3errno return1; } //toSys[0]-odbiórzrury //toSys[1]-wysyłanieprzezrurę intfromSys[2]; if(pipe(fromSys)==-1){ perror("Errorinpipe(fromSys)"); return1; } //rozgałęziamyproces intpid; switch(pid=fork()){ case-1:{ //funkcjazwróciła-1cooznaczabłąd perror("Errorinfork"); return1; } case0:{ //funkcjazwróciłazerocooznaczażejesteśmywprocesiepotomnym //podmieniamystdinistdoutpotomkanaodpowiednie //koniecłącznienazwanych dup2(toSys[0],0); dup2(fromSys[1],1); //zamykamykońcełącznienazwanych(tektóreużywamysąjużdostępne //jakostdin,stdout,innychniepotrzebujemy) close(toSys[0]);close(toSys[1]); close(fromSys[0]);close(fromSys[1]); //zastępujemysięinnymprocesem(wtymwypadkugerpdopasowującynapisy //zawierająceznakzzakresuA-C)-wtakisposóbwjakirobitosystem() execl("/bin/sh","sh","-c","grep--line-buffered'[A-C]'",(char*)0); //oczywiściezamiastwywoływaniainnegoprogramumożnatutajużyćwłasnego //kodupracującegorównoleglezprogramemgłównym } default:{ //funkcjazwróciłacośinnegood0i-1oznaczatożejesteśmywprocesie //macierzystymiotrzymaliśmypidnaszegodziecka... //zamykamyniepotrzebnekoncerur close(toSys[0]);close(fromSys[1]);
//rurymożemyobsługiwaćjakpliki //iwtenspsóbobsługiwanajestkońcówkadozapisu FILE*pout=fdopen(toSys[1],"w"); fprintf(pout,"Alamakota\n"); fprintf(pout,"Kotmacoś\n"); fflush(pout); //możnateżjeobsługiwaćposługującsiębezpośredniodeskryptorem //itakobsługiwanajestruradoczytania //rurędoczytaniaustawiamywtrybienieblokującym fcntl(fromSys[0],F_SETFL,fcntl(fromSys[0],F_GETFL,0)|O_NONBLOCK); //czytaniezostałowyniesionejestdoosobnejfunkcjigetInput() //celemłatwiejszegojegopowtarzania getInput(fromSys[0],pid); //potomekmożepotrzebowaćtrochęczasunaprzetworzeniedanych sleep(1); getInput(fromSys[0],pid); //zamykamynaszkoniecrurydopisania //pozwolitopotomkowiczekającemunainputzakończyćsię fclose(pout); //sprawdzamyczyjestjeszczejakiśinput //(koniecznenp.gdygrepbez--line-buffered) sleep(1); getInput(fromSys[0],pid); //zamykamyrurędoczytania close(fromSys[0]); //czekamynazakończeniepotomka intppid=wait(&retcode); printf("potomekoPID=%dzakończyłsięzkodem%d\n", ppid,WEXITSTATUS(retcode) ); } }}
voidgetInput(intfd,intpid){ char*buf[256]; intlen,gLen=0;
while((len=read(fd,buf,255))>0){ buf[len]=0; gLen+=len; printf("Odebranoodpotomka%d:\n>>>>>\n%s\n<<<<<\n",pid,buf); } printf("Łącznieodebrano:%d\n",gLen);}
print("""##podstawysubprocess#""")importsubprocess
#Pythonpozwalanabezpośredniestosowaniefunkcjitakichjaksystem(),#popen(),fork(),execl()itdpoprzezmodułos...jednakzapewniateż#wygodny,zunifikowanysposóburuchamianiainnychprogramów/poleceń#powłokipoprzezmodułsubprocessorazrozgałęzianiawłasnegoprocesu#poprzezmodułmultiprocessing
#napisktóryzostaniepodanynastandardowewejścieinStr="Alamakota\nKotmapsa\n..."
#uruchamiamysubprocesszgrep'emres=subprocess.run(["grep","-v","A"],input=inStr.encode(),stdout=subprocess.PIPE)print("Kodpowrotuto:"+str(res.returncode))print("Standardowewyjściezkomendyto:"+res.stdout.decode())#wartozwrócićuwagęnakodowanieidekodowanienapisów#(przekazywanych/odbieranychprzezstdin/stdout)do/zutf-8
###PrzykładPython
#jeżelichcemykorzystaćnp.zznakówuogólniającychpowłokilubpodać#komendęjakopojedynczynapis(anielistęargumentów)tomożnaużyć#opcjishell=True:subprocess.run(["ls-ld/etc/pa*"],shell=True)#jeżelipotrzebujemytylkorozbicianapisunalistęargumentówmożna#użyćshlex.split()
#run()pozwalatakże(oboksubprocess.PIPE)naprzekazywanie#istniejącychdeskryptorów(lubsubprocess.DEVNULL,coignorujewyjście)#wramachstdin,stdout,stderr
#modułsubprocessoferujetakżefunkcjęPopen()dającąwiększąkontrolę#naduruchamianiemkomendy
print("""##podstawymultiprocessing#""")importmultiprocessing,os,timedeffun1(txt,st,cnt): for_inrange(cnt): print("Proces",os.getpid(),"zst=",st,"iargumentem:",txt) time.sleep(st)
deffun2(c,e): #obsługaruryizdarzenia c.send("Uwolnićmrożonetruskawki") time.sleep(1.3) c.send([12,13,{"ab":11,"cd":"xx"}]) c.close() e.clear()
if__name__=='__main__': #przygotowaniepotomków p1=multiprocessing.Process(target=fun1,args=('Alamapsa',1.5,4,)) p2=multiprocessing.Process(target=fun1,args=('piesmakota',1,3,)) print("mójpidto",os.getpid(),"...uruchamiamprocesy") #uruchomieniepotomków p1.start() p2.start() #czekanienazakończeniep2 p2.join() print("p2sięzakończył") #wymuszeniezakończeniap1jeżelinadalżyje ifp1.is_alive(): print("p1żyje") p1.terminate() p1.join() print("p1sięzakończył") #ruraievent #Pipe()tworzynamparęobiektówmultiprocessing.Connection #jednegobędziemyużywaćwprocesiegłównym,adrugiegowpotomnym pConn,cConn=multiprocessing.Pipe() #tworzymyobiekttypuEvent...jesttoprostysygnalizator #zflagąbinarnązapewniającyatomowośćwykonywanychoperacji evt=multiprocessing.Event() evt.set() #tworzymyiuruchamiamykolejnypodproces p1=multiprocessing.Process(target=fun2,args=(cConn,evt,)) p1.start() #odbieramydanezpołączeniadopókieventjestustawiony try: whileevt.is_set(): ifpConn.poll(0.1): print("otrzymałem:",pConn.recv()) exceptEOFError:pass
print("""##poolibarierawmultiprocessing#""")importmultiprocessing,queue,os,timefromthreadingimportBrokenBarrierError
deffun5Init(b): globalbariera bariera=b
deffun5(arg): foriinrange(arg['n']): print("Wątek",arg['n'],"iter=",i) time.sleep(arg['ts']) try: print("Wątek",arg['n'],"czekamnainnych") ifbariera.wait()==0: print("wątkizsynchronizowane") #więcejnieużywajtejbariery: bariera.abort() exceptBrokenBarrierError: print("czekanieanulowane") returnarg['n']+arg['ts']
if__name__=='__main__': #tworzymybarieręiwarunek b=multiprocessing.Barrier(3) #tworzymypool'a...wramachinicjalizacji #przekazujemybarieręiwarunek pool=multiprocessing.Pool( processes=3,initializer=fun5Init,initargs=(b,) ) #tworzymylistęargumentówdlafunkcji #uruchamianejwprocesachpotomuych args=[ {'n':3,'ts':0.44}, {'n':13,'ts':0.17}, {'n':2,'ts':0.33}, {'n':7,'ts':0.69}, {'n':4,'ts':0.49}, ] #tworzymypulę3procesówpotomnychiuruchamiamywnichwskazaną #funkcjęzkolejnymizbioramiargumentówzpodanejlisty #uwaga:funkcjawywoływanaprzezmapwrazzewentualnymizmiennymi #globalnymimusibyćzdefiniowanaprzedwywołaniemPool() results=pool.map(fun5,args) pool.close() pool.join()
Komunikacjamiędzyprocesowa
W systemie wieloprocesowym konieczne jest zapewnienie mechanizmów komunikacji pomiędzyprocesami,zwłaszczajeżeligrupaprocesówmarealizowaćwspólnezadanie.
Jednym z takich mechanizmów (można powiedzieć że nawet podstawowym) jest pokazane wcześniejłączenienazwane (pipe) pozwalającenaprzekazywanie strumieniadanychod jednegodo kolejnegoprocesu. Podobnie działa łącze nazwane z tym że nie jest uzyskiwane w wyniku funkcji pipe() aotwarcia specjalnego pliku (utworzonego mkfifo()) przez dwa procesy (jeden do czytania drugi dopisania).
Istnieją także inne mechanizmy komunikacji (zarówno prostsze od łącz jak i bardziej od nichzaawansowane),zktórychczęśćzostałaopisanaponiżej.
Sygnały
Najprostszą formą komunikacji międzyprocesowej są sygnały. Podstawowe sygnały niosą tylko i
wyłącznieinformacjęoswoimnumerze(istniejątakżesygnałyrozszerzone,tzw.czasurzeczywistego,któreniosątakżedodatkowąwartośćliczbową).Sygnałmożezostaćwysłanyprzezdowolnyprocesdodowolnego innego procesu, przy czym warunkiem jego dostarczenia są odpowiednie uprawnienia(procesu użytkowników mogą wysyłać tylko do procesów tego samego użytkownika, root możewysyłaćdowszystkich).
Każdy sygnał ma zdefiniowane domyślne zachowanie procesu po jego otrzymaniu. Wiele sygnałówzwiązanychjestzstandardowymioperacjami(np.wciśnięcieCtrl+C,Ctrl+Z,Ctrl+/,wykonaniekill$PID) i ma odpowiednie do tego zachowania domyślne. Proces może zablokować lub zdefiniowaćwłasnąobsługęwiększości(aleniewszystkich)sygnałów.
#include<stdio.h>#include<signal.h>#include<fcntl.h>#include<time.h>#include<unistd.h>#include<errno.h>
//funkcjeobsługisygnałuvoidobslugaSygnalu(intsig){ printf("Otrzymałemsygnałnumer:%i\n",sig);}
voidakcjaSygnalu(intsig,siginfo_t*info,void*context){ printf("Otrzymałemsygnałnumer:%izkodem%diwartością%dodpid=%d\n", sig,info->si_code,info->si_value.sival_int,info->si_pid); //si_codeokreślapowódwysłaniasygnału}
intmain(){ intsig,pid; pid=getpid(); printf("MójPID=%d\n",pid); //sygnałysąasynchronicznymmechanizmemjednokierunkowejkomunikacji //systemyPOSIXoweoferujądwarodzajesygnałów-standardoweiczasurzeczywistego //sygnałyczasurzeczywistego(wodróżnieniuodstandardowychprzekazującychjedynie //numersygnału)zawierajątakżekodiwartośćorazsąpriorytetyzowane //(niższynumer=>wyższypriorytet=>dostarczanywpierwszejkolejności) //dozdefiniowaniaobsługisygnałustandardowego(dojegoprzechwycenia)służyfunkcja: signal(SIGINT,&obslugaSygnalu);//pojawiasięm.in.wefekcieCtrl+C signal(SIGTSTP,&obslugaSygnalu);//pojawiasięm.in.wefekcieCtrl+Z //oczywiściemożnadefiniowaćróżnefunkcjedlaróżnychsygnałów //zamiastwskaźnikadofunkcjimożemypodaćtakżeSIG_IGNalboSIG_DFL //cooznaczaodpowiednioignorowanietegosygnałulubjegodomyślnąobsługę //możliwejestteżmaskowaniesygnałów sigset_tsigSet; //inicjujemymaskęsygnałównapustą,napełnąbyłobysigfillset() if(sigemptyset(&sigSet)) perror("Errorinsigemptyset()"); //dodajemysygnałdomaski //możnatakżeusuwać-sigdelset()isprawdzaćczyjestobecny-sigismember() //zamaskowanySIGTERMjestdomyślnymsygnałemwysyłanymprzezkill if(sigaddset(&sigSet,SIGTERM)) perror("Errorinsigaddset()"); //ustawiamymaskęsygnałównaprzygotowaną if(sigprocmask(SIG_SETMASK,&sigSet,NULL)) perror("Errorinsigprocmask()"); //sygnałynieobsługiwaneinieblokowaneprzezprocesobsługiwanesąwsposóbdomyślny //naogółprowadzącdozakończeniaprocesu...sygnałówSIGKILL(wysyłanegoprzezkill-9) //orazSIGSTOPniemożnaprzechwycićanizamaskować //dozdefiniowaniaobsługisygnałuczasurzeczywistegosłużyfunkcjasigactionwrazzstrukturą //sigactionopisującąobsługę(możnatakdefiniowaćtakżeobsługęstandardowychsygnałów): structsigactionrtSigAct; //funkcjaobsługi(możatakżepodaćSIG_IGNalboSIG_DFL)
///PrzykładC++
rtSigAct.sa_sigaction=&akcjaSygnalu; //flagi...SA_SIGINFOoznaczafunkcjęprzyjmującą3argumentyanie1jakwsignal() rtSigAct.sa_flags=SA_SIGINFO; //maskasygnałówblokowanychwtrakcieobsługisygnału...blokujemywszystkocosięda sigfillset(&rtSigAct.sa_mask); //ustawienieobsługi sigaction(SIGRTMIN,&rtSigAct,NULL); //wysłaniesygnałuczasurzeczywistego //(funkcjapozwalateżnawysyłaniestandardowychsygnałów) sigqueue(pid,SIGRTMIN,(constunionsigval)123); //oczekiwanienasygnał: puts("Czekamnadowolnysygnał"); pause(); //dodajemySIGINTdozbioru if(sigaddset(&sigSet,SIGINT)) perror("Errorinsigaddset()"); puts("Czekamnasygnałzpodanejmaski"); puts("innebędąobsługiwanealefunkcjaniezakończysię..."); printf("abykontynuowaćCtrl+Clubkill%d\n",pid); if(sigwait(&sigSet,&sig)) perror("Errorinsigwait()"); printf("Czekaniezakończonepootrzymaniusygnału:%d\n",sig); puts("Śpięprzez10s...dowolnysygnałprzerwie"); sleep(10);//jestteżusleep()dlamikrosekund puts("Czekamprzez10.5snasygnałzpodanejmaski"); siginfo_tsigInfo; structtimespectimeOut; timeOut.tv_sec=10; timeOut.tv_nsec=500000000; sig=sigtimedwait(&sigSet,&sigInfo,&timeOut); if(sig<0){ if(errno==EINTR) puts("otrzymałeminnysygnał"); elseif(errno==EINVAL) puts("timeout"); else perror("Errorinsigtimedwait()"); }else{ printf("Czekaniezakończonepootrzymaniusygnału%dodpid=%d\n", sig,sigInfo.si_pid ); } //jestteżsigwaitinfodziałającajaksigtimedwaitalebeztimeout'u}
importos,signal
pid=os.getpid()print("MójPID:",pid);
#obsługasygnałudefobslugaSygnalu(s,f): print("Otrzymałemsygnałnumer:",s)#SIGINT-pojawiasięm.in.wefekcieCtrl+Csignal.signal(signal.SIGINT,obslugaSygnalu)
#SIGTSTP-pojawiasięm.in.wefekcieCtrl+Zsignal.signal(signal.SIGTSTP,obslugaSygnalu)
print("Czekamnadowolnysygnał")signal.pause()
print("Czekamnasygnałzpodanegozbioru")#wodróżnieniuodCinnebędąobsługiwanedopieropootrzymaniu#sygnałuzezbioru(zostanązakolejkowane)sig=signal.sigwait([signal.SIGTERM,signal.SIGINT])print("Czekaniezakończonepootrzymaniusygnału:",sig)
###PrzykładPython
print("Czekamprzez10.5snasygnałzpodanegozbioru")#wodróżnieniuodCinnysygnałjestobsługiwany,#alenieprzerywaczekaniasig=signal.sigtimedwait([signal.SIGTERM,signal.SIGINT],10.5)ifsig==None: print("timeout");else: print("Czekaniezakończonepootrzymaniusygnału:", sig.si_signo,"odpid:",sig.si_pid )
Kolejkikomunikatów
Wprzypadkugdygrupaprocesówmazesobąwspółpracowaćpotrzebnesąbardziejzaawansowane(od sygnałów) mechanizmy komunikacji - pozwalające na przekazywanie jakiś danych międzyprocesami.Jednymztakichmechanizmówsąkolejkiwiadomości.Wpewnymstopniusąonepodobnedo omówionych wcześniej łącz (pipe-ów), jednak w odróżnieniu od nich zamiast jednolitegostrumienia danych pomiędzy dwoma procesami (producentem i konsumentem) służą doprzekazywaniawiadomościpomiędzygrupąproducentówigrupąkonsumentów.
//przykompilacjikoniecznejestdodanie://-lrt-lpthread
#include<stdio.h>#include<mqueue.h>#include<errno.h>#include<time.h>#include<string.h>#include<unistd.h>
voidgetMsg(unionsigvalsv){ puts("kolejkaniejestjużpusta"); //tumógłbybyćrealizowanyodbiórwiadomościzkolejki}
intmain(intargc,char*argv[]){ if(argc!=3){ fprintf(stderr,"%s/nazwa1|2\n",argv[0]); return1; } charrunType=argv[2][0]; //kolejkiwiadomosciPOSIX(wiecejman7mq_overview) //kolejkamożemiećzarównowieluproducentówjakiodbiorców //razodebranawiadomośćznikazkolejki //otwarciekolejki structmq_attratrybuty; atrybuty.mq_maxmsg=3;//pojemnośćkolejki-3wiadomości atrybuty.mq_msgsize=20;//po20bajtówkażda mqd_tmsgQ=mq_open( argv[1],//nazwazasobu O_RDWR|(runType=='1'?O_CREAT|O_EXCL:0),//flagi 0770,//prawadostępu &atrybuty ); if(msgQ==(mqd_t)-1){ perror("Errorinmq_open()"); return-1; } charbuf[20]; unsignedpriorytet; structtimespectimeout; clock_gettime(CLOCK_REALTIME,&timeout); timeout.tv_sec+=2; //odbieramywiadomośćztimeoutem... //wiadomosciodbieranesąwkolejnościpriorytetów,anastępniewysłania ssize_tsize=mq_timedreceive(msgQ,buf,20,&priorytet,&timeout); //mq_receive()-wersjabeztimeoutu //mamytakżemożliwośćodbiorubeztimeoutubądźzażądaniapowiadomienia //owpisaniupierwszejwiadomościdoniepustejkolejki-mq_notify() if(size>0){
///PrzykładC++
printf("odebrałem%dbajtówzpriotytetem%d:%s\n",size,priorytet,buf); }else{ if(errno==ETIMEDOUT) puts("timeout"); else perror("Errorinmq_timedreceive()"); } //ustawieniepowiadamianiaopojawieniusięwiadomościwniepustejkolejce structsigeventsev; sev.sigev_notify=SIGEV_THREAD; sev.sigev_notify_function=getMsg; sev.sigev_notify_attributes=NULL; if(mq_notify(msgQ,&sev)==-1){ perror("Errorinmq_notify()"); } //wysyłamywiadomośćdokolejki //funkcjatazawiesiprocesgdyniemamiejscawkolejcektóraniejest //otwartazO_NONBLOCKnaczasokreślonyprzeztimeout //mq_send()-wersjabeztimeout'u snprintf(buf,20,"infoAod:%d",getpid()); clock_gettime(CLOCK_REALTIME,&timeout); timeout.tv_sec+=2; if(mq_timedsend(msgQ,buf,strlen(buf),9,&timeout)) perror("Errorinmq_timedsend()"); printf("Wysłano:%s\n",buf); if(runType=='1'){ snprintf(buf,20,"infoBod:%d",getpid()); if(mq_send(msgQ,buf,strlen(buf),9)) perror("Errorinmq_send()"); printf("Wysłano:%s\n",buf); sleep(20); mq_unlink(argv[1]); //wprzypadkugdybyprogramzakończyłsiębezwykonaniamq_unlink() //(np.nasutekkill-9)koniecznejestręczneusunięcieplikówz/dev/mqueue }}
print("""##kolejkiwmultiprocessing#""")importmultiprocessing,multiprocessing.managers,queue,os,time
deffun3(q): #obsługakolejki...zakończeniemożnatakżerealizować #np.woparciuodaneotrzymanewkolejce whileTrue: ifnotq.empty(): el=q.get(block=False) #możnatakżeuruchamiaćblokującyget() #ztimeoutemlubbez... ifel[1]==None: break; else: print("potomekotrzymał",el) time.sleep(0.77)
if__name__=='__main__': #tworzymykolejkę #modułmultiprocessingzawieraswojeimplementacjekolejkiFIFO #(Queue,SimpleQueueiJoinableQueue),którychmożnabezpiecznie #używaćpomiędzyprocesami: #q=multiprocessing.Queue() # #chcemyjednakużyćkolejkipriorytetowejzmodułuqueue #(oferujetakżekolejkiFIFO(Queue)iLIFO(LifoQueue)) #abymóczniejpoprawniekorzystaćwmultiprocessing #musimyużyćjejpoprzezSyncManager'a: classManager(multiprocessing.managers.SyncManager): pass Manager.register("PrioQueue",queue.PriorityQueue)
###PrzykładPython
m=Manager() m.start() q=m.PrioQueue() #dodajemyelementydokolejki q.put((100,"delfinmapsa;-)")) q.put((70,[13,17])) q.put((200,[15,{"ab":11,"cd":"xx"}])) #tworzymyiuruchamiamykolejnypodproces p1=multiprocessing.Process(target=fun3,args=(q,)) p1.start() #wkładaniedanychdokolejki time.sleep(0.404) print("dodajenowewiadomościdokolejki...") q.put((13,"ABC...icodalej")) q.put((180,"blablabla...")) #informacjadlapotomkaozakończeniuobsługikolejki print("czekamnaopróżnieniekolejki...") whileq.qsize()>0: time.sleep(0.333) #kończenie q.put((999,None)) p1.join() m.shutdown()
Pamięćwspółdzielona
Kolejnym mechanizmem komunikacji międzyprocesowej jest współdzielenie części pamięci, którepozwala na operowanie na tych samych danych przez grupę procesów (a nie tylko przekazywaniedanychodprocesudoprocesu jakwyżej opisanemetody).Przypomocy tegomechanizmumożliwejeststworzeniewłasnejimplementacjiłącz(pipe-ów)czyteżkolejekwiadomości.
W przypadku korzystania z wspólnej pamięci konieczne jest mechanizm zabezpieczenia przedmożliwością równoczesnej modyfikacji tego samego fragmentu przez kilka procesów. Pierwszymnasuwającymsięrozwiązaniemjestzastosowaniezmiennejwspółdzielonejinformującejotymżektośblokujedanyfragmentcelemjegomodyfikacjinp.:
intblokada=false;zrownoleglijKod();if(!blokada){ blokada=true; sekcjaKrytyczna(); blokada=false;}
Niestetytakierozwiązanieniegwarantujeskutecznościblokady,gdyż:1. może się zdarzyć że na dwóch rdzeniach kod jest wykonywany dokładnie równolegle i dwa
procesysprawdząwartośćzmiennej"blokada"wtejsamejchwiliadopieropotemzmieniąjejwartość(wefekcieczegoobawejdądosekcjikrytycznejwejdąobaprocesy)
2. nastąpi przełączenie procesów wykonywanych na jednym rdzeniu pomiędzy sprawdzeniemwarunku a modyfikacją zmiennej, co pozwoli wejść drugiemu procesowi do sekcji krytycznejgdypierwszyjużsprawdziłwarunekwejścia
Dlatego też korzysta się z mechanizmów systemowych (semaforów, lock'ów, etc) które zapewniająatomowość(niepodzielność)operacjisprawdzeniawartościzmiennejijejmodyfikacji.
//przykompilacjikoniecznejestdodanie://-lrt-lpthread
#include<stdio.h>#include<semaphore.h>#include<fcntl.h>#include<unistd.h>#include<sys/mman.h>#include<errno.h>#include<time.h>
#defineBUF_SIZE128
///PrzykładC++
intmain(intargc,char*argv[]){ if(argc!=3){ fprintf(stderr,"%snazwa1|2\n",argv[0]); return1; } intretcode=1; charrunType=argv[2][0]; //pamięćdzielonaprzezshmimmap(więcej`man7shm_overview`) //możnabytakżeprzezmmapizwykłyplik //1)utworzeniezasobu(pliku)SHM //jeżelirunType=='1'izasóbistniejetowywołaniezakończysiębłędem //jajeżelinieistniejezostanieutworzony intshmFd=shm_open( argv[1],//nazwazasobu O_RDWR|(runType=='1'?O_CREAT|O_EXCL:0),//flagi 0770//prawadostępu ); if(shmFd<0){ perror("Errorinshm_open()"); return1; } //2)ustaleniewielkości if(ftruncate(shmFd,BUF_SIZE)){ perror("Errorinftruncate()"); gotoEND_1; } //3)zamapowaniezasobuSHMwpamięci void*addr=mmap(0,BUF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,shmFd,0); if(addr==MAP_FAILED){ perror("Errorinmmap()"); gotoEND_1; } //semaforyPOSIX(więcej`man7sem_overview`) //1)utworzeniesemafora //jeżelirunType=='1'isemaforistniejetowywołaniezakończysiębłędem sem_t*sem=sem_open( argv[1],//nazwazasobu O_RDWR|O_CREAT|(runType=='1'?O_EXCL:0),//flagi 0770,//prawadostępu 1//wartośćsemafora ); if(sem==SEM_FAILED){ perror("sem_open"); gotoEND_1; } int*c=(int*)addr; if(runType=='1'){ *c=0; } //próbawejściawkodzabezpieczonysemaforem if(sem_trywait(sem)){ if(errno==EAGAIN) puts("semaforniewpuszcza...trzebaspróbowaćpóźniej"); else perror("Errorinsem_trywait()"); }else{ //semaforzostałopuszczony...jesteśmywsekcjikrytycznej *c=*c+0x01; printf("c=0x%x\n",*c); sleep(3);//śpimy,tonieładniespaćwsekcjikrytycznej,aletotylkodemo... //podniesieniesemafora if(sem_post(sem)) perror("Errorinsem_post()"); } sleep(5);
//czekanienamożliwośćwejściawkodzabezpieczonysemaforemztimeout'em structtimespectimeout; clock_gettime(CLOCK_REALTIME,&timeout); timeout.tv_sec+=10; if(sem_timedwait(sem,&timeout)){ if(errno==ETIMEDOUT) puts("timeout...trzebaspróbowaćpóźniej"); else perror("Errorinsem_timedwait()"); }else{ //semaforzostałopuszczony...jesteśmywsekcjikrytycznej *c=*c+0x0100; printf("c=0x%x\n",*c); sleep(5);//śpimy,tonieładniespaćwsekcjikrytycznej,aletotylkodemo... //podniesieniesemafora if(sem_post(sem)) perror("Errorinsem_post()"); } sleep(3); //czekamydoskutkunamożliwośćwejściawsekcjękrytyczną if(sem_wait(sem)){ perror("Errorinsem_timedwait()"); }else{ //semaforzostałopuszczony...jesteśmywsekcjikrytycznej *c=*c+0x010000; printf("c=0x%x\n",*c); sleep(5);//śpimy,tonieładniespaćwsekcjikrytycznej,aletotylkodemo... //podniesieniesemafora if(sem_post(sem)) perror("Errorinsem_post()"); } retcode=0; //oilewwiększościprzypadkówzwalnianieizamykaniezasobówwmomencie //kończeniaprogramuniemaznaczenia(zasobysąautomatycznieodbieraneprzez //system-pamięćbędziezwolniona,pliki,gniazdasieciowepozamykane,itd) //towprzypadkuzasobówwspółdzielonychmożemiećistotneznaczenie //np.jeżelinieusuniemyzasobuSHModanejnazwieniebędziegomożnapóźniej //otworzyćgdyużywamyflagO_CREAT|O_EXCL // //dlategowpowyższymkodziewobsłudzebłędówużywamygotodosekcjikończącej:END_2: if(runType=='1'){ //usunięciesemafora(staniesięniedostępnytakżedlainnychprocesów) sem_unlink(argv[1]); }END_1: //odmapowaniezasobuzpamięci munmap(addr,BUF_SIZE); //zamknięciezasobuSHM close(shmFd); if(runType=='1'){ //usunięciezasobuSHM(staniesięniedostępnytakżedlainnychprocesów) shm_unlink(argv[1]); } //wprzypadkugdybyjednakprogramzakończyłsiębezwykonywaniategokodu //(np.nasutekkill-9)koniecznejestręczneusunięcieplikówz/dev/shm}
print("""##współdzieleniedanychwmultiprocessing#""")importmultiprocessing,queue,os,time
deffun4(lock,l,c): #obsługazmiennejwarunkowej
###PrzykładPython
foriinrange(6): #blokujemydostępdolisty c.acquire() #modyfikujemyzmiennąnaktórejmamywarunek l[0]=i #powiadamiamywszystkichotym c.notify_all() #zwalniamydostępdolisty c.release() time.sleep(0.13) #obsługalockailisty whileTrue: iflock.acquire(timeout=0.5): #jeżeliudałosięzałożyćlock'a... l[1]+=1 print("podprocess:",l) time.sleep(0.77) #zdjęcielock'a lock.release() time.sleep(0.33) else: print("podprocess:can'tlock")
if__name__=='__main__': #tworzymylocka'a,czyliblokadęwejściadosekcjikrytycznej #(zmieniającejdanewspółdzielone) lock=multiprocessing.Lock() #opróczzwykłychLock'ówPythonoferujetakże: #*RLock-Lockwktórymwątekzakładającyblokadęmożejązakładać #kolejnerazybezjejuprzedniegozwalniania,tznsekwencja: #l=RLock(); #l.acquire();l.acquire(); #cos(); #l.release();l.release(); #jestpoprawna(przyzwykłymLock'uzatrzymasięnadrugim #l.acquire()) #*Semaphore-Lockzlicznikiemdozwolonychwejśćdosekcji #krytycznejnp.l=Semaphore(value=3)pozwolina3wywołania #l.acquire()(bezl.release()) #tworzymywspółdzielonąlistę...namenagerze m=multiprocessing.Manager() l=m.list([0,1,2,3]) #tworzymyzmiennąwarunkowąużywającąlock'alock c=multiprocessing.Condition(lock) #tworzymyiuruchamiamykolejnypodproces p1=multiprocessing.Process(target=fun4,args=(lock,l,c,)) p1.start()
print("czekamynaspełnieniewarunku..."); c.acquire() whilel[0]<4: print("czekamy...l[0]=",l[0]) c.wait() c.release() print("warunekspełniony...l[0]=",l[0]); time.sleep(0.17) #obsługalisty foriinrange(3): #założenielock'a print("process:czekamnalock...") lock.acquire() #dodanieelementudolistyiwypisanie l.append(13+i) print("process:",l) time.sleep(0.69) #zdjęcielock'a lock.release() time.sleep(1.0) #zakończenie
p1.terminate() p1.join() m.shutdown()
Wątki
Opróczmożliwościrozgałęzieniaprocesu(utworzeniapotomka)zużyciemnp.fork()możliwejesttakżetworzenie wątków (zwanych tez lekkimi procesami) w ramach procesu. Podstawowa różnica międzyprocesemawątkiempoleganatymiżwszystkiewątki(wramachdanegoprocesu)współdzielącałośćpamięci (przestrzeni adresowej), podczas gdy każdy z procesów posiada niezależną pamięć i conajwyżej jakiś współdzielony z innymi fragment. Każdy z wątków posiada natomiast niezależny stos(umieszczony we wspólnej przestrzeni adresowej), który jest używany m.in. do przechowywaniazmiennychlokalnych(wtymargumentówfunkcji).Jednakzewzględunaumieszczenietychdanychwwspólnej przestrzeni adresowej są one także dostępne dla innych wątków (poprzez wskaźnik lubreferencję).
//przykompilacjikoniecznejestdodanie://-lrt-lpthread
#include<pthread.h>#include<unistd.h>#include<stdio.h>#include<errno.h>#include<string.h>
structwatekInfo{ pthread_mutex_t*mut; pthread_cond_t*cond; constchar*napis; intlicznik;};
voidwypisz1(structwatekInfo*wi){ inti,l=-99,ret; for(i=0;i<4;i++){ //próbujemyzablokowaćwejścienatenkawałekkodu //możnaczekaćdoskutkuprzypomocypthread_mutex_lock() if((ret=pthread_mutex_trylock(wi->mut))!=0){ fprintf(stderr, "Wątek:errorinpthread_mutex_trylock():%s\n", strerror(ret) ); }else{ wi->licznik+=2; l=wi->licznik; pthread_mutex_unlock(wi->mut); } printf("Wątek:%s%d\n",wi->napis,l); usleep(600000); } sleep(8); pthread_exit(0);//kończydziałaniewątku}
voidwypisz2(structwatekInfo*wi){ inti; printf("Towatek:%s\n",wi->napis); pthread_mutex_lock(wi->mut); for(wi->licznik=0;wi->licznik<10;wi->licznik++){ printf(".");fflush(stdout); if(wi->licznik==5) pthread_cond_signal(wi->cond); sleep(1); } pthread_mutex_unlock(wi->mut); //zabraniamyprzerwaniawatkuwtrakcieponizszegowypisywania pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); for(i=0;i<10;i++){ printf(".");fflush(stdout); sleep(1);
///PrzykładC++
} printf("\n"); //aterazjużmożebyćanulowywany pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); //aleodteraztylkowwyznaczonychmomentach //nafunkcjachtakichjaksleep,system,... //czytezpthread_testcancel() pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); sleep(50); puts("koniecwypisz2"); pthread_exit(0);}
intmain(){ inti,l,ret; //przygotowaniemutex'a pthread_mutexattr_tmutAttr; pthread_mutexattr_settype(&mutAttr,PTHREAD_MUTEX_ERRORCHECK); //możemyustawić: //*PTHREAD_MUTEX_ERRORCHECKabymechanizmreagowałbłędemna //unlockowaniezalokowanegoprzezinnywątekmutexuitp, //*PTHREAD_MUTEX_RECURSIVEabyblokadanałożonaprzezwątekA //nieobowiazywalawatkuA(umożliwiatokorzystaniez //mutexówwfunkcjachrekurencyjnych) //*PTHREAD_MUTEX_NORMALlubPTHREAD_MUTEX_DEFAULT //flagitemogąsięniecoróżnićwzależnościodstosowanej //bibliotekiiużytych#defineszczegółównależyszukać //wplikachfeatures.hpthread.horazdokumentacjiman pthread_mutexattr_setprotocol(&mutAttr,PTHREAD_PRIO_NONE); //pozanicniezmieniającymPTHREAD_PRIO_NONEmamytakże: //*PTHREAD_PRIO_INHERITzabezpieczającywątkiprzedinwersją //priorytetów(priorytetpowejściudosekcjikrytycznej //jestpodwyższanydonajwyższegozpriorytetówprocesów //czekających //*PTHREAD_PRIO_PROTECTzabezpieczającyrównieżprzed //zakleszczeniemdziękipodnoszeniutegopriorytetupowyżej //najwyższegozpriorytetówprocesówczekających // //dozapobieganiainwersjipriorytetówprzydatnejestteż: //pthread_mutexattr_setprioceiling(); //inicjalizujemymutex(dladomyślnychustawieńmożnapodać //NULLjakodrugiargument) pthread_mutex_tmut; pthread_mutex_init(&mut,&mutAttr); //przygotowaniedanychdlawątku structwatekInfowInfo; wInfo.napis="Alamakota"; wInfo.licznik=10; wInfo.mut=&mut; //tworzymynowywatekuruchomiającwnimfunkcjewypisz1 //iprzekazującjakopierwszyargumenttejfunkcjiwInfo pthread_twatek; if((ret=pthread_create( &watek,0,(void*(*)(void*))wypisz1,(void*)&wInfo) )!=0 ){ fprintf(stderr,"Errorinpthread_create():%s\n", strerror(ret)); return1; } for(i=0;i<7;i++){ pthread_mutex_lock(wInfo.mut); wInfo.licznik-=1; printf("Programgłówny:%d\n",wInfo.licznik); pthread_mutex_unlock(wInfo.mut); sleep(1); }
#ifdef_GNU_SOURCE //pobranieatrybutuwątku //isprawdzenieczyjestwątkiemprocesuczysystemu pthread_attr_tatrybuty; if((ret=pthread_getattr_np(watek,&atrybuty))){ fprintf(stderr,"Errorinpthread_getattr_np():%s\n", strerror(ret)); return1; } if((ret=pthread_attr_getscope(&atrybuty,&i))){ fprintf(stderr,"Errorinpthread_attr_getscope():%s\n", strerror(ret)); return1; } if(i==PTHREAD_SCOPE_PROCESS){ puts("wątekprocesu"); }elseif(i==PTHREAD_SCOPE_SYSTEM){ puts("wąteksystemu...będziewidocznywps-m:"); system("ps-m"); }else{ puts("innywątek:-o"); }#endif //możemyoczekiwaćnazakończeniewątkupoprzezwywołanie //winnymfunkcjipthread_join()umożliwiaonatakże //uzyskaniekoduzjakimzakończyłsięwątek printf("Programgłównyczekanakoniecwątku\n"); if((ret=pthread_join(watek,NULL))){ fprintf(stderr,"Errorinpthread_join():%s\n", strerror(ret)); return1; } printf("Wątekzakończyłsię\n"); //jejwywołaniejestkonieczneabywątekpozakończeniu //byłwcałościusunięty,chybażewątekzostałokreślony //jakotakidoktóregoniemożnasiędołączyćprzezwywołanie //pthread_detach()lubpodanieprzytworzeniuflagi //PTHREAD_CREATE_DETACHED //przygotowujemyzmiennąwarunkową pthread_cond_tcond; pthread_cond_init(&cond,NULL); //aktualizujemystrukturędanychdlawątku wInfo.napis="drugi"; wInfo.licznik=0; wInfo.cond=&cond; //tworzymykolejnywątek if((ret=pthread_create( &watek,0,(void*(*)(void*))wypisz2,(void*)&wInfo) )!=0 ){ fprintf(stderr,"Errorinpthread_create():%s\n", strerror(ret)); return1; } //czekamy... while(wInfo.licznik<5) pthread_cond_wait(wInfo.cond,wInfo.mut); //pthread_cond_waitzwalniataknaprawdęnachwilepodany //doniegomutexapoodebraniupthread_cond_signalna //dozorowanymprzezniegowarunkuponowniegozamyka printf("jesteśmyzawarunkiem");fflush(stdout); sleep(7); printf("zabijamywątek"); //igokończymyzzewnątrz //wzależnościodustawieńwątkuanulowaniewątkudzieje //sięnatychmiastowoalbowjednymzpunktówanulowania //zobaczfunkcjetoustawiającewwypisz2() pthread_cancel(watek);
//wypadateżodebraćjegokodpowrotu pthread_join(watek,NULL); puts("aterazwatekjużnieżyje..."); //usunięciemutex'a pthread_mutex_destroy(wInfo.mut); //usunięciezmiennejwarunkowej pthread_cond_destroy(wInfo.cond);}
//przykompilacjikoniecznejestdodanie://-lboost_system-lboost_thread-lpthread#include<boost/thread/mutex.hpp>#include<boost/thread/thread.hpp>
#include<queue>#include<string>#include<iostream>
std::queue<std::string>kolejka;
classWatek1{ Watek1(constWatek1&);public: intabc; boost::mutexmutex; //boostoferujetakżemutx'apozwalającegonatworzeniekolejnych //blokadprzezwątekktóryutworzyłpierwszą-boost::recursive_mutex Watek1(){} voidoperator()(){ for(inti=0;i<8;i++){ if(mutex.try_lock()){ abc+=1; std::cout<<"wątek,abc="<<abc<<std::endl; mutex.unlock(); }else{ std::cout<<"wątekniedostałemmutex'a..."<<std::endl; } boost::this_thread::sleep(boost::posix_time::millisec(500)); } for(inti=0;i<8;i++){ boost::this_thread::sleep(boost::posix_time::millisec(700)); boost::mutex::scoped_lockscoped_lock(mutex); //powyższylock(namutexietegowątku) //blokujeodterazdokońcabloku if(!kolejka.empty()){ std::cout<<i<<")odebrałemzkolejki\ "<<kolejka.front()<<std::endl; kolejka.pop(); }else{ std::cout<<i<<")kolejkapusta"<<std::endl; } } }};
intmain(){ //przygotowaniedanychwątku Watek1wf1; wf1.abc=56; //uruchomieniewątku... //boost::ref()potrzebneboobiektyklasyWatek1sąniekopiowalne boost::threadwatek1(boost::ref(wf1)); boost::this_thread::sleep(boost::posix_time::millisec(1500)); //manipulacjadanymiwątku wf1.mutex.lock();
///PrzykładC++
wf1.abc=13; boost::this_thread::sleep(boost::posix_time::seconds(1)); wf1.mutex.unlock(); //obsługakolejki wf1.mutex.lock(); kolejka.push("Alamakota"); kolejka.push("KotmaAle"); wf1.mutex.unlock(); std::cout<<"2pierwszeelementysąwkolejce"<<std::endl; boost::this_thread::sleep(boost::posix_time::seconds(4)); wf1.mutex.lock(); kolejka.push("Abecadlo"); kolejka.push("zpiecaspadlo"); wf1.mutex.unlock(); std::cout<<"2kolejneelementysawkolejce"<<std::endl; //czekamynazakończeniewątku watek1.join();}
importthreading,time#UWAGA:#wstandardowejimplementacjiCPythonwdanym#czasietylkojedenwątekmożewykonywać#kodpythonowy##wefekciestosowaniewątkówmasenstylkodla#wątkówczekającychnacoś,aniemasensudla#wątkówmającychwykonywaćsięrównolegle#(naróżnychrdzeniach)##wtakimprzypadkunależyużywaćpełnego#rozgałęzianiaprocesu(modułmultiprocessing)
deffun(txt,st): #używamylokalnejpamięcidladanegowątku daneWatku=threading.local() fordaneWatku.iinrange(4): print(txt,daneWatku.i) time.sleep(st)
#uruchomieniewątkut=threading.Thread(target=fun,args=("AA",2,))t.start();
#możnatakżezdefiniowaćtimerktóry#uruchomiwątekpozadanymczasietim=threading.Timer(3,fun,args=("BB",1.2,))tim.start()
#dlawątkówmożnastosowaćtakżemechanizmy#synchronizacjitakiejakdlamultiprocessing##ponadtowątkimożnatakżeobsługiwaćprzez#interfejsidentycznyzmultiprocessing#poprzezmultiprocessing.dummy
KomunikacjasieciowaWsystemachPOSIXowychkomunikacjasieciowawymagaotwarciatzw.gniazda(socket),przyotwarciuokreślonemuszązostać:
1. rodzina protokołów sieciowych która będzie używana (np. AF_INET dla IPv4 lub AF_INET6 dlaIPv6)
2. typkomunikacjirealizowanejzużyciemgniazda,doistotniejszychtypówzaliczyćnależy:SOCK_STREAM
oznaczającego dwukierunkową niezawodną łączność zapewniającą zachowanie kolejnościdanych(wprzypadkurodzinIPv4iIPv6będzietooznaczałoużycieTCP)
SOCK_DGRAM
###PrzykładPython
oznaczającegobezpołączenioweprzesyłaniewiadomościolimitowanejdługościmaksymalnej(wprzypadkurodzinIPv4iIPv6będzietooznaczałoużycieUDP)
SOCK_RAWoznaczającegoodbieranie iwysyłaniesurowychpakietówwarstwysieciowej (pozwalam.in.naobsługępakietówICMP,swobodnemanipulowanieadresamiwpakietachIP,itd)
Opcjonalniemożezostaćokreślonykonkretnyprotokółjeżeliwramachwskazanejrodzinyiwskazanegotypuwystępujeichkilka.
Otwarcie gniazda skutkuje uzyskaniem deskryptora plikowego, na którym zależnie od parametrówprzekazanychprzytworzeniugniazdamogąbyćwykonywaneoperacjetakiejakwysyłanie/odbieraniedanych,ustawianyadresnasłuchiwania,zestawionepołączenie,itd.
UDP
User Datagram Protocol (UDP) jest protokołem działającym powyżej protokołu IP umożliwiającymprosteprzesyłaniedanychprzezsieć.PakietUDPopróczźródłowegoidocelowegoadresuIP,zawierateżźródłowyidocelowynumerportu.Numerportuokreślausługę/procesdziałającywramachhosta(określanegonumeremIP)którywygenerował/maotrzymaćdanypakiet.
PootwarciugniazdaobsługującegoUDPmożliwejest:wysyłaniedanychpodwskazanyadresIPinumerportuoczekiwanienaodbiórdanychiichodbiórwskazanieadresuinumeruportunaktórymoczekujemynadane(jeżeliniezostaniewykonane,cojesttypowewklientachUDP,będzieużytylosowynumerportu)
W UDP nie ma zestawionego połączenia zatem nie ma silnego rozróżnienia pomiędzy klientem(nawiązującympołączenie)aserwerem(odczekującymnapołączenie/odbierającymje).Jedynaróżnicapolega na tym że: klient (typowo) nie wywołuje funkcji bind() służącej do określenia adresu wraz znumerem portu używanego do odbioru danych, a zamiast tego korzysta z automatycznieprzydzielonegoprzezsystemoperacyjny(losowego)numeruportu.
#include<sys/socket.h>#include<netinet/ip.h>#include<arpa/inet.h>#include<netdb.h>#include<unistd.h>#include<signal.h>#include<sys/wait.h>
#include<stdio.h>#include<stdlib.h>#include<string.h>
#defineBUF1_SIZE256#defineBUF2_SIZE64
constchar*getAddresInfo( structsockaddr_storage*srcAddr,socklen_tsrcAddrLen,char*buf,intbufLen);
intmain(intargc,char*argv[]){ charbuf1[BUF1_SIZE],buf2[BUF2_SIZE]; intret,pid; if(argc!=3&&argc!=4){ fprintf(stderr,"USAGE:%sdstHostdstPort[listenPort]\n",argv[0]); returnEXIT_FAILURE; } //strukturazawierającaadresnaktórywysyłamy //użyciefunkcjigetaddrinfopozwalanazapewnienieobsługizarównoIPv4jakiIPv6, //atakżepodawanieadresówwpostacinumerycznejbądźprzyużyciunazw //alternatywniemożnaręcznieprzygotowywaćstrukturysockaddr_in/sockaddr_in6 //zużyciemnp.htons(),inet_aton(),... structaddrinfo*dstAddrInfo; if((ret=getaddrinfo(argv[1],argv[2],NULL,&dstAddrInfo))!=0){ fprintf(stderr,"Erroringetaddrinfo():%s\n",gai_strerror(ret)); returnEXIT_FAILURE; } //tutajmogliśmyuzyskaćkilkaadresów, //aleoptymistyczniezakładamyżepierwszybędzieOK
///PrzykładC++
//utworzeniegniazdasieciowego...SOCK_DGRAMoznaczaUDP //(nagnieździezSOCK_DGRAMstandardowoniebędziewidaćbłędówICMP //związanychnp.zniedostępnościądocelowegohostalubportu) intsfd=socket(dstAddrInfo->ai_family,SOCK_DGRAM,0); if(sfd<0){ perror("Errorinsocket()"); returnEXIT_FAILURE; } if(argc==4){ //jeżelipodaneopcjonalneargumentutookreślamynajakimporciesłuchamy if(dstAddrInfo->ai_family==AF_INET6){ structsockaddr_in6listenAddr; listenAddr.sin6_family=AF_INET6; listenAddr.sin6_port=htons(atoi(argv[3])); //hosttonetworkshort(porządekbajtów),sąteżdlalonginetworktohost listenAddr.sin6_addr=in6addr_any; //in6addr_anyoznaczażenasłuchujemynakażdymadresieIPdanegohosta //(zamiasttegomożnaokreślićkonkretnyadres) if(bind(sfd,(structsockaddr*)&listenAddr,sizeof(structsockaddr_in6))){ perror("Errorinbind()"); returnEXIT_FAILURE; } }elseif(dstAddrInfo->ai_family==AF_INET){ structsockaddr_inlistenAddr; listenAddr.sin_family=AF_INET; listenAddr.sin_port=htons(atoi(argv[3])); //hosttonetworkshort(porządekbajtów),sąteżdlalonginetworktohost listenAddr.sin_addr.s_addr=INADDR_ANY; //INADDR_ANYoznaczażenasłuchujemynakażdymadresieIPdanegohosta //(zamiasttegomożnaokreślićkonkretnyadres) if(bind(sfd,(structsockaddr*)&listenAddr,sizeof(structsockaddr_in))){ perror("Errorinbind()"); returnEXIT_FAILURE; } } //określenietegowrazzuruchomieniemrecvfrom()pozwalanaoczekiwaniena //pakietyUDPnawskazanymadresieiporcie,gdybywramachobsługiodebranej //wiadomościodsyłanabyłabyodpowiedźdonadawcytobyłbyto"serwerUDP" } //abymócniezależniewysyłaćiodbieraćrozgałęziamyproces //alternatywniemożnaużyćselect()doczekanianadanezsiecilubstandardowegowejścia switch(pid=fork()){ case-1:{ //funkcjazwróciła-1cooznaczabłąd perror("Errorinfork"); return1; } case0:{ //potomekodbieraodpowiedziwnieskończonejpętli //zostaniezakończonysygnałemodrodzica while(1){ //strukturadoktórejzapisanyzostanieadresnadawcy structsockaddr_storagesrcAddr; socklen_tsrcAddrLen=sizeof(structsockaddr_storage); //informacjętąmożnawykorzystaćdoodsyłaniaodpowiedzidonadawcy //odbiórwiadomości...blokujedomomentuotrzymaniawiadomości ret=recvfrom( sfd,buf1,BUF1_SIZE,0,(structsockaddr*)&srcAddr,&srcAddrLen ); //wypisaniewiadomościzinformacjąonadawcy buf1[ret]='\0'; printf("odebrano%dbajtówod%s:%s\n", ret,getAddresInfo(&srcAddr,srcAddrLen,buf2,BUF2_SIZE),buf1 ); } } default:{ //rodzicwysyławiadomości while(fgets(buf1,BUF1_SIZE,stdin)){
ret=sendto( sfd,buf1,strlen(buf1),0, dstAddrInfo->ai_addr,dstAddrInfo->ai_addrlen ); printf("wysłano:%dbajtów:%s\n",ret,buf1); } //kończymypotomkagdyskończyliśmynadawanie kill(pid,SIGTERM); wait(0); } } //zamknieciegniazda puts("KONIEC"); freeaddrinfo(dstAddrInfo); close(sfd);}
//konwersjaadresówIPv4iIPv6wrazznumeremportunanapisconstchar*getAddresInfo( structsockaddr_storage*srcAddr,socklen_tsrcAddrLen, char*buf,intbufLen){ if(srcAddrLen>sizeof(structsockaddr_storage)) returnNULL; constchar*addrStr=NULL; uint16_tport; if(srcAddr->ss_family==AF_INET){ structsockaddr_in*srcAddrPtr=(structsockaddr_in*)srcAddr; addrStr=inet_ntop(AF_INET,&(srcAddrPtr->sin_addr),buf,bufLen); port=ntohs(srcAddrPtr->sin_port); }elseif(srcAddr->ss_family==AF_INET6){ structsockaddr_in6*srcAddrPtr=(structsockaddr_in6*)srcAddr; addrStr=inet_ntop(AF_INET6,&(srcAddrPtr->sin6_addr),buf,bufLen); port=ntohs(srcAddrPtr->sin6_port); } if(addrStr){ intlen=strlen(buf); snprintf(buf+len,bufLen-len,":%d",port); } returnaddrStr;}
importsocket,sys,os,signal
iflen(sys.argv)!=3andlen(sys.argv)!=4: print("USAGE:"+sys.argv[0]+"dstHostdstPort[listenPort]",file=sys.stderr) exit(1);
#strukturazawierającaadresnaktórywysyłamydstAddrInfo=socket.getaddrinfo(sys.argv[1],sys.argv[2])
#tutajmogliśmyuzyskaćkilkaadresów,#aleoptymistyczniezakładamyżepierwszybędzieOKdstAddrInfo=dstAddrInfo[0]
#utworzeniegniazdasieciowego...SOCK_DGRAMoznaczaUDP#(nagnieździezSOCK_DGRAMstandardowoniebędziewidaćbłędówICMP#związanychnp.zniedostępnościądocelowegohostalubportu...)sfd=socket.socket(dstAddrInfo[0],socket.SOCK_DGRAM)
iflen(sys.argv)==4: #jeżelipodaneopcjonalneargumentutookreślamynajakimporciesłuchamy ifdstAddrInfo[0]==socket.AF_INET6: sfd.bind(('::',int(sys.argv[3]))) #::oznaczadowolnyadresIPv6 elifdstAddrInfo[0]==socket.AF_INET: sfd.bind(('0.0.0.0',int(sys.argv[3]))) #0.0.0.0oznaczadowolnyadres #określenietegowrazzuruchomieniemrecvfrom()pozwalanaoczekiwaniena #pakietyUDPnawskazanymadresieiporcie,gdybywramachobsługiodebranej #wiadomościodsyłanabyłabyodpowiedźdonadawcytobyłbyto"serwerUDP"
###PrzykładPython
whileTrue: rdfd,_,_=select.select([sfd,sys.stdin],[],[]) ifsfdinrdfd: #odbieramyiwypisujemydanezUDP data,addr=sfd.recvfrom(4096) print("odebranood",addr,":",data.decode()); ifsys.stdininrdfd: #wczytujemystdin data=sys.stdin.readline() ifnotdata: #konczymy sfd.close() sys.exit() else: #wysyłamydanezstdin sfd.sendto(data.encode(),dstAddrInfo[4])
#alternatywniemożnaużyćfork():#pid=os.fork()#ifpid==0:# #potomekodbieraodpowiedziwnieskończonejpętli# #zostaniezakończonysygnałemodrodzica# whileTrue:# data,addr=sfd.recvfrom(4096)# print("odebranood",addr,":",data.decode());#else:# #rodzicwysyławiadomości# whileTrue:# data=sys.stdin.readline()# ifnotdata:# break# else:# sfd.sendto(data.encode(),dstAddrInfo[4])# os.kill(pid,signal.SIGTERM)# sfd.close()
TCP-klient
TransmissionControlProtocol(TCP)jestprotokołemdziałającympowyżejprotokołuIPgwarantującymniezawodność i kolejność dostarczania danych. Podobnie jak w przypadku UDP pakiety TCP oprócznumerów IP także zawierają docelowy i źródłowy numer portu, służący do identyfikacji procesuotrzymującegoinadającego.
Działanie TCP opiera się na zestawianiu (i kontrolowaniu) połączenia, w związku z tym klient pootwarciu gniazda musi nawiązać połączenie z wskazanym adresem IP i numerem portu, a dopieropotem może wysyłać lub odbierać dane (nie określając już adresów, gdyż odbywa się to w ramachnawiązanego połączenia) nawet poprzez zwykłe funkcje write() i read(). Połączenie należy zamknąćkorzystajączfunkcjiclose(),coinformujezarównonaszsystemjakiserwerozakończeniupołączenia.
#include<sys/socket.h>#include<netinet/ip.h>#include<arpa/inet.h>#include<netdb.h>
#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<string.h>
#defineBUF_SIZE256
intmain(intargc,char*argv[]){ intret,sfd; charbuf[BUF_SIZE]; if(argc!=3){ fprintf(stderr,"%sdstHostdstPort\n",argv[0]); return1; } //strukturazawierającaadresnaktórywysyłamy //użyciefunkcjigetaddrinfopozwalanazapewnienieobsługizarównoIPv4jakiIPv6, //atakżepodawanieadresówwpostacinumerycznejbądźprzyużyciunazw
///PrzykładC++
//alternatywniemożnaręcznieprzygotowywaćstrukturysockaddr_in/sockaddr_in6 //zużyciemnp.htons(),inet_aton(),... structaddrinfo*dstAddrInfo; if((ret=getaddrinfo(argv[1],argv[2],NULL,&dstAddrInfo))!=0){ fprintf(stderr,"Erroringetaddrinfo():%s\n",gai_strerror(ret)); return1; } //mogliśmyuzyskaćkilkaadresów,więcpróbujemyużywaćkolejnychdoskutku structaddrinfo*aiIter; for(aiIter=dstAddrInfo;aiIter!=NULL;aiIter=aiIter->ai_next){ //utworzeniegniazdasieciowego...SOCK_STREAMoznaczaTCP sfd=socket(aiIter->ai_family,SOCK_STREAM,0); if(sfd<0){ perror("Errorinsocket()"); continue; } //łączymyzserwerem if(connect(sfd,aiIter->ai_addr,aiIter->ai_addrlen)){ perror("Errorinconnect()"); close(sfd); sfd=-1; continue; } //udałosiępołączyć...przerywamysprawdzaniekolejnychadresów break; } freeaddrinfo(dstAddrInfo); if(sfd<0){ fprintf(stderr,"Can'tconnect\n"); return1; } constchar*msg="AlamaKota\n"; if(send(sfd,msg,strlen(msg),0)<0){ //takiewywołaniesend()jestrównoważnewywołaniuwrite() perror("Errorinsend()"); return1; } //ustalamylimitczasuoczekiwanianadane13s structtimevaltimeOut; timeOut.tv_sec=13; timeOut.tv_usec=0; //tworzymyzestawdeskryptorówdlafunkcjiselect() //iumieszczamywnimdeskryptorgniazdasieciowego fd_setfdSet; FD_ZERO(&fdSet); FD_SET(sfd,&fdSet); //czekamynadanewktórymśzdeskryptorówwchodzących //wskładzestawulubtimeout select(FD_SETSIZE,&fdSet,0,0,&timeOut); //selectzmieniwartośćfdSetitimeOut... //będąonezawierałyodpowiedniozbiórdeskryptorówgotowych //doczytaniaiczasjakipozostałdo"wytimeoutowania" if(FD_ISSET(sfd,&fdSet)){ //jeżelisfdjestwzbiorzegotowychdoczytaniatoczytamy ret=read(sfd,buf,BUF_SIZE); if(ret<0){ perror("Errorinread()"); }elseif(ret==0){ puts("connectionclosebypeer"); }else{ buf[ret]='\0'; printf("odebrano%dbajtów:%s\n",ret,buf); } }else{ puts("timeout"); } //wzależnościodwymagańimplementowanegoprotokołumożnakontynuować //czekanienakolejnedanezTCPi/lubjakiegośinnegowejścia(np.stdin),
//możnawysłaćkolejnedane(żądanie)doserwera,itd... // //wprzypadkuoczekiwanianadalszedane(ponownegowywołaniaselect)należy //pamiętaćoponownymustawieniufdSetitimeOut //zamknieciegniazda close(sfd);}
importsocket,select,sys
iflen(sys.argv)!=3: print("USAGE:"+sys.argv[0]+"dstHostdstPort",file=sys.stderr) exit(1);
#strukturazawierającaadresnaktórywysyłamydstAddrInfo=socket.getaddrinfo(sys.argv[1],sys.argv[2],proto=socket.IPPROTO_TCP)
#mogliśmyuzyskaćkilkaadresów,więcpróbujemyużywaćkolejnychdoskutkuforaiIterindstAddrInfo: try: print("tryconnectto:",aiIter[4]) #utworzeniegniazdasieciowego...SOCK_STREAMoznaczaTCP sfd=socket.socket(aiIter[0],socket.SOCK_STREAM) #połączeniezewskazanymadresem sfd.connect(aiIter[4]) except: #jeżelisięnieudało...zamykamygniazdo ifsfd: sfd.close() sfd=None #ipróbujemynastępnyadres continue break;
ifsfd==None: print("Can'tconnect",file=sys.stderr) exit(1);
#wysyłaniesfd.sendall("AlamaKota\n".encode())
#czekanienaodbiórrdfd,_,_=select.select([sfd],[],[],13.0)ifsfdinrdfd: d=sfd.recv(4096) print(d.decode())
#zamykaniepołączeniasfd.shutdown(socket.SHUT_RDWR)sfd.close()
TCP-serwer
Ze względu na nawiązywanie połączenia w przypadku TCP serwer wygląda i działa odmiennie odklienta.Pootworzeniugniazdaserwermusi:
1. określićadresuinumeruportunaktórymoczekujenaprzychodzącepołączenia(funkcjabind)2. określićżegniazdotoużywanejestdonasłuchiwaniapołączeńprzychodzących(funkcjalisten)3. rozpocząćoczekiwanienaodbiórpołączenia(funkcjaaccept)
Po nawiązaniu połączenia TCP (realizowanym na poziomie systemu operacyjnego) funkcja accept()zwraca nowe gniazdo związane z nawiązanym połączeniem TCP. Ma ono ustawiony adresem IP iportem używany przez klienta oraz inny (niż używany do nasłuchiwania) numer portu po stronieserwera.
#include<sys/socket.h>#include<netinet/ip.h>#include<arpa/inet.h>
#include<stdio.h>#include<stdlib.h>#include<unistd.h>
###PrzykładPython
///PrzykładC++
#include<string.h>#include<signal.h>#include<sys/wait.h>
#defineBUF_SIZE256#defineQUERY_SIZE3#defineMAX_CHILD5
intchildNum=0;voidonChildEnd(intsig){ puts("odebranosygnałośmiercipotomka"); --childNum; waitpid(-1,NULL,WNOHANG);}
intmain(intargc,char*argv[]){ intres; charbuf[BUF_SIZE]; if(argc!=2){ fprintf(stderr,"USAGE:%slistenPort\n",argv[0]); returnEXIT_FAILURE; } //obsługasygnałuozakończeniupotomka signal(SIGCHLD,&onChildEnd); //utworzeniegniazdasieciowego...SOCK_STREAMoznaczaTCP intsfd=socket(PF_INET6,SOCK_STREAM,0); if(sfd<0){ perror("Errorinsocket()"); returnEXIT_FAILURE; } //ustawienieopcjigniazda...IPV6_V6ONLY=0umożliwiakorzystanieztego //samegosocketudlaIPv4iIPv6(rozszerzenieLinux-owe-naniektórych //systemachniejestmożliwedualnesłuchanieprzypomocysocketuIPv6) intopt=0;if(setsockopt(sfd,IPPROTO_IPV6,IPV6_V6ONLY,&opt,sizeof(opt))<0){ perror("setsockopt(IPV6_V6ONLY=0)"); returnEXIT_FAILURE; } //utworzeniestrukturyopisującejadres structsockaddr_in6serwer; serwer.sin6_family=AF_INET6; serwer.sin6_port=htons(atoi(argv[1])); //hosttonetworkshort(porządekbajtów),sąteżdlalonginetworktohost serwer.sin6_addr=in6addr_any; //in6addr_anyoznaczażenasłuchujemynakażdymadresieIPdanegohosta //(zamiasttegomożnaokreślićkonkretnyadres)
//przypisanieadresu... if(bind(sfd,(structsockaddr*)&serwer,sizeof(structsockaddr_in6))<0){ perror("Errorinbind()"); returnEXIT_FAILURE; }
//określeniegniazdajakoużywanegodonasłuchiwaniapołączeńprzychodzących if(listen(sfd,QUERY_SIZE)<0){ perror("Errorinlisten()"); returnEXIT_FAILURE; } while(1){ //odebraniepołączenia structsockaddr_in6from; socklen_tfromLen=sizeof(structsockaddr_in6); intsfd2=accept(sfd,(structsockaddr*)&from,&fromLen); //weryfikacjailościpotomków if(childNum>=MAX_CHILD){ printf("zadużopotomków\n"); //możnatutajtakżewysłaćinformacjeobłędzieserweradoklienta close(sfd2); continue; }
//abymócobsługiwaćwielepołączeńrozgałęziamyproces intpid=fork(); if(pid==0){ //procespotomny...zajmujesiętylkonowympołączeniem, //anienasłuchaniemwięczamykamysfd close(sfd); //konwersjaadresunapostaćnapisową charfromStr[64]; snprintf(fromStr,64,"%s:%d", inet_ntop(AF_INET6,&(from.sin6_addr),buf,BUF_SIZE), ntohs(from.sin6_port) ); //obsługapołączenia printf("połączenieod:%s\n",fromStr); FILE*net; net=fdopen(sfd2,"r+"); //należałobytutajużywaćczekaniaztimeout'em... //inaczejusługajestpodatnanaatakiDoS while(fgets(buf,BUF_SIZE,net)){ printf("odebranood%s:%s\n",fromStr,buf); fputs(buf,net); } fclose(net); printf("koniecpołączeniaod:%s\n",fromStr); //zakończeniepołączeniaipotomka close(sfd2); return0; } if(pid==-1) perror("Errorinfork()"); ++childNum; close(sfd2); }
//zamknieciegniazda close(sfd);}
importsocket,select,signal,sys,os
MAX_CHILD=5QUERY_SIZE=3TIMEOUT=13BUF_SIZE=4096
iflen(sys.argv)!=2: print("USAGE:"+sys.argv[0]+"listenPort",file=sys.stderr) exit(1);
#obsługasygnałuozakończeniupotomkachildNum=0defonChildEnd(s,f): print("odebranosygnałośmiercipotomka") globalchildNum childNum-=1 os.waitpid(-1,os.WNOHANG);signal.signal(signal.SIGCHLD,onChildEnd)
#utworzeniegniazdsieciowych...SOCK_STREAMoznaczaTCPsfd_v4=socket.socket(socket.AF_INET,socket.SOCK_STREAM)sfd_v6=socket.socket(socket.AF_INET6,socket.SOCK_STREAM)
#ustawienieopcjigniazda...IPV6_V6ONLY=1wyłączakorzystanie#ztegosamegosocketudlaIPv4iIPv6sfd_v6.setsockopt(socket.IPPROTO_IPV6,socket.IPV6_V6ONLY,1)
#przypisanieadresów...#'0.0.0.0'oznaczadowolnyadresIPv4(czylitosamocoINADDR_ANY)#'::'oznaczadowolnyadresIPv6(czylitosamocoin6addr_any)sfd_v4.bind(('0.0.0.0',int(sys.argv[1])))
###PrzykładPython
sfd_v6.bind(('::',int(sys.argv[1])))
#określeniegniazdjakoużywanychdoodbiorupołączeńprzychodzących#(długośćkolejkipołączeńustawionanawartośćQUERY_SIZE)sfd_v4.listen(QUERY_SIZE)sfd_v6.listen(QUERY_SIZE)
#funkcjazajmującasięodbieraniempołączeńiichobsługądefacceptConn(sfd): globalchildNum #odebraniepołączenia sfd_c,sAddr=sfd.accept() #weryfikacjailościpotomków ifchildNum>=MAX_CHILD: print("zadużopotomków-odrzucampołączenieod:",sAddr); sfd_c.send("InternalServerError\r\n".encode()) sfd_c.close() return #abymócobsługiwaćwielepołączeńrozgałęziamyproces pid=os.fork() ifpid==0: print("połączenieod:",sAddr) whileTrue: #czekanienadaneztimeout'em #abyzabezpieczyćsięprzedatakiemDoS rd,_,_=select.select([sfd_c],[],[],TIMEOUT) ifsfd_cinrd: data=sfd_c.recv(BUF_SIZE) ifnotdata: print("koniecpołączeniaod:",sAddr) break print("odebranood",sAddr,":",data.decode()); sfd_c.send(data) else: print("timeoutpołączeniaod:",sAddr) break #zamykaniepołączenia sfd_c.shutdown(socket.SHUT_RDWR) sfd_c.close() sys.exit() else: childNum+=1
#czekanienapołączeniazużyciemselect()wnieskończonejpętliwhileTrue: sfd,_,_=select.select([sfd_v4,sfd_v6],[],[]) ifsfd_v4insfd: acceptConn(sfd_v4) ifsfd_v6insfd: acceptConn(sfd_v6)
InnefunkcjesystemoweAlokacjapamięci
Zadeklarowaniezmiennejwkodzieprogramu(prawiezawsze)wiążesięzprzydzieleniemjej jakiegośobszarupamięci.Kompilatortypowozmiennelokalneumieszczanesąwobszarzepamięcinazywanymstosem (znajdują się tam też m.in. argumenty funkcji, stany rejestrów procesora w momenciewywołaniafunkcjiiadresypowrotufunkcji).
Stosposiadaograniczonyrozmiar,któregoprzekroczenie(np.naskutekzbytdługiegociąguwywołańfunkcji lub zdefiniowania zbyt dużych zmiennych lokalnych) kończy się błędem przepełnienia stosu.Rozmiarstosumożejednakbyćzmienionyzarównoprzeduruchomieniemprocesu(przypomocyulimit-s),lubwtrakciejegopracy(przypomocysetrlimit(RLIMIT_STACK,...)),podwarunkiemżemieścisięwramachogólnosystemowegolimitu.Zwiększenierozmiarustosuwpływanarozmiarpamięciwirtualnejprzydzielonej procesowi, jednak (samo w sobie) nie wpływa na rzeczywiste zużycie pamięci przezproces.
Częstonawetsamozadeklarowaniedużej tablicyniewpływanarzeczywistązajętośćpamięci,wpływmadopieroużywanietakiejtablicy:
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<sys/resource.h>
charbuf[64],*bufS;
intfun(){ inti,j,x[10000000]; for(i=0;i<17;i+=2){ for(j=0;j<20000;++j)x[i*10000+j]=j; sleep(1); system(buf); }}
intmain(){ snprintf(buf,64,"ps-o'vsize,size,rss,cmd'-p%d",getpid()); system(buf); puts("zwiększamrozmiarstosu"); structrlimitrl; rl.rlim_cur=2000000000; rl.rlim_max=rl.rlim_cur; if(setrlimit(RLIMIT_STACK,&rl)) perror("Errorinsetrlimit()"); system(buf); bufS=buf+strlen(buf); snprintf(bufS,64-(bufS-buf),"--no-headers"); fun(); *bufS='\0';system(buf);*bufS=''; fun();}
Mimomożliwościzwiększeniarozmiarustosutypowowiększebuforyczyteżobiektyalokowanesąpozastosem. W C++ stosowane są dwie techniki takie alokacji: operator new i funkcje z rodziny malloc.Alokacja pamięci poza stosem powoduje konieczność jawnego zwalniania pamięci (nie jest onazwalnianawrazzzniknięciemzmiennej)przypomocyodpowiedniooperatoradeletelubfunkcjifree.
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<inttypes.h>
structAbc{ std::stringa; intb;private: shortc;public: Abc(){ puts("konstruktorABC"); c=123; } ~Abc(){ puts("destruktorABC"); } voidprint(){ printf("a:%s,b:%d,c:%d\n",a.c_str(),b,c); }};
structXxx{ Abcabc1; Abcabc2; inttab[9];
///PrzykładC++
///PrzykładC++
intxx1; intxx2;};
intmain(intargc,char*argv[]){ inta[5],aa; //alokacjapamięci int*bb=(int*)malloc(sizeof(int)); int*cc=newint; int*c=newint[20];//tablicaalokowanadynamiczniewstyluC++ Abc*dd=newAbc; printf("nastosie:%p%p%p%p\n",&argv,&argc,&aa,a); printf("pozastosem:%p%p%p%p\n",bb,cc,c,dd); //zwalnianiepamięci free(bb); deletecc; deletec; deletedd; //alokujemywiększyobszarpamięciprzypomocymalloc'a char*x=(char*)malloc(1024); //jestteżrealloc()umożliwiającyzmianęrozmiaruzaalokowanegoobszaru //zerujemyzaalokowanąpamięć...naogółniejesttopotrzebne, //alewtymprzykładziemożesięprzydać memset(x,0,1024); //częstoprzydatnajestteżfunkcjamemcpy()kopiującawskazany //fragmentpamięciwinnemiejsce //pamięćzaalokowanązużyciemmalloc'amożemydzięki //artmetycewskaźnikowejorazrzutowaniutypówwskaźnikowych //interpretowaćwdowolnysposób... Abc*d1,*d2; int*b1,*b2; d1=(Abc*)x; d2=(Abc*)(x)+1; b1=(int*)(x+2*sizeof(Abc)); b2=b1+10; printf("rozmiarAbc:%ld==%ld==%ld\n", sizeof(Abc),(uint64_t)d2-(uint64_t)d1,(uint64_t)b1-(uint64_t)d2 ); d1->b=15; d1->print(); //jakwidaćpowstałobiekttypuAbc,aleniewykonałsiękonstruktor... //anikonstruktoryskładowych(jakstd::string),więcwywołanie: //d1->a="aabbcc"; //możesięnieudać(zakończyćsięnp.Segmentationfault) // //abyuniknąćzwiązanychztymproblemówmożemyskorzystaćzwariantu //operatoranewktóryutworzyobiektwzaalokowanejpamięci: new(d2)Abc; d2->a="aabbcc"; d2->print(); for(aa=0;aa<10;++aa) b1[aa]=aa+16; *b2=136917; //możemyteżnatakiobszarpamięci(nawetjużzapełniony) //patrzećnp.jaknastrukturę Xxx*z=(Xxx*)x; printf("%d==%d%d==%d%d==%d\n", z->tab[2],b1[2],z->xx1,b1[9],z->xx2,*b2 ); free(x);//takiezwolnienieniewywoładestruktorówdlad1id2}
Czas
Bieżącyczaswsystemachkomputerowychmożebyćreprezentowanynaróżnesposoby.Wprzypadkusystemów POSIXowych jest to ilość sekund od początku epoki czyli 1970-01-01 00:00:00 UTC. Napodstawie tej wartości może zostać obliczona przez funkcje biblioteczne aktualna data i godzina wustawionej(poprzezzmiennąśrodowiskowąTZ)strefieczasowej.
#include<time.h>#include<stdlib.h>#include<string.h>#include<stdio.h>
size_ttime2str( consttime_t*time,constchar*timeZone,constchar*format, char*buf,size_tbufLen,structtm*tmPtr);
intmain(){ time_tczas1=time(0); printf("Odpoczątkuepokiupłynęło%dsekund\n",czas1); //początekepokito:1970-01-0100:00:00UTC //wynikjestniezależnyodlokalnejstrefyczasowej //(zawszewyrażanyjestwUTC) //jeżelipotrzebnajestwiększaprecyzjatomożnaużyćnp.: structtimespecczas2; clock_gettime(CLOCK_REALTIME,&czas2); printf("Odpoczotkuepokiupłyneło%dsekundi%dns\n", czas2.tv_sec,czas2.tv_nsec); //naniektórychplatformach(np.Linux)wclock_gettime() //wspieranesątakżeinnezegaryniżczasurzeczywistego //np.podająceczasmonotonicznyluboduruchomieniasystemu charbuf[128]; //korzystamyzwłasnejfunkcjitworzącejnapiswoparciuo //formatzmiennejczasowej...coprawdadoUTCjestgmtime(), //alewpołączeniuzstrftimepotrafidawaćzłewyniki //(np.dla"%s")ponadtofunkcjatakapozwalatakżena //obsługęinnychstrefczasowych time2str( &(czas2.tv_sec),"UTC","%Y-%m-%d%H:%M:%S%Z(%s)", buf,sizeof(buf),NULL ); printf("Mamyteraz:%s\n",buf); time2str( &(czas2.tv_sec),NULL,"%Y-%m-%d%H:%M:%S%Z(%s)", buf,sizeof(buf),NULL ); printf("Mamyteraz:%s\n",buf);}
size_ttime2str( consttime_t*time,constchar*timeZone,constchar*format, char*buf,size_tbufLen,structtm*tmPtr){ //jeżelipodanotmPtr!=NULLużyjpodanejstruktury, //wprzeciwnymrazieużyjlokalnej structtmtmTmp; if(!tmPtr){ tmPtr=&tmTmp; } //jeżelipodanostrefęczasowąto //zapamiętajoryginalnąstrefęiustawnową charoldTZ[128]; if(timeZone){ strncpy(oldTZ,getenv("TZ"),128); setenv("TZ",timeZone,1); tzset(); } //pobierzrozłożonyczaswustawionejstrefieczasowej localtime_r(time,tmPtr);
///PrzykładC++
//zapiszsformatowanynapisdobufora bufLen=strftime(buf,bufLen,format,tmPtr); //przywróćoryginalnąstrefęczasową if(timeZone){ setenv("TZ",oldTZ,1); tzset(); } returnbufLen;}
importtimeimportos
deftime2str(t,tz=None,fmt="%Y-%m-%d%H:%M:%S%Z(%s)"): iftz: oldTZ=os.environ['TZ'] os.environ['TZ']=tz time.tzset() tm=time.localtime(t) s=time.strftime(fmt,tm) iftz: os.environ['TZ']=oldTZ time.tzset() return[s,tz]
czas=time.time()print("Odpoczątkuepokiupłynęło"+str(czas)+"sekund")#początekepokito:1970-01-0100:00:00UTC#wynikjestniezależnyodlokalnejstrefyczasowej#(zawszewyrażanyjestwUTC)
tt=time2str(czas,tz="UTC")print("Mamyteraz:"+tt[0]);
tt=time2str(czas)print("Mamyteraz:"+tt[0]);
fromdatetimeimportdatetime,timezone
dt=datetime.fromtimestamp(czas,tz=timezone.utc)print("Mamyteraz:"+dt.strftime("%Y-%m-%d%H:%M:%S%Z(%s)"))
#wcelupobraniaaktualnegoczasuzamiastfromtimestamp()#możnaskorzystaćzmetodynow()
Timery
Jeżeli program ma wykonywać jakąś czynność co określony czas może korzystać z funkcji sleep lubpodobnychcelemprzeczekaniapodanegoczasulubskorzystaćztimerówcelemotrzymaniasygnałupozadanymczasie.
//przykompilacjikoniecznejestdodanie://-lrt-lpthread
#include<time.h>#include<signal.h>#include<stdio.h>#include<unistd.h>#include<errno.h>
voidonTimer(intsig){ puts("timer!!!"); //drzemka0.35s //dospaniamożnawykorzystaćusleep(),sleep()lubnanosleep() //usleepisleepdziałająbardzopodobnie
###PrzykładPython
///PrzykładC++
//(ztymżepierwszyprzyjmujeczaswsekundach,adrugiwmikrosekundach) usleep(350000);}
intmain(){ //obslugujemysygnałSIGALRM signal(SIGALRM,&onTimer); //najprostrzytimer... alarm(4);pause(); //timeryPOSIX(wiecejmantimer_settime) //1)tworzymytimer timer_ttimer; timer_create(CLOCK_REALTIME,NULL,&timer); //podaniewskaźnikanastrukturęsigeventzamiastNULLpozwalanaokreślenie //innegosygnałujakimawygenerowaćtimerlubobsługętakjakwątku //(więcejw`man7sigevent`) //2)konfiguryujemytimer structitimerspectSpec; //pierwszewykonanietimerapo100ms tSpec.it_value.tv_sec=0; tSpec.it_value.tv_nsec=100000000; //kolejneco1s //(jezeliit_intervalbędziewyzerowanetotimerwykonasiętylkoraz) tSpec.it_interval.tv_sec=1; tSpec.it_interval.tv_nsec=0; //3)uruchamiamytimer //drugimargumentemsąflagi-flagaTIMER_ABSTIMEpozwalana //ustawienietimeranaczasabsolutny(anieokresczasu) timer_settime(timer,0,&tSpec,NULL); chari=0; do{ structitimerspectRest; timer_gettime(timer,&tRest); printf("dotimerapozostało:%dns\n",tRest.it_value.tv_nsec); pause();//czekamynatimer printf("aktualnaliczbautraconychtyknięćtimerawynosi%d\n", timer_getoverrun(timer)); }while(i++<3); //powyższametodazapewniarozpoczynaniewrównychodstępachczasu... //wprzypadkuzastosowaniasleep()należałobyobliczaćczasprzezktóry //wykonywałsiękodiodejmowaćgoodczasuktórypodajemydosleep() //drzemka //nanosleeppozwalanaokreśleniesekundimilisekundorazzwracaczas //różnicępomiędzyplanowanymczasemspaniaarzeczywistymczasem //odwejściadopowrotuzfunkcjinanosleep()-uwzględniającnp.czas //obsługisygnałuktóryprzerwałdziałaniefunkcjinanosleep() structtimespecdrzemka,pobudka; drzemka.tv_sec=2; drzemka.tv_nsec=100000000; //chcemyspac2.1saleobudzinastimer //toilezesmyniedospalizostaniezapisanewpobudka if(nanosleep(&drzemka,&pobudka)<0&&errno==EINTR) printf("niedospalismy:%dsi%dns\n",pobudka.tv_sec,pobudka.tv_nsec); //usuniecietimera timer_delete(timer);}
BibliotekiCelem uniknięcia konieczności wielokrotnego tworzenia funkcji realizujących te same zadania wprogramowaniu powszechnie wykorzystuje się różnego rodzaju biblioteki programistyczne. Bibliotekajest zbiorem funkcji i powiązanych z nimi typów danych oraz danych. Praktycznie każdy z językówoferuje zbiór podstawowych funkcji zgromadzony w tzw. bibliotece standardowej, oprócz bibliotekistandardowejdanegojęzykamożnakorzystaćtakżezzewnętrznych(wtymwłasnych)bibliotek.
Bibliotekaposiadaokreślonyinterfejsprogramistyczny(API),definiowanynapoziomiekoduźródłowego,którywprzypadkuprogramówwC/C++jestzazwyczajopisanywplikachnagłówkowychzwiązanychzdaną biblioteką (najczęściej z rozszerzeniem .h). Zmiany API biblioteki wraz z kolejnymi jej wersjamimogą(aleniemuszą-zależyodzachowywaniatzw.kompatybilnościwstecznejprzeztwórcówbiblioteki)wymagaćzmianwprogramachzniejkorzystających.Interfejsbibliotekitypowodostępnyjestnatywnietylkodlajęzykawktórymzostałastworzona.Dlainnychjęzykówwymagaonobudowaniawtakispsóbabybyłzrozumiałydlakompilatora/interpretaradanegojęzyka,zadanietorealizujątzw.wrappery.
OpróczAPIbibliotekiposiadają takżeokreślony interfejsbinarny (ABI),któryodpowiadazamożliwośćwywoływania odpowiednich procedur z biblioteki przez skompilowany i zlinkowany program. TypowoABI jest mniej stabilne od API i zmiany wymagające skompilowania i zlinkowania programu z nowąwersjąbibliotekizachodzączęściejniżzmianyAPIniezachowującekompatybilnościwstecznej.
Kod biblioteki może być włączony na stałe w kod programu (biblioteka statyczna) - zapewnia to brakproblemówzzgodnościąABIbibliotekipomiędzysystememnaktórymprogramzostał skompilowany izlinkowany, a systemem na którym jest uruchamiany. Skutkuje to jednak wzrostem rozmiaru plikuwykonywalnegoorazzapotrzebowaniemnapamięćuruchomionegoprogramu.Alternatywąsąbibliotekiładowanedynamicznie, któredostarczane są jakoosobne (w stosunkucodobinarki programu)pliki iładowanedopamięciwmomenciestartuprogramulubpodczasjegodziałania.Kilkaróżnychprogramówużywających tej samej biblioteki dynamicznej będzie używało jednej jej kopi umieszczonej w pamięciRAM.
API,skrypty,...APIpythonowebibliotekiC++
Podstawowy interpreter Pythona stworzony jest w C, podobnie wiele z popularnych modułów(bibliotek)pythonowychjesttworzonywClubC++.PythonpotrafikorzystaćzzwykłychbibliotekC(poprzez moduł ctypes), jednak aby z biblioteki korzystało się wygodnie powinna ona wystawiaćbardziejnatywnyinterfejspythonowywpostacimodułu.NautworzenietakiegointerfejsuzpoziomuCpozwalabibliotekaprogramistycznadostarczanawrazzPythonem,wprzypadkuC++możnatakżekorzystaćzobudowującegowywołaniatejbibliotekiboost::python.
/*PLIK:py_api.cppkompilacja: g++--std=c++11-shared-fPIC-I/usr/include/python3.7m/py_api.cpp\ -oMyPyAPI.so-lpython3.7m-lboost_python37 uwaga:-kolejnośćargumentówmożebyćistotna -plikwynikowypowinienmiećtakąsamąnazwęjakmoduł zadeklarowanyprzypomocyBOOST_PYTHON_MODULE()*/
#include<iostream>#include<string>#include<list>
std::stringf1(inta){ for(inti=0;i<a;++i) std::cout<<"Alamakota\n"; return"KotmaAlę";}
structK1{ inta; staticK1*obj; intf1(intb){returna+b;} staticK1*get(){returnobj;}};
voidf2(K1&k,intn){ std::cout<<"runf2():"<<k.f1(2*n)<<"\n"; k.a+=1;}
K1*K1::obj=NULL;
#include<boost/python.hpp>
BOOST_PYTHON_MODULE(MyPyAPI){ boost::python::def("f1",f1); boost::python::class_<K1>("Klasa") .def_readwrite("a",&K1::a) .def("f1",&K1::f1)
///PrzykładC++
//wpythoniewodróżnieniuodC++referencjadoklasyjestjawnym //argumentemmetodniestatycznychzatemf2któreprzyjmujejako //pierwszyargumentreferencjędoobiektuklasyK1możemyużyć //jakometodyklasypythonowej .def("f2",f2) //typozfunkcjidopythonazwracanajestwartośćzmiennej(anie //referencjadozmiennejC++)jednakdlafunkcjizwracających //wskaźniklubreferencjęnaogółchcemyabyzwracanabyławłaśnie //referencjadoistniejącejzmiennejC++ .def("get",&K1::get, boost::python::return_value_policy< boost::python::reference_existing_object >() ) ; //f2możemyteżużyćjakoniezależnejfunkcji boost::python::def("f22",f2); //podobniejakf1 boost::python::def("f11",&K1::f1);}
#skryptwykorzystującymoduł#MyPyAPIstworzonywC++
#dodajemybierzącykatalogdościeżkiwktórejpythonszukabibliotekimportsyssys.path.append('./')
#importujemynasząbibliotekę(zplikuMyPyAPI.so)importMyPyAPI
#uruchomieniefunkcjif1iodebraniewynikuret=MyPyAPI.f1(2)print(ret)
#utworzenieobiektuklasyK1(Klasa)kk=MyPyAPI.Klasa()
#orazjegoużywanie...kk.a=3print(kk.f1(2))
kk.f2(1)MyPyAPI.f22(kk,1)print("kk.a=",kk.a)
print(MyPyAPI.f11(kk,1))
#skryptużywającybibliotekiC#bezAPIpythonowego
#skryptpowodujewłączenieNumLock#przypracywtrybiegraficznym#zgodnymzX11
fromctypesimport*X11=cdll.LoadLibrary("libX11.so.6")
X11.XOpenDisplay.restype=c_void_pdisplay=X11.XOpenDisplay(None);X11.XkbLockModifiers( c_void_p(display),c_uint(0x0100), c_uint(16),c_uint(16))X11.XCloseDisplay(c_void_p(display))
interfejsskryptowyprogramuC++
W wielu przypadkach zachodzi potrzeba połączenia zalet programów kompilowanych (szybkośćdziałania) i interpretowanych (elastyczność, łatwość modyfikacji). Jednym z rozwiązań toumożliwiających jest utworzenie w ramach kodu kompilowanego C++ interfejsu modułu
###PrzykładPython
###PrzykładPython
pythonowego, przy jednoczesnej możliwości zapewnienia wywoływania skryptów pythonowych zpoziomukoduC++korzystającychdokomunikacjiztymkodemztegointerfejsu.
/*PLIK:py_run.cppkompilacja: g++-I/usr/include/python3.7m/py_run.cpp-lpython3.7m-lboost_python37 uwaga:-kolejnośćargumentówmożebyćistotna -plikużywa"py_api.cpp"zpoprzedniegoprzykładu -plikwywołujeskrypt"py_run.script.py"zbieżącegokatalogu*/
//korzystamyzwcześniejprzygotowanego(w"APIpythonowebibliotekiC++")interfejsupythonowego#include"py_api.cpp"
intmain(int,char**){ K1*o1=newK1(); o1->a=1;
K1*o2=newK1(); o2->a=2; K1::obj=o1;
std::cout<<"o1->a="<<o1->a<<"o2->a="<<o2->a<<"\n"; //initialisepython Py_Initialize(); try{ //initialiseandimportMyPyAPImodule PyObject*module=PyInit_MyPyAPI(); PyDict_SetItemString(PyImport_GetModuleDict(),"MyPyAPI",module); Py_DECREF(module); PyRun_SimpleString("importMyPyAPI"); //poprzezPyRun_SimpleStringmożnateżuruchamiaćinnefragmentykodupythonowego //preparetorunscripts boost::python::objectmain=boost::python::import("__main__"); boost::python::objectglobal(main.attr("__dict__")); //exportobjecttopython global["ck1"]=boost::python::ptr(o1); //runfile boost::python::objectresult=boost::python::exec_file( "./py_run.script.py",global,global ); //importobjectfrompython boost::python::objectscript=global["script1"]; //runpythonfunctionwithargsfromC++ if(!script.is_none()){ //runscripts std::cout<<"RUN\n"; std::cout<<"return="<<boost::python::extract<int>( script(boost::python::ptr(o2)) )<<"\n"; } }catch(boost::python::error_already_set&){ PyErr_Print(); exit(-1); } std::cout<<"o1->a="<<o1->a<<"o2->a="<<o2->a<<"\n"; deleteo1; deleteo2; return0;}
#PLIK:py_run.script.py#uruchamianyprzezkodC++zpy_api.cpp
///PrzykładC++
###PrzykładPython
print("początekpliku.py")
ck0=MyPyAPI.Klasa.get()print("ck0:",ck0.f1(0))print("ck1:",ck1.f1(0))
ck0.a=4print("ck0:",ck0.f1(0))print("ck1:",ck1.f1(0))
defscript1(arg): print("runscript1") print("ck0:",ck0.f1(0)) print("ck1:",ck1.f1(0)) print("arg:",arg.f1(0)) arg.a=13 print("ck0:",ck0.f1(0)) print("ck1:",ck1.f1(0)) print("arg:",arg.f1(0)) print("endscript1") returnarg.a+ck0.a;
print("koniecpliku.py")
Bazydanych
StandardowymjęzykiemużywanymdokomunikacjizsystemamibazodanowymijestSQL.Pomimojegostandaryzacjiistniejąróżnicewskładnizapytańdlaposzczególnychsilnikówbazodanowych(takichjak:MariaDB,PostgreSQL,SQLite,...).
Typowo komunikacja z bazą danych odbywa się za pośrednictwem biblioteki odpowiedzialnej zanawiązanie połączenia z serwerem i przekazywanie do niego zapytań SQL. Wymaga to działaniaosobnego procesu (często nawet na innej maszynie) obsługującego silnik bazodanowy, co jestpożądanym rozwiązaniem dla baz danych z których równocześnie może korzystać wielu klientów.Typowymprzykłademmożebyćkomunikacjaskryptówjakiegośserwisuinteretowegozbaządanych.Jednak takie podejście nie jest wygodne w rozwiązaniach nie wymagających współdzielenia bazydanych.DozastosowańtakichmożnaużyćbibliotekiSQLite,którapozwalanałatwestosowaniebazySQLowej do wewnętrznych potrzeb aplikacji, bez konieczności uruchamiania osobnego systemubazodanowego.
//przykompilacjikoniecznejestdodanie://-lsqlite3
#include<sqlite3.h>#include<stdio.h>
/*bazęmożnautworzyćzarównowponiższymkodziepoleceniamiSQL,*jakteżzpoziomupowłoki:cat<<EOF|sqlite3example.dbCREATETABLEposts(pidINTPRIMARYKEY,uidINT,textTEXT);INSERTINTOpostsVALUES(1,21,'abc..');INSERTINTOpostsVALUES(3,2671,'test');EOF*/
intmain(){ sqlite3*db; if(sqlite3_open("example.db",&db)){ fprintf(stderr,"Can'topendatabase:%s\n",sqlite3_errmsg(db)); sqlite3_close(db); return1; } sqlite3_stmt*stmt; intret=sqlite3_prepare_v2(db, "SELECTuid,textFROMposts", -1,&stmt,NULL ); while((ret=sqlite3_step(stmt))==SQLITE_ROW){
///PrzykładC++
intuid=sqlite3_column_int(stmt,0); constchar*text=(constchar*)sqlite3_column_text(stmt,1); printf("uid=%d,text:%s\n",uid,text); }}
importsqlite3importos.path
ifos.path.isfile('example.db'): create=Falseelse: create=Trueconn=sqlite3.connect('example.db')c=conn.cursor()
ifcreate: print("createnewdb") c.execute("CREATETABLEusers(uidINTPRIMARYKEY,nameTEXT);") c.execute("CREATETABLEposts(pidINTPRIMARYKEY,uidINT,textTEXT);") c.execute("INSERTINTOusersVALUES(21,'userA');") c.execute("INSERTINTOusersVALUES(2671,'userB');") c.execute("INSERTINTOpostsVALUES(1,21,'abc..');") c.execute("INSERTINTOpostsVALUES(2,21,'qwexyz');") c.execute("INSERTINTOpostsVALUES(3,2671,'test');")
conn.commit()
maxUid=100forrinc.execute("SELECT*FROMusersWHEREuid<?;",(maxUid,)): print(r)
forrinc.execute("""SELECTu.name,p.textFROMusersASuJOINpostsASpON(u.uid=p.uid);"""): print(r)
<?php$sql_conn=mysqli_connect('server','user','password','database');if(!$sql_conn){ echo"ERROR:".mysqli_connect_error(); exit;}else{ echo"ConnectedtoMySQL:".mysqli_get_host_info($sql_conn);}
$query=$db->query("SELECTu.name,p.textFROMusersASuJOINpostsASpON(u.uid=p.uid);");while($row=$query->fetch_array()){ print($row["name"].":".$row["text"]."\n");}?>
(Graficzny)interfejsużytkownika
Jeżeli zachodzi potrzeba interakcji z użytkownikiem programu, zamiast wspomnianego wcześniejprostegopytania o kolejneparametry z użyciem standardowego wyjścia iwejścia, często stosuje siępseudo-graficzny lub graficzny interfejs użytkownika. Interfejs pseudo-graficzny jest zasadniczobardziejwyrafinowanąformąinterakcjiprzezstandardowewyjścieiwejścieprogramuiwykorzystujestandardowewyjściedorysowaniaróżnegotypuokienekdialogowych,itp.wtrybietekstowym.
#interfejspseudograficznyzużyciembibliotekicurces...#ataknaprawdęprogramudialogzniejkorzystającego
fromdialogimportDialogfromtimeimportsleep
d=Dialog(dialog="dialog")#taknaprawdęjesttowraper
###PrzykładPython
///PrzykładPHP
###PrzykładPython
#wykorzystującyprogramonazwie"dialog"##jestwstanie(wograniczonymzakresie)#współpracowaćzinnymitegotypunarzędziami#(takżedziałającymiwtrybiegraficznym)#takimijak:whiptail,kdialog,...#d=Dialog(dialog="kdialog",compat="kdialog")
d.set_background_title("ABC...")
res=d.yesno("TakczyNIE?")
ifres==d.OK: d.msgbox("TAK!!!")else: d.msgbox("NIE!!!")
d.gauge_start("proszęczekać...będzierozmowa...")foriinrange(0,101,5): d.gauge_update(i) sleep(1)
#interfejspseudograficznyzużyciemQt4
importsysfromPyQt4importQtGui,QtCore
app=QtGui.QApplication(sys.argv)
win=QtGui.QWidget()win.resize(250,150)win.move(300,300)win.setWindowTitle('ABC...')
defshowDialog(): reply=QtGui.QMessageBox.question(None,'Message', "Takczynie?",QtGui.QMessageBox.Yes| QtGui.QMessageBox.No,QtGui.QMessageBox.No) ifreply==QtGui.QMessageBox.Yes: print("YES") elifreply==QtGui.QMessageBox.No: print("NO") else: print("cosinnego?!")
button=QtGui.QPushButton('Nacisnijmnie',win)button.clicked.connect(showDialog)button.resize(button.sizeHint())button.move( 250/2-button.sizeHint().width()/2, 150/2-button.sizeHint().height()/2)
win.show()
#interfejspseudograficznyzużyciemGtk3
importgigi.require_version("Gtk","3.0")fromgi.repositoryimportGtk
window=Gtk.Window(title="HelloWorld")
defshowDialog(caller): dialog=Gtk.MessageDialog(window,0, Gtk.MessageType.QUESTION,Gtk.ButtonsType.YES_NO, "Ważnepytanie!!!") dialog.format_secondary_text("Takczynie?") response=dialog.run() ifresponse==Gtk.ResponseType.YES: print("TAK!!!") elifresponse==Gtk.ResponseType.NO: print("NIE!!!")
###PrzykładPython
###PrzykładPython
else: print("bezodpowiedzi!?") dialog.destroy()
button1=Gtk.Button("Nacisnijmnie")button1.connect("clicked",showDialog)
window.add(button1)
window.show_all()window.connect("delete-event",Gtk.main_quit)Gtk.main()
ProgramowaniesprzętuTypowo programy komputerowe uruchamiane są pod kontrolą jakiegoś systemu operacyjnego, któryodpowiada za realizację sporej części funkcji określonych przez bibliotekę standardową (np. operacjiplikowych, standardowegowejścia iwyjścia) oraz zapewniamożliwość równoczesnegodziałaniawieluprocesów (ich przełączania). Jednak niekiedy zachodzi potrzeba stworzenia programu który będziedziałał bezpośrednio na sprzęcie bez pośrednictwa systemu operacyjnego. Może to mieć miejsce np.wtedy gdy zasoby danej platformy sprzętowej są zbyt ograniczone aby uruchomić na niej systemoperacyjnyinasząaplikacjęlubtworzymysystemoperacyjny.
Przerwania
Przerwanie (żądanie przerwania, IRQ) jest sygnałem powodującym wstrzymanie wykonywaniaaktualnego kodu i wykonanie zdefiniowanej (dla danego przerwania) procedury jego obsługi.Przerwaniamogąbyćzwiązanez:
sygnałemotrzymanymodzewnętrznegoukładu(tzw.przerwaniasprzętowe)-mającenacelunp.poinformowanie o zakończeniu jakiejś operacji wejścia wyjścia, otrzymaniu danych na jakimśinterfejsie,wykonywanym kodem (tzw. przerwania programowe) - zarówno wywołane celowo (np. celemkomunikacjizsystememoperacyjnym),jakteżpojawiającesięnaskuteknietypowych/błędnychdziałań-tzw."wyjątki"(np.dzieleniaprzezzero).
Na wielu architekturach program może wygenerować dowolne z przerwań (także tych związanych zsprzętem,czyteżwyjątków)poprzezwywołaniestosownejinstrukcjiprocesoraktórejargumentemjestnumer przerwania. Generowanie przerwań instrukcją procesora jest wykorzystywane m.in. celemrealizacji wywołań systemowych (czyli wywołań funkcji jądra z poziomu programu użytkownika). Wprzypadku Linuxa na architekturze x86 za wywołania systemowe odpowiada przerwanie o numerze0x80, numer funkcji systemowej musi być uprzednio umieszczony w rejestrze eax, a jej kolejneargumentywrejestrachebx,ecx,edx,edi,esi,ebp;podobniestatusoperacji iwartośćzwracanajestumieszczanawodpowiednichrejestrachprocesora.
Istniejemożliwośćzablokowaniaobsługiwszystkichprzerwańpochodzącychzzewnątrz (zwyjątkiemprzerwańniemaskowanych)stosowanąinstrukcjąprocesora.Obsługaprzerwańprzezprocesorpoleganazidentyfikowaniu(woparciuonumer/źródłoprzerwaniaidanezawartewobszarzepamięciczęstonazywanym tablicą wektorów przerwań) adresu procedury obsługi przerwania i wykonaniu jej wsposóbpodobnydowykonania funkcji,czylizodłożeniemaktualnegostanuprocesoranastos (celemumożliwieniapowrotudoniegopozakończeniuproceduryobsługiprzerwaniawcelukontynuowaniaprzerwanegokodu).Jeżeliproceduraobsługiprzerwaniamainnypoziomuprzywilejowania(np.działanaprawachjądrasystemuoperacyjnego)toprocesormożetakżedokonaćprzełączeniastosu.
Z punktu widzenia wielozadaniowego systemu operacyjnego szczególnie istotne jest przerwaniesprzętowezwiązanezodmierzeniemustalonegoczasu(zwaneprzerwaniemzegarowym),pozwalaononaodebraniekontroliaktualniewykonywanemuprocesowi,przekazaniejejsystemowioperacyjnemuiumożliwieniaprzełączenianainnyproces.
Mikrokontrolery
Programowaniemikrokontrolerów,azwłaszczazwykorzystaniemperyferiówwktóresąwyposażone,dośćznacznieróżnisięodtworzeniaaplikacjidziałającychpodkontroląsystemuoperacyjnego(nawetpomimo użycia tego samego języka programowania – najczęściej C lub C++), a także pomiędzyposzczególnymitypamimikrokontrolerów.Korzystaniezperyferiówoferowanychprzezmikrokontrolerpolega głównie na wykonywaniu odczytu i zapisów do rejestrów zgodnie z dokumentacją danegoukładu oraz obsłudze odpowiednich przerwań. Niekiedy takie surowe operowanie na rejestrachobudowane jest przez funkcji biblioteki wspomagającej programowanie danej platformy, z którychprogramistamożekorzystaćabywczytelniejszysposóbzapisaćwykonywanyalgorytm.
Także proces kompilacji kodu dla takich platform przebiega odmiennie niż przy „normalnym”
programowaniu – bardzo często wykorzystywana jest cross kompilacja, czyli kompilator działa podkontrolą innej architektury niż ta dla której tworzy kod. W związku z tym wykorzystywane są innekompilatorywrazzwłasnymizestawamibibliotekstandardowych(stanowiącetzw.toolchaindladanejplatformy). Bardzo istotne jest też często określenie w opcjach takiego kompilatora szczegółówmikrokontrolera dla którego chcemy zbudować dany kod (typowo toolchain dotyczy całej rodziny, akonkretnymodelmikrontrolera,posiadającykonkretnyzbiórperyferiów,itdokreślanyjestwopcjach).
Przykładowe kody wraz z opisem kompilacji lub plikiem Makefile automatyzującym kompilacje dladwóchchybanajpopularniejszych rodzinmikrokontrolerówudostępniony jestwpostaci repozytoriówgit:
AVR-examples-dla8bitowychmikrokontrolerówAVRSTM32-examples-dla32bitowychmikrokontrolerówSTM32(rdzeńARM)
obsługasprzętuwramachOS
Obsługasprzętuniezawszewiążesięz tworzeniemkodudziałającegobezsystemuoperacyjnego,nawiększychukładachmożedziałaćnormalnysystemoperacyjny(np.LinuxnapłytkachtypuRaspberryPiczyOrangePi).Wtakiejsytuacjiobsługęsprzętumożnazrealizowaćpoprzezwłasnymodułjądrazaniąodpowiedzialnylub(gdytojestmożliwe)poprzezfunkcjeudostępnionedoprzestrzeniużytkownikaprzezsystemoperacyjnyijakąśbibliotekę.Przykłademdrugiegopodejściamożebyćwykorzystywanieplików funkcji operujących na przestrzeni I/O (plik nagłówkowy asm/io.h), funkcji realizującychkomunikację I2C (pliknagłówkowy linux/i2c-dev.h), czy teżbiblioteki libusbpozwalającejnaobsługękomunikacjiUSB.
komunikacjaI2C
#include<unistd.h>#include<fcntl.h>#include<sys/ioctl.h>
#include<linux/i2c-dev.h>#ifndefI2C_FUNC_I2C#include<i2c/smbus.h>#endif
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<errno.h>
//wymaganypakietlibi2c-dev,kompilacja://dlalibi2c-dev<4://gcckomunikacja_I2C.c//dlalibi2c-dev>=4://gcc-li2ckomunikacja_I2C.c
voidhelp(constchar*prog_name){ fprintf(stderr,"USAGE(withoutonchipregisteraddres):\n"); fprintf(stderr,"-read:%si2c_devaddrr-\n",prog_name); fprintf(stderr,"-write:%si2c_devaddrw-data\n",prog_name); fprintf(stderr,"USAGE(withonchipregisteraddres):\n"); fprintf(stderr,"-read:%si2c_devaddrrreg_addr\n",prog_name); fprintf(stderr,"-write:%si2c_devaddrwreg_addrdata\n",prog_name); fprintf(stderr,"\n"); fprintf(stderr,"i2c_dev=/dev/ic2...devicepath\n"); fprintf(stderr,"addr=I2C_devide_address\n"); fprintf(stderr,"reg_addr=register(data)addressinI2Cchip\n"); fprintf(stderr,"data=datatowritetodevice\n");}
intmain(intargc,char*argv[]){ intfd,i2c_addr,reg_addr,res,d; if(argc<4){ help(argv[0]); return1; } //otwarcieurządzenia fd=open(argv[1],O_RDWR); if(fd<0){ fprintf(stderr,"ErroropenI2Cdevicefile(%s):%s\n",argv[1],strerror(errno)); return2;
} //ustawienieadresuslave i2c_addr=strtol(argv[2],NULL,0); res=ioctl(fd,I2C_SLAVE,i2c_addr); if(res<0){ fprintf(stderr,"ERRORsetdeviceaddressto0x%02x:%s\n",i2c_addr,strerror(errno)); return3; } if(argv[3][0]=='r'&&argc==5){//odczyt if(argv[4][0]!='-'){ //jeżelijestpodanytoustawiamyadresrejestrudoodczytu //wartozauważyćżejesttorobionejakoWRITEdourządzeniaI2C reg_addr=strtol(argv[4],NULL,0); res=i2c_smbus_write_byte(fd,reg_addr); if(res<0){ fprintf(stderr,"ERRORwrite(registeraddress)%dtoi2cdevice0x%02xon%s:%s\n",reg_addr return4; } } //czytamydanezurządzenia res=i2c_smbus_read_byte(fd); if(res<0){ fprintf(stderr,"ERRORreadfromi2cdevice0x%02xon%s:%s\n",i2c_addr,argv[1],strerror(errno return5; } printf("0x%02x\n",res); }elseif(argv[3][0]=='w'&&argc==6){//zapis d=strtol(argv[5],NULL,0); if(argv[4][0]!='-'){ //jeżelijestpodanyadresrejestrudozapisutogoużywamyiwykonujemyzapis reg_addr=strtol(argv[4],NULL,0); res=i2c_smbus_write_byte_data(fd,reg_addr,d); if(res<0){ fprintf(stderr,"ERRORwrite%dtoi2cdevice0x%02x,register0x%02xon%s:%s\n",d,i2c_addr return5; } }else{ //wprzeciwnymraziepoprostuzapisujemydanedourządzenia res=i2c_smbus_write_byte(fd,d); if(res<0){ fprintf(stderr,"ERRORwrite%dtoi2cdevice0x%02xon%s:%s\n",d,i2c_addr,argv[1],strerror return5; } } }elseif(argv[3][0]=='R'&&argc==5&&argv[4][0]!='-'){//odczytzrejestrujednąfunkcją reg_addr=strtol(argv[4],NULL,0); res=i2c_smbus_read_byte_data(fd,reg_addr);//odczytzrejestruodanymadresiemożebyćwykonanytakżejednąfunkcją(analogiczniejakzapis) if(res<0){ fprintf(stderr,"ERRORreadfromi2cdevice0x%02x,register0x%02xon%s:%s\n",i2c_addr,reg_addr return5; } printf("0x%02x\n",res); }else{ help(argv[0]); return1; } close(fd);}
Wzorceprojektowe,algorytmy,itpObiektowość
Obiektowośćjestpodejściemdoprogramowaniapolegającymnałączeniudanychipowiązanychznimiprocedur w obiekty. W rezultacie zamiast grupy funkcji operujących na jakiejś strukturze danych i
osobnych instancjach tej struktury (np. napis typu char* i funkcje z rodziny string.h) operuje sięobiektami zawierającymi w sobie dane i posiadającym metody na nich operujące (np. napis typustd::string). Z obiektowością związane są zagadnienia takie jak: określanie interfejsów klasodnoszących się jedynie do kluczowych dla danego zagadnienie elementów i ukrywaniu pozostałychaspektówwewnątrz implementacjiklasy,wydzielaniewspólnychcechobiektówróżnego typudoklasbazowychpoktórychdziedziczą.
Dziedziczenie,polimorfizm,itp
Dziedziczenie jest jednym z mechanizmów pozwalających na konstrukcję klas opisujących bardziejzłożoneobiektyzklasprostszych.
//klasaabstrakcyjna-definiującainterfejsdlajakiejśgrupyobiektów//faktbyciaklasąabstrakcyjnąwynikazniezdefiniowanejmetodywirtualnej//zfaktutegowynikaniemożnośćutworzeniaobiektówbędącychbezpośrednimi//instancjamitakiejklasyclassKsztalt{public: virtualfloatobjetosc()=0; //użycievirtualwymuszawywoływaniemetodyzklasypotomnej //kiedyodwołujemysięprzyużyciuklasybazowej};
//klasydziedziczącapoklasieKsztaltclassKula:publicKsztalt{ floatpromien;public: Kula(floatr){ promien=r; } floatobjetosc(){ return1.25*3.14*promien*promien*promien; }};classSzescian:publicKsztalt{ floatbok;public: Szescian(floata){ bok=a; } floatobjetosc(){ returnbok*bok*bok; }};
structKolor{ charr,g,b;};
classCena{public: Cena(floatc);};
classMaterial{};
//klasadziedziczącapokilkuklasachbazowychstructOpakowanie:publicKsztalt,publicKolor,publicCena{ Ksztalt*ksztalt; Material*material;public: Opakowanie(Ksztalt*k,constKolor&kolor,floatc): //wywołaniekonstruktorówklasybazowej //jawnegodlaCenaikopiującegodlaKolor Cena(c),Kolor(kolor) { //inicjalizacjazmiennejwskaźnikowejksztalt //dziękirozwiązaniuzzmiennąprzechowującąinformacjęokształcie //niemapotrzebytworzeniaróżnychklasOpakowaniedlaróżnychkształtów ksztalt=k; material=0; }
Opakowanie(Ksztalt*k,floatc):
///PrzykładC++
//wywołaniekonstruktoraklasybazowejCena //orazinicjalizacjazmiennychksztaltimaterial Cena(c),ksztalt(k),material(0) { //inicjalizacjapólodziedziczonychpostrukturzeKolor r=0x96;g=0xFF;b=0x03; }
floatobjetosc(){ returnksztalt->objetosc(); }
//jesttoalternatywnawstosunkucododziedziczenia //metodarozszerzaniainterfejsujakiejśklasy //dziedziczenie(wprzypadkudziedziczeniapublic)dodajemetody //klasybazowejbezpośredniodointerfejsuklasydziedziczącej //natomiasttorozwiązaniepozwalanapobranieposzczególnychklas //opisującychzłożonyobiektniezależnieioperowaniunaichinterfejsie Material*getMaterial(){ returnmaterial; }
voidsetMaterial(Material*m){ material=m; }};
Tworzenieirozbudowaobiektówmetodawytwórcza
jesttokreacyjnywzorzecprojektowy(inaczejnazywanywirtualnykonstruktor)realizowanypoprzezutworzenie klasy fabryki z metodą statyczną odpowiedzialną za tworzenie różnych produktów(dziedziczącychpowspólnejklasiebazowej).
Efektem zastosowanie jest ukrycie szczegółów implementacji poszczególnych produktów przezużytkownikiem(korzystaontylkozklasybazowejproduktuifabryki).
#include<iostream>
structProduct{ virtualvoidinfo()=0; virtual~Product(){}};
structProductA:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductA:a,b,c\n"; }};
structProductB:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductB:a,f,g\n"; }};
structProductFactory{ staticProduct*getProduct(conststd::string&type){ if(type=="A") returnnewProductA(); elseif(type=="B") returnnewProductB(); else returnNULL; }};
intmain(intargc,char*argv[]){ std::stringid="A"; if(argc>1&&argv[1][0]=='B') id="B";
///PrzykładC++
Product*p=ProductFactory::getProduct(id); p->info(); deletep;}
fabrykaabstrakcyjna
jest to kreacyjny wzorzec projektowy realizowany poprzez utworzenie klasy fabryki z metodąstatyczną odpowiedzialną za tworzenie różnych typów fabryk dziedziczących po wspólnej klasiebazowej. Klasa bazowa fabryki określa gamę produktów z użyciem klas bazowych produktów, wefekciekażdazfabrykprodukujetakąsamągamęproduktów,aledoichtworzeniamożekorzystaćzspecyficznychdladanejimplementacjifabrykiklasdziedziczącychpoproduktachbazowych.
Efektem zastosowanie jest ukrycie szczegółów implementacji poszczególnych produktów przezużytkownikiem (korzysta on tylko z klasy bazowej produktu i fabryki). W odróżnieniu od metodywytwórczej stosowany jest do produkcji spójnych gam produktów dzięki jednokrotnemu określaniutypu produktów przy tworzeniu fabryki (zamiast niezależnego określania typu każdego produktu).Pozwalatylkorazokreślićużywanytypfabrykiiwytwarzaćproduktuuzyskanąfabrykąkonkretnegotypu, jest to przydatne wtedy gdy konkretna implementacja fabryki jest zależna np. od stosowanejbibliotekilubsystemu.
#include<iostream>
structProduct{ virtualvoidinfo()=0; virtual~Product(){}};
structProductA:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductA:a,b,c\n"; }};
structProductB:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductB:a,f,g\n"; }};
structFactory{ staticFactory*getFactory(conststd::string&type); virtualProduct*getProduct()=0; //fabrykatakamożezłatwościąprodukowaćkilka //różnychproduktów(całąrodzinęproduktów) virtual~Factory(){}};
structFactoryA:publicFactory{ virtualProduct*getProduct(){ returnnewProductA(); }};
structFactoryB:publicFactory{ virtualProduct*getProduct(){ returnnewProductB(); }};
Factory*Factory::getFactory(conststd::string&type){ if(type=="A") returnnewFactoryA(); elseif(type=="B") returnnewFactoryB(); else returnNULL;}
intmain(intargc,char*argv[]){ std::stringid="A"; if(argc>1&&argv[1][0]=='B') id="B";
///PrzykładC++
Factory*f=Factory::getFactory(id); Product*p=f->getProduct(); p->info(); deletep; deletef;}
budowniczy
jest to kreacyjny wzorzec projektowy realizowany poprzez utworzenie klasy kierownikakorzystającego z bazowego interfejsu klasy budowniczego do realizacji jakiegoś algorytmu (częstokonwersji formatów). Użytkownik odpowiedzialny jest za utworzenie konkretnego budowniczego,przekazaniewskaźnikananiegokierownikowi(ewentualniewrazzdanymipotrzebnymidobudowy,np.danymiktóremajązostaćpoddanekonwertowaniu)orazodebraniuwynikuodbudowniczego.
Efektemjestpełneukrycieszczegółówimplementacjiprzedklasąimplementującąkierownika(niewienicoprodukcie,używatylkobazowegobudowniczego).
#include<iostream>
structProduct{ voidinfo(){ std::cout<<"Product:\n"; std::cout<<""<<el1<<"\n"; std::cout<<""<<el2<<"\n"; } voidsetElement1(conststd::string&e){ el1=e; } voidsetElement2(conststd::string&e){ el2=e; }private: std::stringel1,el2;};
structProductBuilder{ virtual~ProductBuilder(){} voidcreateProduct(){ p=newProduct(); } Product*getProduct(){ returnp; } //wtakiejimplementacjinieodebranielub //nieskasowanieproduktuprzezklientabędzie //prowadziłodowyciekówpamięci virtualvoidbuildElement1(conststd::string&d)=0; virtualvoidbuildElement2()=0;protected: Product*p;};
structProductDirector{ voidsetData(conststd::string&d){ this->d=d; } voidsetBuilder(ProductBuilder*b){ this->b=b; } voidcreateProduct(){ b->createProduct(); b->buildElement1(d); b->buildElement2(); }private: ProductBuilder*b; std::stringd;};
///PrzykładC++
structProductBuilderA:publicProductBuilder{ voidbuildElement1(conststd::string&d){ p->setElement1(d+d); }; voidbuildElement2(){ p->setElement2("ab"); };};
structProductBuilderB:publicProductBuilder{ voidbuildElement1(conststd::string&d){ p->setElement1("b"+d); }; voidbuildElement2(){ p->setElement2("bb"); };};
intmain(intargc,char*argv[]){ ProductBuilder*b; if(argc>1&&argv[1][0]=='B') b=newProductBuilderB(); else b=newProductBuilderA(); ProductDirector*d=newProductDirector(); d->setData("x"); d->setBuilder(b); d->createProduct(); Product*p=b->getProduct(); p->info(); deletep; deleted; deleteb;}
singleton
Singleton jest kreacyjnym wzorcem projektowym zapewniającym istnienie tylko jednej instancji(jednego obiektu) klasy go implementującej. Uzyskiwane jest to poprzez ukrycie konstruktorów izastąpienieichmetodąstatycznązwracającązawszetensamobiektdanejklasy.
#include<iostream>
classSingleton{private: //konstruktor,konstruktorkopiującyorazoperator //przypisaniasąprywatneabyuniemożliwićtworzenie //lubkopiowanieobiektówtejklasyzzewnątrz Singleton(); Singleton(constSingleton&){} Singleton&operator=(constSingleton&); //destruktorteżprywatny...dlazabezpieczeniaprzed //możliwościązrobieniadeletenauzyskanymwskaźniku ~Singleton(){} //klasazawieraprywatnystatycznywskaźniknasiebie //(naswojąjedynąinstancję) staticSingleton*objPtr;public: //atakżemetodęsłużącąpobraniutegowskaźnika //(iutworzeniuobiektugdynieistnieje) staticSingleton*getPtr(){ //alternatywniezamiastwskaźnikamożnaużyć //statycznegoobiektutejklasyzadeklarowanego //wewnątrztejfunkcji if(!objPtr) objPtr=newSingleton(); returnobjPtr; }
///PrzykładC++
};
Singleton*Singleton::objPtr=0;
Singleton::Singleton(){ std::cout<<"konstruktorSingleton\n";}
intmain(){ Singleton*a=Singleton::getPtr(); Singleton*b=Singleton::getPtr(); std::cout<<a<<"=="<<b<<"\n";}
dekorator
jest strukturalnymwzorcemprojektowympozwalającymnarozbudowę funkcjonalności jakiejśklasybez ingerencji w nią, realizowany jest poprzez dziedziczenie po wspólnym z obudowywaną klasąinterfejsie i zawieranie w sobie wskaźnika na obudowywaną klasę. Dekorator reimplementujewybranefunkcjeklasyoryginalnejjednakwywołującwnichfunkcjeklasyoryginalnej,copozwalanawielokrotneobudowywaniepierwotnegoobiektu.
#include<iostream>
structProduct{ virtual~Product(){} virtualvoidinfo()=0;};
structProductA:publicProduct{ voidinfo(){ std::cout<<"Product:\n"; std::cout<<"ab\n"; }};
structDecoratorX:publicProduct{ DecoratorX(Product*p){ this->p=p; } voidinfo(){ p->info(); std::cout<<"xx\n"; }protected: Product*p;};
structDecoratorY:publicProduct{ DecoratorY(Product*p){ this->p=p; } voidinfo(){ p->info(); std::cout<<"yy\n"; }protected: Product*p;};
intmain(intargc,char*argv[]){ Product*p=newProductA(); Product*p1=newDecoratorX(p); Product*p2=newDecoratorY(p1); p1->info(); p2->info(); deletep2; deletep1; deletep;}
///PrzykładC++
kompozyt
jest strukturalnym wzorcem projektowym pozwalającym na zapewnienie interfejsu zgodnego zinterfejsemobiektudlagrupyobiektów.
#include<iostream>#include<list>
structProduct{ virtualvoidinfo()=0; virtual~Product(){};};
structProductA:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductA:a,b,c\n"; }};
structProductB:publicProduct{ virtualvoidinfo(){ std::cout<<"ProductB:a,f,g\n"; }};
classProductComposite:publicProduct{public: std::list<Product*>elements; virtualvoidinfo(){ for(autoe:elements) e->info(); } ~ProductComposite(){ for(autoe:elements) deletee; }};
intmain(intargc,char*argv[]){ ProductComposite*pc=newProductComposite(); pc->elements.push_back(newProductA()); pc->elements.push_back(newProductB()); pc->elements.push_back(newProductA()); pc->info(); deletepc;}
Komunikacjamiędzyobiektamilistener
Obserwator (określany też jako listener) jest czynnościowym wzorcem projektowym pozwalającymjednemu obiektowi powiadomić wiele innych obiektów o jakimś zdarzeniu, obiekty te powinny byćuprzedniozarejestrowanewklasiepowiadamiającej jakozainteresowanedanymzdarzeniem).Możebyć teżwykorzystywanydo realizacjiwzorca łańcuchzobowiązańwtedygdypowiadamianeobiektymają / mogą wykonać jakieś operacje i od kodu powrotu funkcji powiadamiającej zależypowiadamianiedalszychobiektów.
#include<iostream>#include<map>
structObserwator{ virtualboolonUpdate(inteventID)=0;};
structObserwowany{
///PrzykładC++
///PrzykładC++
voidaddListener(Obserwator*l,intkey){ //sprawdźczyjestjużzarejestrowany autosubset=listeners.equal_range(key); for(autoiter=subset.first;iter!=subset.second;++iter) if(iter->second==l)return;
//zarejestruj listeners.insert(std::pair<int,Obserwator*>(key,l)); } voidremListener(Obserwator*l){ for(autoiter=listeners.begin();iter!=listeners.end();++iter){ if(iter->second==l){ listeners.erase(iter); return; } } } //klasycznywzorzeclistenera voidcallListenersAll(inteventID){ //mapazapewniawywoływanielistenerówwgkolejnościkluczy for(auto&l:listeners){ l.second->onUpdate(eventID); } } //wzorzeclistenerapołączonyzłańcuchemzobowiązań voidcallListeners(inteventID){ //mapazapewniawywoływanielistenerówwgkolejnościkluczy for(auto&l:listeners){ if(l.second->onUpdate(eventID)) break; } }protected: std::multimap<int,Obserwator*>listeners;};
structObserwatorA:publicObserwator{ virtualboolonUpdate(inteventID){ std::cout<<"ObserwatorAzid="<<eventID<<"\n"; if(eventID==4) returntrue; returnfalse; };};
structObserwatorB:publicObserwator{ virtualboolonUpdate(inteventID){ std::cout<<"ObserwatorBzid="<<eventID<<"\n"; if(eventID==7) returntrue; returnfalse; };};
intmain(intargc,char*argv[]){ Obserwowany*o=newObserwowany(); Obserwator*o1=newObserwatorA(); Obserwator*o2=newObserwatorA(); Obserwator*o3=newObserwatorB(); o->addListener(o1,30); o->addListener(o2,10); o->addListener(o3,20); std::cout<<"callAll:\n"; o->callListenersAll(7); std::cout<<"call:\n"; o->callListeners(7); deleteo; deleteo1; deleteo2;
deleteo3;}
Mediator
jest czynnościowym wzorcem projektowy realizującym przekazywanie wiadomości pomiędzyobiektami poprzez pośrednika, w przypadku nie natychmiastowego wysyłania wiadomości przezmediatorapozwalatakżenarealizacjękolejkiwiadomości/pętlikomunikatów.
#include<iostream>#include<map>
structReceiver{ virtualvoidreceive(std::stringmsg)=0;};
structMediator{ voidaddReceiver(Receiver*l,intkey){ //sprawdźczyjestjużzarejestrowany autosubset=receivers.equal_range(key); for(autoiter=subset.first;iter!=subset.second;++iter) if(iter->second==l)return;
//zarejestruj receivers.insert(std::pair<int,Receiver*>(key,l)); } voidremReceiver(Receiver*l){ for(autoiter=receivers.begin();iter!=receivers.end();++iter){ if(iter->second==l){ receivers.erase(iter); return; } } } boolsend(std::stringmsg,intdstID){ //gdybyzamiastnatychmiastowegowywoływaniareceive()uadresatów //zaimplementowaćgromadzeniewiadomościwjakiejśstrukturze //iosobnąfunkcjęwysyłającąkolejnewiadomościztejstruktury //towzorzectenpozwoliłbynarealizacjękolejkiwiadomości //(pętlikomunikatów) // //strukturaprzechowującazakolejkowanedowysłaniawiadomościmoże //uwzględniaćkolejnośćichodebraniaprzezMediatoralubwartość //priorytetuzawartegowwiadomości(kolejkapriorytetowa) autosubset=receivers.equal_range(dstID); for(auto&iter=subset.first;iter!=subset.second;++iter){ iter->second->receive(msg); } }
protected: std::multimap<int,Receiver*>receivers;};
RegulatorPID
RegulatorPID jest to algorytm regulacji parametruprocesudziałającywpętli sprzężenia zwrotnegoposiadającyczłony:proporcjonalny(P),całkujący(I)iróżniczkujący(D).
Wyjściem algorytmu jest wartość zmiany jakiegoś sygnału sterującego - może być wykorzystanabezpośrednio przy sterowaniu krokowym lub akumulowana celem uzyskania stałej wartości sygnałusterującego.
Wejściemalgorytmujestwartośćmierzona(bądźodrazuróżnicawartościzadanejimierzonej).Jeżelikierunekzmianysterowania jestzgodnyzezmianąwartościmierzonej (zwiększeniewartościsygnałusterującego powoduje zwiększenie wartości mierzonej) to należy odejmować wartość mierzoną odzadanej,wprzeciwnymrazieodzadanejmierzoną.
///PrzykładC++
///PrzykładC++
classPID{ //poprzedniaróżnicamiędzywartościązadanąaotrzymaną //(poprzednibłądregulacji/uchyb) floatlastDiff; //poprzedniawartośćotrzymana(zmiennaprocesu) floatlastVal; //częśćcałkująca,akumulowanapomiędzykrokami floatintegral;public: //nastawa-wartośćzadana floatsetPoint; //wartośćwyjściadlasterowaniakrokowego //(akumulacjawukładzierealizującym) floatoutStep; //wartośćwyjściadlasterowaniasygnałem floatoutValue; //parametryregulatoraPID floatKp,Ki,Kd; //limitywartościsterowanej floatoutValueMin,outValueMax; //konstruktor-inicjalizacjaparametrów PID( floatinitVal,floatsp, floatkp,floatki,floatkd,floatmin,floatmax ): lastDiff(0),lastVal(initVal),integral(0), setPoint(sp),outStep(0),outValue(0), Kp(kp),Ki(ki),Kd(kd), outValueMin(min),outValueMax(max) {} intdoStep(floatinputVal,floatstepTime){ //obliczmyaktualnybłądregulacji //(napodstawieodczytanejwartościwejściowej) floatdiff=setPoint-inputVal; //wyłączamyregulacjęgdyprowadziłbydoprzesterowania if(outValue>outValueMax&&diff>0) return1; if(outValue<outValueMin&&diff<0) return-1; //całkowanieprzybliżamyjakojakosumapóltrapezów integral+=(diff+lastDiff)/2*stepTime; //różniczkowanieprzybliżamyjakotangensnachylenia //prostejpomiędzypoprzednimkrokiemaobecnym //celemzłagodzeniaodpowiedzinazmianywartościzadanej //różniczkujemysygnałwejściowy floatderivative=-(inputVal-lastVal)/stepTime; //aniebłądregulacji:derivative=(diff-lastDiff)/stepTime; //obliczeniewartościsygnałusterującegonapodstawietegokroku outStep=Kp*diff+Ki*integral+Kd*derivative; //akumulacjasygnałusterującego outValue+=outStep; //zapamiętanieaktualnegobłęduregulacji //jakopoprzednidlanastępnegokroku lastDiff=diff; //zapamiętanieaktualnejwartościwejściowej //jakopoprzedniejdlanastępnegokroku lastVal=inputVal; return0; }};
intmain(){ PIDpid(readInput(),21.0,1.0,0.0,0.0,-100.0,100.0); //okresdziałaniaalgorytmu[us] unsignedintstepTime=250000; //pętlaalgorytmu while(1){ //odczytwejścia floatcurVal=readInput(); //obliczeniewartościsterującejzużyciemPID pid.doStep(curVal,stepTime); //wystawieniewartościsterującej setOutput(pid.outValue); //odczekaniedonastępnegokroku usleep(stepTime); }}
SiecikomputeroweSieć komputerowa jest to zbiór hostów (urządzeń wykorzystujących sieć do komunikacji, takich jakkomputery,drukarkisieciowe,...)orazinfrastrukturysieciowej(okablowanie,urządzaniapośredniczącewkomunikacji).Wprzypadkubardziejabstrakcyjnegopatrzenianazagadnieniasieciowe(właśnieodstronyprotokołów wyższych warstw niż sprzętowa - takich jak IP) na sieć można patrzeć tylko jako na zbiórhostów (posiadających identyfikujące je numery). Dla funkcjonowania sieci konieczne jest zapewnieniedobrzeokreślonychzasad jejdziałania -właśniezbiorami takichzasadwymiany informacji sąprotokołysieciowe.
Siecikomputerowedziałająnazasadzieprzesyłaniainformacjiwpostaciporcji,zktórychkażdaposiadaco najmniej informację o adresie odbiorcy (zwykle też nadawcy), nazywanych ramkami lub pakietami.Kierowaniepakietówwodpowiedniemiejsceodbywasięnapodstawieadresupakietuiniejestzwiązanezfizycznymzestawianiemłączapomiędzynadawcąaodbiorcą-każdypakietjestkierowanyniezależnie,awramachpojedynczego łącza(kanałutransmisji)mogąbyćprzekazywanepakietyadresowanedoróżnychodbiorców.Nazywanejesttokomutacjąpakietów,wodróżnieniuodkomutacji łącza(którawystępowałanp.wklasycznej,analogowejtelefonii,gdzieprzekaźnikiwcentralachdokonywałyzestawieniapołączeńelektrycznychmiędzydwomaaparatamitelefonicznymi).
Komunikacjasieciowatypowoposiadastrukturęwarstwową.WmodeluOSIwyróżniasię7warstw:fizyczną (pierwszą) definiującą aspekty związane z fizycznym przesyłem sygnału takie jakczęstotliwościradiowe,poziomynapięć,etc.;określasposóbtransmisjikolejnychbajtówłącza danych (drugą) definiującą aspekty związane z formatem ramki, protokoły ustalania zasaddostępudomediumtransmisyjnego,itd.;określasposóbtransmisjiporcjidanychpomiędzyhostamiwjednejsiecisieciową (trzecią) definiującą aspekty związane z formatem pakietu, adresacją i zasady routinguumożliwiającezapewnieniełącznościpomiędzyróżnymisieciami;określasposobytransmisjiporcjidanychpomiędzysieciamitransportową (czwartą) odpowiedzialną za podział strumienia na porcje informacji, kontrolę nadpoprawnościątransmisji,adresacjęusługwramachhostasesji(piątą)prezentacji(szóstą)aplikacji(siódmą)
WmodeluTCP/IPwyróżniasię4warstwy:Dostępudosieci-obejmującąwarstwy1i2modeluOSIInternetu-obejmującąwarstwę3modeluOSITransportową-obejmującąwarstwę4modeluOSIAplikacji-obejmującąwarstwy5,6i7modeluOSI
ZpunktuwidzeniamodeluTCP/IPmożnapowiedziećoenkapsulacjidanychkolejnychwarstwwramachwarstwy niższej, czyli "surowe" dane (np. strona HTML) obudowywane są strukturą opisywaną przezwarstwęaplikacji (np.nagłówkamiHTTP), następnie całość taumieszczana jestwpoludanychpakietuwarstwy transportowej (np. TCP), ten z kolei w polu danych pakietu IP (warstwy sieciowej), na koniecpakiet IP jestumieszczanywpoludanych ramkiwarstwydostępudosieci (np. ramkiethernetowej).W
ramachpodróżyprzezkolejnesiecipakietIPjestwyjmowanyiwkładanywkolejneramkiwarstwydostępudo sieci, na ogół tylko z niewielkimi ingerencjami w zawartość tego pakietu (prawie zawsze niedochodzącymidopoladanychpakietuTCPlubdatagramuUDP,czyliniewykraczającymipozawarstwę4OSI).
WarstwasprzętowaOdstronysprzętowejsiećskładaz:
hostówstanowiącychnadawcówiodbiorcówinformacjiurządzeń sieciowych pośredniczących w ich przekazywaniu, takich jak nadajniki, switche,mediakonwerteryokablowaniamiedzianegobądźświatłowodowego(jeżeliniejestsieciąbezprzewodową)
Ethernet
W przypadku sieci w standardzie Ethernet stosowane są 48 bitowe adresy MAC (pierwsza częśćidentyfikuje producenta karty) oraz wspólny dla wszystkich odmian (przewodowych ibezprzewodowych) format ramki (określający położenie w ramce adresów, informacji dodatkowychorazdanych).Pakietyprotokołuwarstwywyższej(np.pakietyIPwrazichstrukturązawierającąadresyitd)zpunktuwidzeniaramkiethernetowejsądanymi,wktóre tawarstwaniewnika.DomapowaniaadresówIPnaadresyMACwykorzystywanyjestprotokółARP(dlaIPv4)lubNeighborDiscovery(dlaIPv6)-odbywasiętopoprzezwysłanieramkiethernetowejnaadresrozgłoszeniowy(odbieranyprzezwszystkiehosty)zpytaniemotojakiMACadresmahostopodanymnumerzeIP.
Sieć ethernetowa typowo posiada strukturę wielokrotnej gwiazdy (drzewa), w węzłach którejstosowane są switche.Kierują one ramki do odpowiednichgałęzi napodstawie adresudocelowego iwpisów w tablicy adresów MAC, utworzonej w oparciu o źródłowe nadawców przechodzących przezdanyswitch ramek.Wprzypadkugdyadresudocelowegoniemaw tablicy ramkakierowana jestnawszystkieporty switcha zwyjątkiem tegona którymzostała odebrana.W taki sposób zawsze są teżprzesyłaneramkiwysyłanenaadresrozgłoszeniowy(bradcast).
Ethernet pozwala na wirtualne podzielenie pojedynczej sieci lokalnej na wiele niezależnych (niekomunikujących się ze sobą w warstwie ethernetu) sieci, nazywanych VLAN. Działanie tegomechanizmuopierasięnazastosowaniuzarządzalnychswitchy,któreprogramowomogąbyćdzielonena części zapewniające separację ruchu poszczególnych VLANów. Ponadto wybrane porty takiegoswitchamogąbyćprzypisanedoróżnychczęści(celemudostępnieniadoinnegoswitchalubhostakilkusieciwirtualnych),wtakimprzypadkudoramekethernetowychwysyłanychtymportemdodawanajestinformacjadoktóregoVLANunależą(dwubajtowynumer),awprzypadkuramekotrzymywanychnapodstawie tegonumeruodbywasię ichkierowaniedoodpowiedniej "części"przełącznika (mówimyoVLANachtagowanych).Możliwe jestaby jedenwybranyVLANna takimporciebyłnie tagowany (dojegoramekniebędziedodawanynumer,aotrzymywanepakietybeznumerubędąkierowanedoniego.
Ethernet pozwala również na grupowanie kilku portów w jeden port wirtualny (tzw port trunking /bonding)celemzwiększeniaprzepustowościlubniezawodnościłącza.Adziękizastosowaniuwróżnychtypach sieci ethernet tego samego formatu ramki możliwe jest też stosunkowo proste zmienianiemediumtransmisyjnego(np.zkablamiedzianegonaświatłowód)zużyciemmedia-konwerterów.
WprzewodowychsieciachEthernetwykrywaniemzajętościmediumtransmisyjnegoorazwykrywaniemkolizji zajmuje się protokół CSMA/CD (Carrier Sense Multiple Access with Collision Detection -wielodostęp z rozpoznawaniem stanu kanału oraz wykrywaniem kolizji). Przed rozpoczęciemnadawaniastacjamusisprawdzićczymediumjestwolne,jeżelitakmożezacząćnadawać,jeżelidwiestacje zaczną nadawać równocześnie zostaje to wykryte, obie przerywają nadawanie i wznawiają polosowymczasie. Jednak zewzględuna stosowaniegłówniepołączeńpunkt-punkt full-duplex (osobneprzewodydonadawaniaiosobnedoodbioru),coograniczatzw.domenękolizjidopojedynczegohosta,protokółtennieodgrywaobecnieszczególnieistotnejroli.
SieciIPProtokół IP (InternetProtocol)odpowiedzialny jestprzedewszystkimza sposóbadresacjihostóworazreguły komutacji pakietów (routing). Jest onwspomaganyprzez kolejnyprotokół z tej rodziny - ICMP(InternetControlMessageProtocol),któregozadaniemjestprzekazywanieinformacjikontrolnychnp.onieosiągalności hosta docelowego, odrzuceniu przetwarzania pakietu ze względu na zbyt dużą liczbęskoków (gdy wartość pola TTL z nagłówka IP wyniesie zero) a także pingi (zarówno żądanie jak iodpowiedź).
Adresacjairouting
Adresyhostów(nazywaneadresamiIP)sąto32-bitowe(wIPv4)lub128-bitowe(wIPv6)liczby.
AdresyIPv4zapisywanesąnajczęściejwnotacjikropkowo-dziesiętnej,gdziekażdybajt(ciąg8bitów)zapisywany jest jako liczbadziesiętnarozdzielanakropkąodpozostałych.AdresyIPv6zapisywanesązazwyczajwnotacji dwukropokowej, polegającej na zapisywaniu16bitowych części adresu liczbami
szesnastkowymi oddzielanymi dwukropkiem, dodatkowo jeden ciąg zer (o długości będącejwielokrotnością16bitów)możebyćskompresowany(pominięty)codajewzapisiedwadwukropki::.
Długośćprefixuimaska
Adresyhostówgrupujesięwadresysieci,bazującnajednakowym(bitowo)początkutakiegoadresu(zwanym adresem sieci lub prefixem). Ilość bitów stanowiących adres sieci w danym adresie IPnazywana jestdługościąprefixu izapisywana jestzazwyczajpoukośniku.Np.zapis2001:db8::a17/48oznaczażepierwsze48bitystanowiąadressieciakolejne128-48=80bitówstanowiadreshostawtejsieci.
Długość prefixu jednoznacznie określa maskę danej podsieci, czyli liczbę odpowiadającą długościadresu(32bitylub128bitów),złożonązciągujedynekodługościprefixuorazciąguzer(odługościadresu hosta). W przypadku IPv4 spotykane jest także podawanie maski sieci w notacji kropkowo-dziesiętnejzamiastdługościprefixu.
Siećmożezostaćpodzielonanamniejszesieci(zwiększąwartościąprefixu),jakteżgrupasiecimożezostaćzagregowanawjednąwiększą(2nraza)sieć(zprefixemmniejszymon).Agregacjahostówisieci w większe całości jest wykorzystywana w mechanizmach routingu, co pozwala na redukcjęwielkościtablicroutingowych.
Przynależnośćdosieci
Adressiecizapisujesiętypowozwyzerowanymibitamistanowiącymiadreshosta(czylipodokonaniubitowego and z maską danej sieci) oraz podaną informacją o długości prefixu, dla powyższegoprzykładu będzie to 2001:db8::/48. Informacja taka jest wystarczająca do sprawdzenia czy dowolnyinnyadresIPnależydotejsieciczynie.
#adresacjaIPv6
fromipaddressimport*
a1=IPv6Address("2001:0db8::17:15")aa1=int(a1)print("adressIPv6jest128bitowąliczbącałkowitąnp.:"+str(a1)+"=="+hex(aa1))
n0=IPv6Network("::/112");m1=n0.netmaskmm1=int(m1)p1=n0.prefixlen
print("MaskapodsieciIPv6jest128bitowąliczbącałkowitąnp.:"+str(m1)+"=="+hex(mm1))print("Jakożemaskajestliczbą,którazapisanabinarnie,zawszezawieraciągłyciągbitów")print("owartości1,aponimciągłyciągbitówowartości0(mogąbyćzerowejdługości),to")print("częstostosowanyjestzapispolegającynapodawaniudługościprefiksu:/"+str(p1))print("jesttoilośćbitówowartości1wmasce,czyliimwiększyprefixtymmniejszasieć.")
n1=IPv6Network("2001:0db8::17:15/112",strict=False);nn1=int(n1.network_address)
print("Abyobliczyćadressieci(czyliwspólnądlawszystkichhostówwdanejsieciczęść")print("adresuIP)należywykonaćbinarnyANDpomiędzyadresemIPhostaamaskąpodsieci.")print("Dlapowyższegoprzykładu:")print(hex(mm1&aa1)+"=="+str(n1)+"=="+hex(nn1))
#abysprawdzićczyadresIPnależydodanejsiecitrzebaobliczyćadressiecitegohosta#woparciuomaskęsieciktórąsprawdzamydefsprawdzSiec(n,a): nn=int(a)&int(n.netmask) ifnn==int(n.network_address): print(str(a)+"należydosieci"+str(n)) else: print(str(a)+"NIEnależydosieci"+str(n))
sprawdzSiec(n1,IPv6Address("2001:0db8::17:ab13"))sprawdzSiec(n1,IPv6Address("2001:0db8::13:a"))
#adresacjaIPv4
fromipaddressimport*
a1=IPv4Address("192.168.34.17")aa1=int(a1)
###PrzykładPython
###PrzykładPython
print("adressIPv4jest32bitowąliczbącałkowitąnp.:"+str(a1)+"=="+hex(aa1))
n0=IPv4Network("0.0.0.0/25");m1=n0.netmaskmm1=int(m1)p1=n0.prefixlen
print("MaskapodsieciIPv4jest32bitowąliczbącałkowitąnp.:"+str(m1)+"=="+hex(mm1))print("Jakożemaskajestliczbą,którazapisanabinarnie,zawszezawieraciągłyciągbitów")print("owartości1,aponimciągłyciągbitówowartości0(mogąbyćzerowejdługości),to")print("częstostosowanyjestzapispolegającynapodawaniudługościprefiksu:/"+str(p1))print("jesttoilośćbitówowartości1wmasce,czyliimwiększyprefixtymmniejszasieć.")
n1=IPv4Network("192.168.34.17/25",strict=False);nn1=int(n1.network_address)
print("Abyobliczyćadressieci(czyliwspólnądlawszystkichhostówwdanejsieciczęść")print("adresuIP)należywykonaćbinarnyANDpomiędzyadresemIPhostaamaskąpodsieci.")print("Dlapowyższegoprzykładu:")print(hex(mm1&aa1)+"=="+str(n1)+"=="+hex(nn1))
#abysprawdzićczyadresIPnależydodanejsiecitrzebaobliczyćadressiecitegohosta#woparciuomaskęsieciktórąsprawdzamydefsprawdzSiec(n,a): nn=int(a)&int(n.netmask) ifnn==int(n.network_address): print(str(a)+"należydosieci"+str(n)) else: print(str(a)+"NIEnależydosieci"+str(n))
sprawdzSiec(n1,IPv4Address("192.168.34.13"))sprawdzSiec(n1,IPv4Address("192.168.34.199"))
Routing
Router kieruje każdy z pakietów do kolejnego routera lub bezpośrednio do hosta docelowego napodstawie jego adresu docelowego i tablicy routingu. Tablica taka zawiera adresy sieci wraz zadresami następnych routerów do nich prowadzących bądź wskazaniem lokalnego interfejsusieciowego poprzez który powinny być osiągalne hosty z danej sieci. W tym celu korzysta zsprawdzania przynależności adresu do sieci, w celu ustalenia adresu następnego routera i/lubinterfejsusieciowegonaktórymazostaćprzekazanypakiet.
Tablica przeglądana jest od wpisów najbardziej precyzyjnych, czyli z największym prefixem dowpisównajbardziejogólnych(ostatnimwpisemjestnaogółtrasadomyślnaczylisieć::/0dlaIPv6lub0.0.0.0/0 dla IPv4). Dzięki czemu jeżeli kilka wpisów (sieci) z tablicy routingu pasuje do adresudocelowegoznagłówkapakietu,wybieranyjestwpisnajbardziejprecyzyjny(onajdłuższymprefixie),apasującadokażdegoadresutrasadomyślnawybieranajesttylkogdyniemażadnejlepszej.Możesięzdarzyćżekilkawpisów (nawetz tąsamąmaską)pasujedoadresudocelowegohosta,w takiejsytuacjidowyboruścieżkiużywanesąinnedaneztablicyroutingu(takiejakmetryka).
Tablice routingu mogą zawierać wpisy dodawane statycznie (wpisane do konfiguracji danegourządzenia), jak też wpisy dodawane dynamicznie w oparciu o protokołu wymiany informacjiroutingowych (protokoły routingu) takie jak: IGRP, OSPF, BGP. Protokoły routingu dynamicznegomogąbyćwykorzystywanem.in.dorozkładaniaobciążenianaróżnełącza,zapewnieniaredundancjiłącz,blokowaniaataków(D)DoS.
Takżekażdyzhostówmatabliceroutingu,typowoskładasięzdwóchpozycji–trasydosiecilokalnej(tej sieci z której adres posiada dany host) wskazującej bezpośrednio na urządzenie sieciowe oraztrasy domyślnej wskazującej na router zapewniający dostęp do innych sieci, nazywany bramką(gateway).Jeżelirouternieposiadaadresuwtejsamejsiecicohostkoniecznajestdodatkowatrasawskazującapoprzezjakieurządzeniedostępnyjestrouterdomyślny.
Opróczopisanegopowyżej routinguunicastowego (kierowaniado jednegoodbiorcy) realizowanesątakżetransmisje:
anycast – do dowolnego / najbliższego hosta o danym adresie; zasadniczo jest to transmisjaunicast, tyle żeadresdocelowynie jestunikalnywskaliglobalneja różne routerykieruje tepakietydoróżnychhostówdocelowych(typowowybierającnajbliższytakihost)multicast – do grupy hostów, w tym wypadku (multicastowy) adres IP identyfikuje "kanałnadawczy"anieunikalnyhostdocelowybroadcast – do wszystkich hostów (w ramach danej sieci – nie są routowne), transmisjerozgłoszeniowe można traktować jako szczególny przypadek transmisji multicastowych wktórychgrupamulticastowaobejmujewszystkiehosty(można jezastąpićtakimitransmisjami
multicastowymi)
Klient-serwer
WoparciuoprotokółIPdziałająprotokoływarstwytransportowejtakie jakUDP,TCP,czyteż(mniejznane protokoły czasu rzeczywistego, transmisji strumieniowych): RTP, RTCP i SCTP. Najprostszymprotokołem warstwy transmisji wydaje się być UDP, protokół ten umożliwia przesłanie informacjipomiędzydwomahostamiIPiniekontrolujeontegoczyzostałaonaprzesłanapoprawnie.NatomiastTCP kontroluje to czy przesłana informacja dotarła do adresata i nie została uszkodzona, a wprzypadkuproblemówinformacjawysyłanajestponownie.TCPwzwiązkuztymwprzeciwieństwiedoUDP musi otworzyć połączenie i wykorzystywać je do kontroli poprawności przesłania informacji,wymagazatemprzesłaniawiększej liczbypakietów(comożeprowadzićdopewnychopóźnieńitp).Wzwiązku z tym TCP używany jest tam gdzie konieczna jest kontrola poprawności transmisji (orazponownewysłaniezgubionegopakietu),UDPtamgdzieniejesttopotrzebne(aliczysięczas).
Dodatkowo zarówno UDP jak i TCP na każdym z hostów wyróżniają numeryczny identyfikator dlaaplikacji/procesu/usługibędącegoodbiorcączyteżnadawcąinformacjizwanynumeremportu.
RTP często jest zaliczany jest do warstwy transportowej gdyż działa poniżej typowych protokołówwarstwyaplikacji, jednakdanektóre opisująnie są informacjami systemowymi/sieciowymi awłaśnieaplikacyjnymi, ponadto działa on powyżej protokołów transportowych (zazwyczaj nad UDP). Możeprzenosićw jednej sesji kilka strumieni, ale zazwyczaj dla każdego strumienia tworzona jest osobnasesja(zestawportów).Protokółtenumożliwiaidentyfikacjęzawartościpakietu,identyfikacjękolejnościpakietów w strumieniu. Pozwala także na przepuszczanie ruchu przez mostki maskujące oryginalneadresy,zmieniającemedium,replikującestrumień (replikowanyunicast,którywydajesiębyćbardzodobrym rozwiązaniem gdy z jakiś powodów multicast nie może zadziałać), czy też nawet łączącestrumieniezkilkuźródeł.WspółpracującyznimRTCPsłużydoprzesyłaniaraportówzinformacjamiostratach, opóźnieniach itp oraz wzajemnej synchronizacji mediów pomiędzy strumieniami - np.synchronizacjiaudiozwideo).
Popularneusługi
Wramachsiecimogąbyćrealizowaneróżneusługiwoparciuoróżneprotokoływarstwyaplikacyjnej.Standardowe usługi posiadają zdefiniowane domyślne adresy portów dla swoich protokołów. Wśródusługiprotokołówsieciowychnależywymienićprzynajmniej:
DNS (Domain Name System) - odpowiedzialny za system mapujący nazwy alfanumerycznehostównaadresyIP.mechanizmy auto konfiguracji hostów - DHCP, rozgłaszanie informacji routingowej poprzezICMPv6(protokółwarstwy3)WWW-udostępnianietreścizużyciemprotokołuHTTPpocztęelektroniczną-przesyłaniewiadomości(protokołySMTP,IMAP,POP)komunikacjęnatychmiastowąitelefonięIP(protokołySIP,XMPP,IAX)SSH-zdalny,szyfrowanydostępdosystemówIT,przesyłplikóworaztunelowanieinnychusług
Nauwagęzasługuje faktżewiększośćzwymienionychprotokołówwarstwyaplikacyjnej toprotokołytekstowe(istotnewyjątkistanowiąDNS,DHCPiSSH).
DomainNameSystem
DNS umożliwia mapowanie nazwy na adres IP (lub wiele adresów IP) oraz przechowywaniedodatkowychinformacjinatematdomenyiznajdującychsięwniejusług.Domenyposiadająbudowęhierarchiczną/drzewiastą:
precyzjarośnieodprawejdolewejkolejnepoziomyoddzielanesąkropkaminajwyższym poziomem jest kropka będąca ostatnim znakiem w pełnej nazwie domenowej (np.ciekawi.icm.edu.pl.),którąnajczęściejpomijasięwzapisiehierarchia ta jest niezależna od hierarchii routingu i wynika z faktu posiadania/użytkowaniadanej(pod)domeny)
RealizacjaodpowiedzinazapytanieDNSwyglądanastępująco:
1. host kieruje zapytanie do określonego w jego konfiguracji serwera "rozwijającego" DNS (DNSresolver),
2. serwertakisprawdzawswojejpamięcipodręcznejczyznaodpowiedźnatozapytanie(iniejestonaprzeterminowana-nieupłynąłczasTTLododnalezienia),jeżeliniemajejwswojejpamięcito
3. serwer taki znaadresygłównychserwerówDNS (root serwerów) zawierających informacjenatematserwerówobsługującychdomenynajwyższegorzęduikierujedojednegoznichzapytanieoserwerobsługującyskrajnieprawączęśćadresu(np..org),
klient serwer rozwijający DNS (resolver)
root serwer DNS
ns- cc1 lub ns- cc2
ns- bb1 lub ns- bb2
zapytanie o rekord A (IPv4)dla aa. bb. cc. (1)
odpowiedź: aa. bb. cc.ma IPv4 x. y. z. q (8)
zapytanie o cc. (2)
cc. ma NS: ns- cc1 i ns- cc2 (3)
zapytanie o bb. cc. (4)
bb. cc. ma NS: ns- bb1 i ns- bb2 (5)
zapytanie o aa. bb. cc. (6)
aa. bb. cc. ma IPv4: x. y. z. q (7)
(X) oznacza kolejność wykonywanych operacj i. Przed wykonaniem zapytania resolver sprawdzaczy nie posiada w swoim cache zapamiętanej (i nie przeterminowanej) odpowiedzi na to zapytanie.
4. do otrzymanegoserwera kierowane jestzapytanie o większączęść adresu (np.eu.org),
5. itd. aż do uzyskaniaodpowiedzi o pytanyadres
DNSprzechowujeinformacjew postaci rekordówmających określony typ (wwiększości przypadków dladanej nazwy domenowejmoże być zdefiniowanychwielerekordów,tegosamegolub innych typów). Wśródnajważniejszych typówrekordównależywymienić:
NS – informacja oserwerachobsługującychDNSdanejdomenyA–mapowanienazwynaadresIPv4AAAA–mapowanienazwynaadresIPv6MX–informacjaoserwerachobsługującychpocztędanejdomenySRV– informacjeohościeświadczącymusługę(usługaokreślana jestwnazwiedomenyoktórąpytamy)PTR – mapowanie adresów IP na nazwy domenowe, realizowane w specjalnym drzewie in-addr.arpa (dlaIPv4) lubip6.arpa (IPv6),gdzieadresIPzapisywanyjestwodwróconejkolejnościpobajciedlaIPv4lubcyfrzeszesnastkowejdlaIPv6(zobaczwynikpoleceniahostzadresemIPv4iIPv6)TXT–informacjedodatkowe(np.jakieserwerypocztowe,sąupoważnionedowysyłaniapocztyztejdomeny)SOA–informacjepodstawoweostrefieopisującejdomenęCNAME – alias na inną domenę (domena którą aliasujemy nie może mieć innych wpisów, nawetSOA)
Translacjaadresów
Routeryopróczzwykłegokierowaniapakietównaodpowiedniełącze,mogątakżemodyfikowaćadresyIP i numery portów. Mechanizm ten określany jest mianem translacji adresów sieciowych (NetworkAddressTranslation).Modyfikowaniumogąulegać zarówno źródłowe (SNAT) jak i docelowe (DNAT)adresyIP,jakteżnumeryportówprotokołówwarstwytransportowej(takichjakTCP,czyUDP).
Translacjamożeodbywaćsięwoparciuostałereguły(danyadres,portlubzestawadres+portzawszemapowanyjestnatakiesamewartości)jakteżwsposóbdynamiczny,gdziemapowanieodbywasięnp.na grupę adresów lub pojedynczy adres i dynamicznie dobierane porty. Dynamiczne mapowaniewymaga od routera śledzenia przechodzących przez niego połączeń i ich stanu, celem umożliwieniaprzekazaniapakietuzodpowiedziąorazzwolnieniamapowaniapozakończeniupołączeniaTCP.
Filtracjapakietów
Względybezpieczeństwaczęstowymuszają filtracjęruchusieciowegodocierającegododanegohostalub przechodzącego przez router. Filtracja taka może odbywać się zarówno w oparciu o dane znagłówkówIP(np.adresyźródłoweidocelowe),daneznagłówkówwarstwytransportowej(np.numeryportówTCPlubUDP),jakrównieżinformacjęzsystemuśledzeniapołączeńczyteżzawartośćsamegopakietu.
TunelowanieiVPN
Możliwa jest enkapsulacja pakietów IP w pakietach innych protokołów (w szczególności także IP).PozwalatonarealizacjęróżnegorodzajutuneliIP.PrzykłademtakiegotunelujestVPNzapewniającyszyfrowanydostęp(wwarstwietrzeciej-IPlubnawetwwarstwiedrugiej-LAN)dojakiejśinnejsieci.
Multicast
Multicastjesttransmisjąjedendowielu,pozwalającąnauniknięciepowielaniaidentycznychpakietów(różniącychsiętylkoadresemodbiorcy).Metodatajestużytecznanp.przystreaminguaudio-videona
żywo.MulticastowyadresIPidentyfikujedynamiczną(mogącązmieniaćsięwczasie)grupęodbiorcówi jest on przydzielany danej transmisji przez jej nadawcę, a nie przyznawany administracyjniekonkretnemu odbiorcy. W związku z tym często wszystkie pakiety adresowane do danej grupymulticastowej(mającetakisammulticastowyadresdocelowy)pochodząodtegosamegohosta(awięcmają taki sam unicastowy adres źródłowy). Zależność ta została wykorzystana w source-specificmulticast, który eliminuje problem przydzielania adresów multicastowych nadawcom – dowolnegoadresumulticastowegozpuliprzeznaczonejnapotrzebysource-specificmulticastmożeużyćkażdy,akanał multicastowy (grupa odbiorców) identyfikowana jest w oparciu o dwa adresy (unicastowynadawcyimulticastowyodbiorcy).
W celu obsłużenia transmisji multicastowych router musi posiadać informacje o aktualnie"zasubskrybowanych" przez jego klientów transmisjach multicastowych. Posiadając takie dane (czyliadres multicastowy na który kierowane są pakiety danej transmisji i ewentualnie unicastowy adresźródłowy z którego są wysyłane) może on pozyskać stosowne transmisje od routerów z którymi jestpołączonyiprzekazaćjeswoimklientom.Dopoinformowaniarouteraożądaniudostarczeniatransmisjimulticastowej (a także do przekazania informacji o zakończeniu odbioru takiej transmisji) hostywykorzystują protokół Internet Group Management Protocol (dla IPv4) lub Multicast ListenerDiscovery(dlaIPv6).Celemobsługizaprzestaniatransmisjigdyhostniepoinformowałozakończeniuodbioru, routerzwykorzystaniem tychprotokołówcopewienczaszadajepytanieczynadal sąhostyzainteresowanedanatransmisją.
QualityofService
QoSsątotechnikigwarantujące jakośćusługi.NajczęściejstosowanątechnikązaliczanądoQoSjestdynamicznypodziałprzepustowościłączazwykorzystaniemalgorytmówtakichjak:HTB(HierarchicalTokenBucket),CBQ(ClassBasedQueueing).NiejesttojednakprawdziwyQoS,gdyżmechanizmyteto coś więcej niż tylko prosty podział pasma. O QoS'ie możemy zaczynać mówić gdy systemkolejkowaniauwzględniapriorytetydlapewnychtypówruchu(m.in.napodstawiepolaToS-Typeofservice).Kolejkipriorytetowemogąbyćrealizowanejakowagowe-cykliczniezkażdejklasywysyłamyproporcjonalnie do wagi, lub bez-wagowy (klasa ważniejsza może zagłodzić klasy o mniejszympriorytecie, gdyż brany jest z ważniejszej dopóki są lub nie pojawią się jeszcze ważniejsze). IstniejądwiepodstawowearchitekturysystemówQoS:
DiffServ - nie ma ścisłych gwarancji dla jakiegokolwiek strumienia, na brzegu użytkowniknegocjujeSLAiruchjestkontrolowanypodwzględemtegoSLA(m.in.ustawianieikontrolapolaToS).Możewystępowaćtakżezarządcapasma(BandwidthBroker),zktórymkliencikomunikująsię przy pomocy protokołu RSVP (Resource Reservation Protocol) i negocjują z nim kontraktySLA, natomiast sam BB dokonuje rezerwacji zasobów w routerach i kontroluje ich stan(zazwyczajzwykorzystaniemprotokołuCommonOpenPolicyService).IntServ-odbiorcawoparciuoinformacjeuzyskaneodnadawcynatematparametrówtransmisjidokonuje rezerwacji zasobów w wszystkich routerach na ścieżce łączącej go z nadawcą(wykorzystuje do tego protokół RSVP), każdy z routerów decyduje czy może spełnić tewymagania(gdyjedenniemożecałaoperacjanieudajesię).Każdystrumieńnegocjowanyjestindywidualnie, poprzez mechanizm Addmision Control (podawane są specyfikacje filtru - jakidentyfikowaćtenruch,specyfikacjeprzepływu,itd),ponadtoinformacjeorezerwacjimusząbyćokresowoodnawiane.Wyróżniasięklasyruchu:BestEffort(standardowa),GuaranteedService(gwarancjadostępnościpasmaiopóźnienia),ControlLoadService(zapewniamymałoobciążonykanał,alebezgwarancji).
SystemyoperacyjneCorobisystemoperacyjny?
System operacyjny jest oprogramowaniem odpowiedzialnym za zarządzanie zasobami systemukomputerowego(sprzętem,alenietylko)orazuruchomionyminanimaplikacjami.Donajistotniejszychzadańsystemuoperacyjnegozaliczasiępodziałczasuprocesoraiszeregowaniezadańorazzarządzaniepamięcią - w szczególności obsługa pamięci wirtualnej, najczęściej z wykorzystaniem mechanizmustronicowania.
Oprócz tego system zajmuje się także zarządzaniem plikami, wejściem/wyjściem (najczęściej jest onorealizowane w oparciu o przerwania (IRQ), ale znane są także modele programowego we/wypolegającego na aktywnym czekaniu), obsługą urządzeń (wejście/wyjście, sterowniki, dostęp), obsługąsieci(stosprotokołówsieciowych),itd.Częśćzadańrealizowanajestzminimalnymudziałemprocesora(awięc także i systemu) jest tonaprzykład transferdanychw trybieDMApolegającyna tym iżdanekopiowane są całymi blokami bez udziału procesora do/z pamięci (system zajmuje się tylko inicjacjątransmisji). Należy tu jednocześnie zaznaczyć iż w przypadku nie stosowania tej technologii dane teżkopiowane są pomiędzy dyskiem a procesorem całymi blokami (minimum sektor) gdyż dysk (wodróżnieniuodpamięcioperacyjnej)niejestbezpośredniodostępnydlaprocesora.
Współczesne systemy korzystają z co najmniej dwóch poziomów pracy - uprzywilejowanego poziomu"nadzorcy" w którym działa jądro systemu operacyjnego oraz trybu użytkownika. Operacje I/O muszą
odbywać się w trybie uprzywilejowanym. Również pamięć posiada obszar chroniony, w którymumieszczany jest m.in. tablica wektorów przerwań (inaczej zmiana adresu w tym wektorze mogłabydoprowadzićdoprzejęciasystemuwtrybieuprzywilejowanym).
Procesyiszeregowaniezadań
Istotnąroląsystemuoperacyjnegowzarządzaniuprocesami(obokczynnościadministracyjnychjakichtworzeniepowielanie,usuwanie,czyteżwstrzymywanieitp)jestzapewnienieochronypamięci(każdyprocesmożepisaćposwojej i ewentualniewspółdzielonejgdydostałdo tegoprawo)orazprocesora(przerwaniezegarowepowodujewywołanieplanisty,któryustalajakiprocesdostanienastępnykwantczasu procesora). Niektóre systemy wyróżniają obok procesów także wątki, które różnią się od nichwspółdzieloną(międzywątkamijednegoprocesu)pamięciąizasobami(np.otwartymiplikami).Systemoperacyjny zapewnia także zestaw usług i funkcji (wywołań) systemowych zapewniającychpośrednictwomiędzyinterfejsemtrybuużytkownikaasprzętem.
Istotnymzadaniemsystemuoperacyjnegojestprzeciwdziałaniemtzw.blokadom,czylisytuacjigdydwalubwięcejprocesówblokująsięwzajemniewoczekiwaniunazasoby(amazasóbX,któregopotrzebujeb aby zwolnić zasób Y, którego potrzebuje a do zwolnienia X). Realizowane to może być na kilkasposobów:
zapobieganie blokadzie (czyli niedopuszczenie do zajścia warunków koniecznych) - np. poprzezkonieczność deklarowania wszystkich zasobów na początku, zwalniania przydzielonych zasobówprzedzgłoszeniemzapotrzebowaniananastępneunikanie blokady (czyli określamy maksymalne zapotrzebowanie i tak przydzielamy zasoby abyuniknąćzajściablokady)-np.poprzezkontrolęczypospełnieniużądaniadalejbędziemydziałaćwstanie "bezpiecznym", tj takim że istnieje sekwencja (zwana bezpieczną) w której maksymalnezapotrzebowanie każdego procesu może być spełnione w oparciu o zasoby zwolnione przezprocesybędącewcześniejwtejsekwencjiorazzasobywolnewykrywanieiusuwanieblokadygdydoniejdoszło
Planistaprocesora,czylifragmentsystemuodpowiedzialnyzaprzydzielanieprocesoraprocesom,możepracować w trybie z wywłaszczaniem lub bez. W tym pierwszym wypadku proces otrzymuje kwantczasu procesora który może wykorzystać w całości (wtedy przejdzie z stanu wykonywania w stangotowości) lub z niego wcześniej zrezygnować (gdy np. czeka na I/O, wtedy przejdzie z stanuwykonywania w stan oczekiwania). W drugim przypadku proces wykonuje swój kod do momentu ażsamoddaprocesor.Formatazbliżonajestdowykorzystywanejwszeregowaniuczasurzeczywistego-procesbędziewywłaszczonytylkoprzezprocesowyższympriorytecieibędzietonatychmiastowe(przynajbliższymprzerwaniuzegarowym).Istniejewielealgorytmówszeregowaniatakichjak:
FCFS-pierwszyzgłoszony=pierwszyobsłużonySJF-najkrótszyzgłoszonybędziepierwszymwykonanym(wersjazwywłaszczaniem-SRTF-gdynowy najkrótszy pozostały), algorytm raczej nie do zastosowania praktycznego - trzeba byprzewidywaćdługośćwykonaniapriorytetowe - zawsze o najwyższym priorytecie (jak wspomniałem wyżej wykorzystywane wsystemachreal-timerotacyjne-każdypokawałku,potemnakonieckolejkikolejkiwielopoziomowe-systemzpriorytetami,podziałemczasupomiędzykolejki,przenoszeniemprocesówmiędzykolejkami,...
Zarządzaniepamięcią
Drugą podstawową funkcją systemu operacyjnego, wspomnianą na początku, jest zarządzaniepamięcią.Zarządzaniepamięciąpoleganaodpowiednimmapowaniuadresów logicznych (używanychprzezprocesy)naadresyfizyczne(używaneprzezprocesor),korzystaonozwsparciasprzętowegozestronyprocesora. Jesttonajczęściejrealizowanewoparciuowspomnianymechanizmstronicowania.Polega to na podziale pamięci dostępnej pamięci fizycznej na jednakowe bloki zwane ramkami orazpodzialepamięcilogicznejnajednakowebloki(otejcałejwielkościcoramki)zwanestronami.Stronyktóre są wykorzystywane przez program są mapowane na dowolne ramki pamięci fizycznej (wprzypadkugdydanastronaniezamapowana-wzależnościodokolicznościbłądbrakustronylubbłądochrony strony). Rozwiązuje to problem fragmentacji zewnętrznej, polegającej na braku spójnegoobszarupamięciożądanejdługościpomimoiżłącznailośćwolnejpamięcijestdostateczna,jednaknierozwiązujeproblemufragmentacjiwewnętrznej,polegającejnaprzydzielaniuzbytdużychfragmentówpamięcidlaprocesu (awręczmożnapowiedzieć żegopogłębia).Mechanizm tenwymaga trzymaniatablicy wolnych ramek, tablicy stron dla każdego procesu (zawierającej przypisania mapowań strondanegoprocesunaramki)orazwykonywaniatłumaczeniaadresówlogicznych(strona+przesunięciena stronie). Także sama tablica stron procesu procesu może być stronicowania (mamy tablicę którainformujenasżeprzypisaniastronwdanymzakresieadresówsąprzechowywanewjakiejśramce).
Stronyiramkimogąbyćwspółdzielonepomiędzyprocesami(np.przyrozgałęzianiuprocesustronysąkopiowane dopiero gdy zajdzie taka potrzeba). W przypadku braku miejsca w pamięci fizycznej
wybrane strony nieaktywnego aktualnie procesu mogą być umieszczane na dysku (swap). Niekiedymożetopowodowaćszamotanieprocesupolegającenazbytdużejliczbiewymianstron.Zawszejednakprowadzitodokoniecznościustalaniaktórestronynajlepiejjestprzenieśćnadysk.Optymalnebyłobyprzenoszenie tych które najdłużej nie będą potrzebne (jednak z oczywistych względów jet topraktycznieniedozrealizowania).Stosujesięróżnealgorytmytegowyboru:
FIFO-usuwamynajdłużejbędącąwpamięciLRU - usuwanie tej do której najdawniej się odwoływano (licznik czasu, bit odniesienia, bitodniesieniawokreślonymczasie,bitmodyfikacji)LFU-usuwamyznajmniejsząliczbąodwołańMFU-usuwamyzdużąliczbąodwołań
Alternatywną (i mniej wymagającą) wobec stronicowanie metodą zarządzania pamięcią jestsegmentacja. W przypadku architektury x86 jest ona zawsze wykorzystywana jednak może byćprzykrytadużymsegmentemnaktórymwykorzystujemystronicowaniem.
ProcesuruchamianiakomputeraPo otrzymaniu sygnału resetu (także przy uruchamianiu systemu - "Power-on Reset") procesor poinicjalizacji rejestrów zaczyna wykonywanie kodu znajdującego się pod jakimś ustalonym adresem(typowo w wbudowanej lub zewnętrznej pamięci typu ROM lub Flash). W zależności od danejarchitektury / procesrora może to być m.in.: bezpośrednio kod programu użytkownika, wbudowanybootloader danego procesora umożliwiający dalsze ładowanie np. z karty SD, zewnętrznyniskopoziomowybootloader(np.u-boot).
Wprzypadkuarchitekturzgodnychzx86jesttoBIOS,którypozakończeniuprocesuinicjalizacjisprzętui testów rozruchowych ładuje do pamięci kod znajdujący się w pierwszym sektorze dysku twardego(sektorzerozruchowymrozpoczynającymsięodadresuzerowego)iuruchamiago(przekazujedoniegokontrolę).Znajduje się tamkod (lub tylkopoczątekkodu)programu rozruchowego, którego zadaniemjest załadowanie systemu operacyjnego. W przypadku współczesnych systemów linuxowych jest tozazwyczajGRUB.
W przypadku sektorów rozruchowych typu MBR (i kompatybilnych z nim), kod ten może liczyćmaksymalnie446bajtów(gdyżnakolejnychpozycjachznajdujesiętablicapartycji)ijegozadaniemjestzaładowanie i uruchomienie pozostałej części programu rozruchowego (musi znać jej położenie nadysku).PozostałaczęśćprogramurozruchowegomożeznajdowaćsiętużzaMBR(wprzerwiepomiędzyMBRapierwsząpartycją-dlatablicypartycjiMBR/msdos),wdedykowanejpartycjiBIOSbootpartition(dla tablicy partycji GPT) lub w partycji oznaczonej jako bootowalna. Część ta zawiera modułypozwalającenadostępdosystemuplikówzawierającegokonfigurację,obrazjądra,itporazinformacjęojegopołożeniu(dysk,partycja,ścieżka).
WprzypadkukomputerówopartychnaUEFI firmwareodpowiedzialny jestzazinterpretowanie tablicypartycji(GPT)izaładowanieprogramurozruchowegozplikuznajdującegosięnaspecjalnejpartycjiEFI(EFI System partition) z systemem plików FAT32. W pliku tym umieszczana jest całość (obie opisanepowyżejczęściprogramurozruchowego).
Start systemu rozpoczyna się od załadowania do pamięci obrazu jądra wraz z parametrami oraz(opcjonalnie)initrdiprzekazaniakontrolidojądraprzezprogramrozruchowy(np.GRUB).Wprzypadkujądra linuxowego i korzystania z initrd obraz ten przekształcany jest na RAM-dysk w trybie zapisu-odczytuimontowanyjakorootfszktóregouruchamianyjest/sbin/init(któregopodstawowymzadaniemjest zamontowanie właściwego rootfs). Po jego zakończeniu (lub od razu gdy nie używamy initrd)uruchamiany jest program wskazany w opcji init= jądra (domyślnie typowo /sbin/init) z rootfswskazanegowopcjiroot=jądra.Wopcjiinit=możnawskazaćdowolnyprogramlubskrypt(uruchomionyzostaniezprawamiroot'a).
Systemy"unix-owate"Jesttogrupasystemówoperacyjnych,będących(przynajmniejwjakimśstopniu)zgodnychzspecyfikacjąPOSIX / Single UNIX Specification. Charakteryzują się zbliżonym zbiorem wywołań systemowychdostępnych z poziomu jęzka C oraz funkcji biblioteki standardowej C, co ułatwia zapewnienieprzenośnościoprogramowania(wpostaciźródłowej).Zapewniająpodobnyzbiórpodstawowychkomendliniipoleceń(konsoli).
Systemyunix'oweposiadajądrzewiastysystemplikówzaczynającysięwkatalogugłównymoznaczanymprzezukośnik(/),wktórymzamontowanyjestgłównysystemplików(rootfs),innesystemyplikówmogąbyćmontowanewkolejnychkatalogach.Donajistotniejszychkatalogównależyzaliczyć:/bin
zawierającyplikiwykonywalnepodstawowychprogramów/sbin
zawierającyplikiwykonywalnepodstawowychprogramówadministracyjnych
/libzawierającyplikipodstawowychbibliotek
/usrzawierającyoprogramowaniedodatkowe (wewnętrzniemapodobną strukturędogłównego - tzn.katalogi/usr/bin,/usr/sbin,/usr/lib,itd)
/etczawierającykonfiguracjeogólnosystemowe
/varzawierającydaneprogramówiusług(takiejakkolejkapoczty,harmonogramyzadań,bazydanych)
/homezawierającykatalogidomoweużytkowników(częstomontowanyzinnegosystemuplików,dlategoteżrootmaswójkatalogdomowyw/root,abybyłdostępnynawetgdytakiemontowanieniedoszłodoskutku)
/tmpzawierającypliki tymczasowe (typowoczyszczonyprzystarciesystemu);wLinuxiewystępuje też/run przeznaczonydo trzymaniadanych tymczasowychdziałającychusług takich jaknumerypid,blokady,itp
/devzawierającyplikireprezentująceurządzenia;wLinuxiewystępujeteż/syszawierającyinformacjeiustawieniadotyczącem.in.urządzeń
/proczawierającyinformacjeodziałającychprocesach(wLinuxietakżeinterfejskonfiguracyjnydlawieluparametrówjądra)
Plikiikatalogiktórychnazwarozpoczynasięodkropkitraktowanesąjakoplikiukryte.
Z punktu widzenia programisty czy też użytkownika (prawie) wszystko jest plikiem, których istniejąróżnerodzaje(zwykłyplik,katalog,urządzenieznakowe,urządzenieblokowe,linksymboliczny,kolejkaFIFO, ...);pewnymwyjątkiemsąurządzenia sieciowe (któreniemają reprezentacjiwsystemieplików(alegniazdazwiązaneznawiązanymipołączeniamiobsługujesięzasadniczotakjakpliki).
Najważniejszepolecenia
Wiele z poniższych komend stanowi standardowe polecenia określone w POSIX / Single UNIXSpecification,cogwarantujeichobecnośćnakompatybilnychsystemach(jednakniejesttopełnalistapoleceń wymaganych przez POSIX). Część z nich jest powszechnie dostępnym, wieloplatformowymoprogramowaniem dla systemów "unix-owatych". Niektóre (zwłaszcza związane z działaniamiadministracyjnymi)sąspecyficznedlaDebianalubLinuxa.
Uzyskiwaniepomocy
man[nazwapolecenia]wyświetlastronępodręcznikasystemowegonatematwskazanegopolecenia,funkcjisystemowej,plikukonfiguracyjnego
pinfo[nazwapolecenia]lubinfo[nazwapolecenia]wyświetlastronęnowegopodręcznikasystemowegonatematwskazanegopolecenia
apropos[tekst]wyszukiwaniewopisachstronpodręcznikasystemowegoapropos-s1''pozwalazapoznaćsięzspisemwszystkichstronwrozdzialepierwszym(cojestwktórymrozdzialemożnazobaczyćwmanman)
Większość poleceń obsługuje także opcje --help lub -h, które wyświetlają informację na temat ichużycia.Wtymmiejscuwartoteżzauważyćżetypowoopcjekrótkie(pojedynczalitera)poprzedzanesąpojedynczymmyślnikiem(ipojednymmyślnikumożewystąpićkilkakolejnychopcji),natomiastopcjedługiepoprzedzanesądwomamyślnikami.
Zarówno w tekstach pomocy jak i w tym dokumencie stosowana jest konwencja polegająca naoznaczaniu opcjonalnych argumentów poprzez umieszczanie ich w nawiasach kwadartowych (jeżelipodajemy ten argument do komendy nie obejmujemy go już tymi nawiasami) oraz rozdzielaniualternatywnychopcjiprzypomocy~|.Np.a[b]c|doznaczaiżpolecenieawymagaargumentupostacicalbod,którymożebyćpoprzedzonyargumentemb.
Powłoka(iokolice)
bashpopularna powłoka (interpreter poleceń) zgodna z sh, zapewnia m.in. obsługę zmiennych(zasadniczonapisowych)orazznakówuogólniającychtakichjak:?oznaczającydowolnyznak*oznaczającydowolny(takżepusty)ciągznaków[a-zAD]oznaczającydowolnyznakzwymienionychwzbiorzeujętymwnawiasachkwadratowych,
zbiórmożebyćdefiniowanyzużyciemzakresów,np.a-zADoznaczadowolnąmałąliteręodadozwłącznie,spację,dużąliterąAlubD[!a-z] oznaczający dowolny znak z wyjątkiem znaków wymienionych w podanym zbiorze, zbiórmożebyćdefiniowanyzużyciemzakresów,np.a-zoznaczadowolnąmałąliteręodadozwłącznieArgumenty liniipoleceńprzekazywanedowywoływanychprzezpowłokępoleceńrozdzielanesądowolną ilością spacji. Jeżeli argument ma być napisem zawierającym spacje konieczne jestzabezpieczenieichprzypomocyodwrotnegoukośnika(\,np.aaa\bbb)lubujęciecałegonapisuwcudzysłowie pojedynczym (', np. 'aaa bbb') lub podwójnym (", np. "aaa bbb"). Oba typycudzysłowówzabezpieczająprzedrozwijaniemznakówuogólniających(zastępowaniemnapisuzeznakamilistąpasującychnazw/ścieżek).Cudzysłówpojedynczy(wodróżnieniuodpodwójnego)zabezpiecza także przed interpretacją umieszczonych wewnątrz innych znaków specjalnychtakichjakczyodwołaniadozmiennych.
ssh[user@]hostumożliwiauzyskaniepowłokizdalnegosystemupoprzezszyfrowanepołączenie,przydatneopcje:-L portLokalny:hostZdalny:portZdalny tworzy tunel przekierowujący dane kierowane na portLokalnykomputeranaktórymdziałaklientsshdoportuportZdalnynaserwerzehostZdalnypoprzezserwerSSH(przydatnegdyhostZdalnyjestosiągalnyzhostSSHaleniezkomputeralokalnego)-Dporttworzytuneldynamicznynawskazanymporcie(możeonbyćużytyjakoproxytypuSOCKSnp. w Firefoxie w celu zapewnienia dostępu do zasobów WWW dostępnych z serwera SSH aniedostępnyzkomputeralokalnego)-pportokreślainnyniżdomyślnyportserweraSSH-X aktywuje przekazywanie komend X serwera ze strony zdalnej do klienta (pozwala nauruchomienie po stronie zdalnej aplikacji z GUI, które zostanie wyświetlone na lokalnym Xserwerze)
tmuxlubscreenmultiplexer terminala - pozwala na uzyskanie wielu okien konsoli (także wyświetlanych jednoobokdrugiego)napojedynczymterminalu;ponadtopozwalająnaodłączanie ipodłączaniesesji,co pozwala na łatwe pozostawienie działającego programu po wylogowaniu i powrót do niegopóźniej
watch[opcje]polecenieokresowo uruchamia polecenie i wyświetla jego wynik, opcja -i pozwala na określenie co ilesekundmaaktualizowaćwynikpolecenia
scripttworzyzapissesji(stdin,stdout,...)
wyświetlanieiedycjaplików
vimlubvivi jest chyba najbardziej zaawansowanym edytorem, którego obecność gwarantuje standardPOSIX. vim jest mocno rozbudowanym jego klonem, oferującym bardzo zaawansowanefunkcjonalności, powszechnie stosowanym jako zamiennik oryginalnego vi. vim obsługuje 3podstawowe tryby pracy: komend (służący do wydawania opisanych niżej poleceń), wizualny(służący do zaznaczania i wydawania niektórych komend), edycji (wstawiania/nadpisywania -służącydowprowadzaniatekstu).Podstawowaklawiszologia:
przełączaniepomiędzytrybami:Escpowrótdotrybukomendi trybwstawiania; A trybwstawiania ze skokiemnakoniec linii, o / O trybwstawiania zewstawieniemnowejliniipo/przedbierzącąRtrybzastępowaniaInsertzmianatrybuwstawianiaizastępowaniav tryb wizualny (umożliwia zaznaczenie przy pomocy strzałek); ctrl+v tryb wizualnyblokowy,Vtrybwizualnyliniowy:set paste włącza :set nopaste wyłącza tryb wklejania (nie będzie działać automatyczneformatowanieitp.)gvponawiaostatniezaznaczenietrybuwizualnego
wycinanieikopiowanie:yskopiuj;d-wytnij(skopiujiusuń)poy,dmożnapodaćnp.20llub20[strzałkawprawo]cooznacza 20 kolejnych znaków, 2w oznacza dwa słowa (więcej o takich punktach skokuponiżej)xwytnij(skopiujiusuń)znak(możebyćpoprzedzoneilościąznakówdowycięcia);wielkieXdziałaanalogicznie,tyleżewtyłyyskopiujlinię;dd-wytnij(skopiujiusuń)wobuwypadkachmożebyćpoprzedzoneilościąliniidoskopiowania/wycięciapwklejapo;P-wklejaprzed
komendykopiowania iwklejaniamogąbyćpoprzedzone jedno-znakowąnazwąrejestruwktórymumieszczanesądane(poprzedzamyjąznakiem" ipodajemyprzed licznikiem,np."a3ddwytniedorejestrua3linie),częśćrejestrówjestużywanaautomatycznie,aniektóresą tylko do odczytu, podgląd aktualnej zawartości rejestrów możliwy jest przy pomocykomendy:registers
wyszukiwanie,zastępowanie,skokdolinii:/szukaniewprzód,?szukaniewtył;*szukaniewprzódsłowapodkursorem,#szukaniewtyłsłowapodkursoremnwyszukanienastępnegowystąpienie;NwyszukaniepoprzedniegowystąpienieGprzejściedowskazanej linii,numerpodajemyprzedG,0oznaczaostatnią linięwpliku,więc0Gspowodujeprzejściedoniej:[zakres]s@regexp@napis@[g]wyszukaj izastąpwyrażenieregularneregexpprzeznapis;zakresmoże być: numerem linii, przedziałem z numerami linii postaci pierwsza,ostatnia, gdzie: .oznaczabieżącąlinię,$oznaczaostatniąlinięwpliku,wartośćnumerycznapoprzedzona+oznacza tyle kolejnych linii od bieżącej, a poprzedzona - przed bieżącą, znakiem % (cooznaczacałyplik), zakresemzaznaczonymw trybiewizualnym;podanieopcjig powodujezastępowaniewszystkichwystąpieńanie tylkopierwszego;znak@pełni rolęseparatora imożezostaćzamiastniegoużytyinnyznak
otwieranie,zapisywanie,zamykanieplików::eścieżkaotwarciewskazanegopliku:wzapis(możnatakżepodaćścieżkępodjakamazostaćzapisanyplik):qwyjście:q!wyjściebezzapisywania:wqzapisiwyjście
przełączaniesięmiędzyotwartymiplikamiioknami::nnastępnyplik;:Npoprzedniplik:split poziomy podział okna; :vs pionowy podział okna; Ctrl+W a następnie strzałka -przełączaniemiędzyoknami
cofanieiponawianieedycji:u,:undocofaostatniąoperacjęCtrl+r,:redoponawiacofniętąoperację
punkty skoku (mogą być używane jako polecenia do poruszania się lub jako adresy wpoleceniachtakichjakd,y):
l/h/k/jjedenznak/linięwprawo/lewo/górę/dół(działatakjakstrzałki)0/^/$począteklinii/początektekstuwlinii,koniecliniiw / b / e następne słowo / poprzednie słowo / koniec słowa; wielkie W / B / E działaanalogicznie,różnisiętraktowaniemspacjiprzysłowief / F następny /poprzedni znakpodanypo tej komendzie,włącznie znim (np.dfX usuniewszystkodonajbliższegowystąpieniaXwrazztymX);t/Tdziałaanalogicznie,tylewyłączapodanyznakpoprzedzeniepowyższychkomendliczbąpowodujepowtórzenieichtylerazy-np.10l-10znakówwprawo,3F:-trzecidwukropekwlewopunktemskokujestteżwyżejopisanepolecenieGpoprzedzanenumeremliniidoktórejmasięodbyćskokpunktem skoku mogą być także swobodnie umieszczane z dokumencie zakładkiidentyfikowanepojedynczymznakiem:
m i następie znak ją identyfikujący - utworzenie zakładkiwmiejscukursora (np. ma -utworzyzakładkęa)`(backtick)/'(apostrof)skokdozakładki/liniizzakładkąpodanąpotejkomendzie:marks-listazakładek;:delmarks/:delmarks!-usunięciezakładki/usunięciewszystkichnieautomatycznychzakładek
inne::rplik,wstawieniezawartościpliku:%!xxdpokazaniewartościnumerycznychiumożliwienieedycjiplikujakobinarnego;:%!xxd-rpowrótdonormalnejedycji>/<zwiększanie/zmniejszaniewcięciazaznaczonego(wtrybiewizualnym)tekstu
zczwijabieżącyblok,zCzwijabieżącyblokażdonajwyższegopoziomu,zorozwijabieżącezwinięcie, zO rozwija rekurencyjnie bieżące zwinięcie, zR rozwija wszystkie zwinięcia wdokumencie:setwrapwłącza:setnowrapwyłączazawijanialiniiwpodglądzie
lesslubmoreprzeglądanietekstuekranpoekranie,less posiada większe możliwości od more (w szczególności posiada możliwość przeglądaniedokumentuwtył),przydatneopcje:-X nie czyści ekranu przy wychodzeniu z less'a (całość historii wyświetlania pliku pozostaje whistoriiterminala)-Fautomatyczniekończygdywyświetlanytekstmieścisięnajednymekranie
bviwzorowanynavim'ieedytorhexalny(binarny)
odlubxxdlubhexdumpwypisywanie plików interperowanych binarnie w postaci liczby oktalne, szesnastkowe, itd,przykłady:hexdump-e'1/4"%010d"1/2"%05d"2/1"%02x""\n"'plikkażdekolejne8bajtówplikuzostaniezinterpretowane jako: jedna liczba 32 bitowa liczba całkowita (4 bajty), 16 bitowowa liczbacałkowita(2bajty)idwieliczbyjednobajtowe(wyświetlaneszesnastkowo)
vbindiffporównujewizualnieplikibinarne(interfejsncurces)
Operacjenasystemieplików
katalogroboczy
cd[ścieżka]zmianabieżącegokatalogu,warto zauważyć, iż katalogi w ścieżce oddzielamy ukośnikami /, bieżący katalog oznaczamykropką.,nadrzędnyoznaczamydwiemakropkami..,ścieżki zaczynające się od ukośnika / oznaczają ścieżki bezwzględne (od korzenia systemuplików),pozostałeoznaczająścieżkęwzględną(wyrażonąwzględembierzącegokatalogu),katalogdomowyoznaczasiętyldą~
pwdwyświetlaścieżkędobieżącegokatalogu
listowanieiwyszukiwanieplików
ls[opcje][ścieżka]listowaniezawartościkatalogu,doważniejszychopcjinależyzaliczyć:-awyświetlajplikiukryte(zaczynającychsięodkropki)-l wyświetlaj pliki w formie listy z szczegółowymi informacjami (uprawnienia, rozmiar, datamodyfikacji,właściciel,grupa,rozmiar)-1wyświetlajplikiwformie1plikwjednejlinii(bezdodatkowychinformacji;stosowanedomyślnegdywynikkomendyprzekazywanyjeststrumieniemdoinnejkomendylubpliku)-hstosujjednostkitypuk,M,Gzamiastpodawaćrozmiarwbajtach-tsortujwgdatymodyfikacji-Ssortujwgrozmiaru-rodwróćkolejnośćsortowania-cużyjdatyutworzeniazamiastdatymodyfikacji(stosowanewpołączeniuz-li/lub-t)-dwyświetlajinformacjeokataloguzamiastjegozawartości
find[opcje][katalogstartowy][wyrażenie]wyszukiwanie w systemie plików w oparciu o nazwę/ścieżkę lub właściwości pliku, doważniejszychopcjinależyzaliczyć:-Pwypisujinformacjeolinkachsymbolicznychanieplikachprzezniewskazywanych(domyślne)-Lwypisujinformacjeowskazywanychprzezlinkisymboliczneplikachdoważniejszychelementówwyrażenianależyzaliczyć:-name "wyrażenie" pliki których nazwa pasuje do wyrażenia korzystającego z shellowych znakówuogólniającychkomendafind(wodróżnieniunp.odls)samodzielnieinterpretujewyrażeniazawierająceshelloweznaki uogólniające w argumentach tych opcji, w związku z czym konieczne może się okazaćzabezpieczenie ich przed interpretacją przez powłokę np. przy pomocy umieszczenia wewnątrzpojedynczychcudzysłowów-iname"wyrażenie"jak-name,tyleżenierozróżniawielkościliter-path"wyrażenie"plikiktórychścieżkapasujedowyrażeniakorzystającegozshellowychznakówuogólniających-ipath"wyrażenie"jak-path,tyleżenierozróżniawielkościliter-regex"wyrażenie"plikiktórychścieżkapasujedowyrażeniaregularnego-iregex"wyrażenie"jak-regexp,tyleżenierozróżniawielkościliter
warunek-owarunekłączywarunkisumąlogicznąORzamiastdomyślnegoiloczynulogicznegoAND!waruneknegacjawarunku-mtime[+|-]nplikiktórychmodyfikacjaodbyłasięn*24godzinytemu-mmin[+|-]nplikiktórychmodyfikacjaodbyłasięnminuttemu-ctime[+|-]nplikiktórezostałyutworzonen*24godzinytemu-cmin[+|-]nplikiktórezostałyutworzonenminuttemu-size[+|-]n[c|k|M|G]plikiktórychrozmiarwynosin(c-bajtów,k-kilobajtów,M-Megabajtów,G-gigabajtów)wpowyższychtestach+oznaczawięcejniż,-oznaczamniejniż,uwaga:porównywaniupodlegająliczbycałkowite,np.+1oznacza > 1wliczbachcałkowitychtzn. ≥ 2-execpolecenie\{\}\;dlakażdegoznalezionegoplikuwykonajpoleceniepodstawiającścieżkędotegoplikupod\{\}(zastosowaneodwrotneukośnikisłużązabezpieczeniunawiasówklamrowychiśrednikaprzedzinterpretowaniemichprzezpowłokę)-execdirpolecenie\{\}\;,podobniejak-exectyleżepoleceniezostanieuruchomionewkataloguwktórymznajdujesięwyszukanyplik
tree[ścieżka]wyświetladrzewokatalogówiplików
statścieżkawyświetlainformacjeopodanymplikulubkatalogu
realpathścieżkawypisujeuproszczoną/rozwiniętąścieżkę(tzn.zezredukowanyminadmiarowymiodniesieniamiwzględnymi),standardowo wypisuje ścieżkę bezwzględną (opcja --relative-to=katalog powoduje wypisaniewzględnejwstosunkucodokatalog),standardowo zastępuje linki symboliczne wskazywaną przez nie ścieżką (opcja -s wyłącza tąfunkcjonalność),opcja-mpozwalanaoperowanienieistniejącymiścieżkami,standardowezachowanieodpowiadadziałaniukomendyreadlink
du[opcje]ścieżka1[ścieżka2[...]]wyświetlanie informacji o zajętej przestrzeni dyskowej przez wskazane pliki / katalogi, doważniejszychopcjinależyzaliczyć:-s podaje łączną ilość zajętego miejsca dla każdego argumentów (zamiast wypisywać rozmiarkażdegopliku)-cpodajełącznąilośćzajętegomiejscadlawszystkichargumentów-hstosujejednostkitypuk,M,Gpodawany rozmiar może się różnić (w obie strony) od wyniku ls: ls podaje rozmiar pliku (ilezawiera informacji lub ile zostało zadekarowane że może jej zawierać), a du to ile zajmuje nadysku
df[opcje]wyświetlanieinformacjiozajętościmiejscanaposzczególnychsystemachplików
kopiowanie,przenoszenie,usuwanie,...
cp[opcje]źródło1[źródło2[...]]celkopiujewskazanyplik(lubpliki)dowskazanejlokalizacji,wprzypadkukopiowaniawieluplikówcelpowinienbyćkatalogiem,doważniejszychopcjinależyzaliczyć:-rpozwalana(rekursywne)kopiowaniekatalogów-apodobniejak-r,dodatkowozachowującatrybutyplików-lzamiastkopiowaćtworzytwardedowiązania(hardlinks)-szamiastkopiowaćtworzylinkisymbolicznedoplików-fnadpisywaniebezpytania-izawszepytajprzednadpisaniem
lnźródło1[źródło2[...]]celtworzy link twardy do wskazanego pliku (lub plików) w wskazanej lokalizacji, w przypadkuwskazania wielu plików źródłowych cel powinien być katalogiem, do ważniejszych opcji należyzaliczyć:-stworzydowiązaniasymbolicznezamiasttwardych-rużywaścieżkiwzględnejzamiastbezwzględnejprzytworzeniudowiązańsymbolicznych
katalog*
**)dokładniej„miejsca”wsystemieplikówokreślanezapomocąi-nodów
zawartośćdysku**
*)nakatalogpatrzymyjaknaplikzawierającyinformacjeozawartościtegokatalogu
plik1.txtplik2.txt
Alamakota
KotmaAlę
...
...
...link1.txtlink2.txt→./plik1.txt ln-s./plik1.txtlink2.txt
lnplik2.txtlink1.txtpowodujeutworzenielinkutwardegolink1.txt,czyliwpisuwkataloguwskazujacegonatesamedane(tensami-node)coplik2.txt
powodujeutworzenielinkusymbolicznegolink2.txt,czyliwpisuwkataloguwskazującegonapodanąścieżkę(./plik1.txt)
Link twardy jest innym uchwytem do tych samych danych i może być używany także poskasowaniu oryginalnego pliku. Liczbę dowiązań do danego pliku pokazuje m.in. komenda ls zopcją -l. Nie można utworzyć linków twardych do katalogów, ani do plików na innym zasobiedyskowym(innymsystemieplików).Link symboliczny wskazuje na konkretną ścieżkę (względną lub bezwzględną – co może miećznaczenie przy przenoszeniu takiego linku) do dowolnego (nawet nie istniejącego – wtedymówimyozerwanymlinku)plikulubkatalogu.
mv[opcje]źródło1[źródło2[...]]celprzenosi wskazane pliki / katalogi do wskazanej lokalizacji, w przypadku przenoszenia wieluplikówcelpowinienbyćkatalogiem,doważniejszychopcjinależyzaliczyć:-fnadpisywaniebezpytania-izawszepytajprzednadpisaniem
rm[opcje]ścieżka1[ścieżka2[...]]usuwawskazanepliki,doważniejszychopcjinależyzaliczyć:-rpozwalanana(rekursywne)kasowaniekatalogówwrazzzawartością-fusuwaniebezpytania-izawszepytajprzedusunięciem
touch[opcje]ścieżka1[ścieżka2[...]]zmianadatymodyfikacjipliku(wykorzystywanytakżedotworzeniaplików)
katalogi
mkdir[opcje]ścieżka1[ścieżka2[...]]tworzywskazanekatalogi,doważniejszychopcjinależyzaliczyć:-p pozwala na tworzenie całej ścieżki a nie tylko ostatniego elementu, nie zgłasza błędu gdywskazanykatalogistnieje
rmdir[opcje]ścieżka1[ścieżka2[...]]usuwawskazanekatalogi(musząbyćpuste)
zdalnekopiowanie
scp[opcje]źródło1[źródło2[...]]celkopiujewskazanyplik(lubpliki)dowskazanejlokalizacji,wprzypadkukopiowaniawieluplikówcelpowinienbyćkatalogiem,doważniejszychopcjinależyzaliczyć:-rpozwalana(rekursywne)kopiowaniekatalogów-PportokreślaportSSHW odróżnieniu od cp źródło lub cel w postaci [user@]host:[ścieżka] wskazują na zdalny systemdostępnypoprzezSSH.
rsync[opcje]źródłocelkopiuje (synchronizacjiuje) pliki i drzewa katalogów (zarówno lokalnie jak i zdalnie), doważniejszychopcjinależyzaliczyć:-rpozwalana(rekursywne)kopiowaniekatalogów-lkopiujelinkisymbolicznejakolinkisymboliczne(zamiastkopiowaniazawartościplikunaktórywskazują)-tzachowujeczasmodyfikacjiplików-ukopiujetylkogdyplikźródłowynowszyniżdocelowy-ckopiujetylkogdyplikźródłowyidocelowymająinnesumykontrolne--deleteusuwazdocelowegodrzewakatalogówelementyniewystępującewdrzewieźródłowym-e'ssh'pozwalanakopiowaniena/zzdalnychsystemówzapośrednictwemssh,źródło lubcelwpostaci[user@]host:[ścieżka]wskazująnazdalnysystem--partial--partial-dir=."-tmp-"zachowujeskopiowaneczęściowoplikiwkatalogu.-tmp-(pozwalanaprzerwanieiwznowienietransferupliku)--progresspokazujepostępkopiowania--exclude="wzorzec" pomija (w kopiowaniu i kasowaniu) pliki pasujące do wzorzec (wzorzec możezawieraćznakiuogólniającepowłoki)-nsymulujepracę(pokazujecozostałobyskopiowane,aleniekopiuje)
sshfs[opcje]host:scieżkamontuje zdalny system plików z użyciem FUSE (filesystem in userspace) oraz SSH, doważniejszychopcjinależyzaliczyć:-pportokreślainnyniżdomyślnyportserweraSSH-oworkaround=rename,któryzapewniapoprawnemvnaistniejącyplik
Operacjenaarchiwach
tararchiwizujewieleplikówwpostacijednego,przykłady:tar -xf plik.tar - wypakowuje zawartość niekompresowanego archiwum plik.tar interpretujączapisanewarchiwumścieżkiwzględembieżącegokatalogutar -czf - ścieżka1 [ścieżka2 [...]] | ssh [user@]host 'cat > plik.tgz' - archiwizuje wskazanepliki/katalogibezpośrednionazdalnysystemzużyciemsshikompresjigzip
arpolecenie[modyfikatory]archiwum[pliki]archiwizuje wiele plików w postaci jednego (format wykorzystywany w plikach biblioteklinkowanychstatycznieiwpakietachDebiabna),przykłady:arrcslibAA.aaa*.o-tworzybibliotekęlibAA.azwszystkichplikówaa*.oarxpakiet.deb-wypakowujezawartośćpakietuDebianazplikupakiet.deb(będątodwaarchiwaiplikzwersjąformatupakietu)
7zarchiwizerobsługującewieleformatów,wtymformatyzsilnąkompresją
Operacjenaplikach(tekstowych)
cat[opcje][plik1[plik2[...]]]wypisywanieiłączenieplików
tac[opcje][plik]wypisywanieplikówzodwróceniemkolejnościlinii(odwróceniekolejnościwypisywania;możebyćużytenp.doodwrócenieporządkusortowania)
tail[opcje][plik]wyświetlaostatnieliniepliku,przydatneopcje:-nxokreślażemazostaćwyświetlonexostatnichlinii-furuchamiadopisywania(gdydoplikuzostanądopisanenowelinietailjewyświetli)
head[opcje][plik]wyświetlapoczątkoweliniepliku,przydatneopcje:-nxokreślażemazostaćwyświetlonexpierwszychlinii
multitailtaillepiejoperującynawieluplikachrównocześnie
rev[plik]wypisujeplikodwracająckolejnośćznakówwkażdymwierszu
wcliczylinie,słowa,znakiibajty
grep[opcje]wyrażenie[plik1[plik2[...]]]wyszukujepasującedowyrażeniaregularnegowyrażenieliniewplikach,przydatneopcje:-vzamiastpasującychwypiszniepasujące-iignorujwielkośćliter-aprzetwarzajplikibinarnejaktekstowe-EkorzystajzExtendedRegularExpressions(ERE)zamiastBasicRegularExpressions(BRE)-P korzystaj z Perl-compatible Regular Expressions (PCRE) zamiastBasic Regular Expressions(BRE)-rrekursywnieprzetwarzajpodanekatalogiwyszukującwwszystkichznalezionychplikach-Rjak-r,alezawszepodążazalinkamisymbolicznymi--exclude="wyrażenie"pomińplikipasującedowyrażenie(możezawieraćznakiuogólniającepowłoki)-lwypisujeplikizpasującymiliniami-Lwypisujeplikizbezpasującychlinii
diffścieżka1ścieżka2porównujeplikilubkatalogi(wprzypadkutychdrugichporównujezesobąplikiotakichsamychnazwachorazzgłaszafaktwystępowaniaplikutylkowjednymzkatalogów),przydatneopcje:-rrekursywnieprzetwarzajpodanekatalogi-uwypisujeróżnicewformacie"unified"-cwypisujeróżnicewformacie"context"
vimdiffścieżka1ścieżka2porównuje pliki wyświetlając je jeden obok drugiego (podobnie jak diff z opcją -y), pozwalającjednaknaedycjętychplików
patchstosujeplikłaty(wynikdiff'a)wceluzmodyfikowaniaplików,typowo:
patch -pn < plik.diff co powoduje zastosowanie zmian opisanych w plik.diff na plikach wbieżącym katalogu, n określa ilość poziomów ścieżek podanych w pliku łaty które mają zostaćzignorowane
combinediff/splitdiffłączydwaplikiłat/dzieliplikłatzłożonyzprzyrostowychzmiannaosobne(pakietpatchutils)
flipdiffzmienia kolejność w której będą nakładane dwie łaty dotyczące tych samych plików (pakietpatchutils)
interdiffporównywaniedwóchplikówłat(pakietpatchutils)
lsdiffwyświetlanieplikówmodyfikowanychprzezłatę(pakietpatchutils)
filterdiffwyciągnięciezplikułatyzmiandotyczącychwybranychplików(pakietpatchutils)
grepdiffprzeszukiwanie pliku łat celem znalezienia plików w modyfikacja których pasuje do wyrażeniaregularnego(pakietpatchutils)
rediff/editdiff/recountdiffprzeliczanienumerówliniiwplikułaty(pakietpatchutils)
unwrapdiff/dehtmldiff/fixcvsdiffnaprawa pliku łaty uszkodzonego przez zawijanie linii, html-izację, błędy w generowaniu łatyprzezcvs(pakietpatchutils)
quiltnarzędzieułatwiająceutrzymywaniezmiandojakiśplikówwpostacizbiorułat
sort[plik]sortujeliniewwskazanympliku,przydatneopcje:-ntraktujliczbyjakowartościnumeryczneanienapisy-iignorujwielkośćliter-rodwróćkolejnośćsortowania-knsortujwgkolumnyn-tsepkolumnyrozdzielanesąprzypomocyseparatorasep
tr[opcje]zbiór1[zbiór2]zastępujeznakizzbiór1odpowiadającymiimpodwzględemkolejnościznakamizzbiór2,przydatneopcje:-dzamiastzastępowaćusuwaznakiwystępującewzbiór1uwaga:częstodziałapoprawniewyłączniedlaznakówjednobajtowych-możnawtedyzastosowaćsed-e'y#zbiór1#zbiór2#'lubtrs-f'zbiór1zbiór2'
trs(wchodzącywskładpakietukonwert)bardziej inteligentnyodtrprogramsłużydozamienianiaznakówz jednegozbiorunaznakizdrugiegozbioru(wodróżnieniuodtrnadajesiędoznakówkilku bajtowych - utf8, lepiej od sed'a sprawdza się przy zmianie kodowań - patrz przykład wmanualu)
sed[opcje][pliki]edytujeplikzgodniezpodanymipoleceniami,przydatneopcje:-e "polecenie" - wykonuj na pliku polecenie (może wystąpić wielokrotnie celem podania wielupoleceń)-f"plik"-wczytajpoleceniazplikuplik-E-używajrozszerzonychwyrażeńregularnych-i-modyfikujpodanyplikzamiastwypisywaćzmienionynastdout-n-wyłączadomyślnewypisywanielinii,wypisaniemusibyćwykonanejawniepoleceniempprzydatnepolecenia:s@regexp@napis@[g]-wyszukajdopasowaniadowyrażeniaregularnegoregexpizastąpjeprzeznapis,podanieopcjigpowodujezastępowaniewszystkichwystąpieńanietylkopierwszego,znak@pełnirolęseparatoraimożezostaćzamiastniegoużytyinnyznaky@zbiór1@zbiór2@ - zastąp znaki z zbiór1 znakami odpowiadającymi im pod względem kolejnościznakamizzbiór2,znak@pełnirolęseparatoraimożezostaćzamiastniegoużytyinnyznakmożliwejestteżm.in.adresowanieliniinaktórychmabyćwykonywanaoperacja,np:0,/regexp/s@regexp@napis@wykonapolecenie sna liniachodpoczątkuplikudo linii pasującej dowyrażeniaregularnegoregexp,czylizastąpitylkopierwszewystąpieniewpliku
cut[opcje][pliki]wybierazplikuzadanyzestawkolumn,przydatneopcje:-fnnnwypierzkolumnyokreśloneprzeznnn(np.1,3-4,6-oznaczakolumnę1,kolumnyod3do4iod6,a-3oznacza3pierwszekolumny)-dsepkolumnyrozdzielanesąprzypomocyseparatorasep(musibyćpojedynczymjednobajtowymznakiem,abyominąćtoograniczenienależyskorzystaćzawk)
awkskryptowy językumożliwiającyprzetwarzanie tekstowychbazdanychpostaci linia=rekord,polaoddzielaneustalonymseparatorem(m.in.łączyfunkcjonalnośćgrep,cut,itp),szerzejomówionywprzykładzieprzetwarzanianapisówwbashu
pastełączy(odpowiadającesobiepodwzględemnumerów)liniezdwóchplików
joinłączyliniezdwóchplikówwoparciuoporównaniewskazanegopola
commporównuje dwa posortowane pliki pod względem unikalności linii (może wypisać wspólne lubwystępującetylkowjednymzplików)
uniqusuwapowtarzającesięliniezposortowanegopliku,przydatneopcje:-cwypiszliczbępowtórzeń-dwypisztylkoliniez2lubwięcejwystąpieniami-uwypisztylkoliniez1wystąpieniem
xmlstarletnarzędzie do przetwarzania, modyfikowania plików XML (można powiedzieć taki odpowiedniksed/awkdlaxml'a)
xsltprocnarzędziedoprzetwarzaniaXSLT1.0
Uprawnieniadoplików
Podstawowe unixowe uprawnienia do plików składają się z trzech członów: uprawnienia dlawłaściciela(u),grupy(g)ipozostałychużytkowników(o).Wkażdymzczłonówmogąbyćprzyznaneuprawnieniadoczytania(r),pisania(w)iwykonywania(x);w odniesieniu do plików jest to intuicyjne (uprawnienie do wykonywania jest potrzebne douruchomieniaprogramów),natomiastwstosunkudokatalogówwyglądatonastępująco:uprawnieniado czytania pozwalają na listowanie zawartości, do wykonania pozwalają na dostęp, do zawartościkatalogu (wejściadoniego)dopisaniana tworzenienowychobiektówwewnątrzniego i zmienianienazwistniejących.Wartozaznaczyćiżprogramwplikuniemającymprawwykonywalnościteżmożebyćwykonany(wprzypadkuskryptupoprzezuruchomienieinterpretatoraipodanietegoprogramujakoodpowiedniegoargumentu wywołania, w przypadku typowych binarek poprzez wywołanie /lib/ld-linux.so.2 z tymplikiemijegoopcjamijakoparametrem.
Rozszerzeniem podstawowych uprawnień opisanych powyżej jest mechanizm Filesystem AccessControlList(ACL,fACL).Jest on opcjonalnym mechanizmem który (na wspierających go systemach plików) pozwala nadefiniowanie indywidualnychuprawnieńdoplikudlaposzczególnychużytkownikówigrup-plikmanadalswojegowłaściciela,grupęiwszystkichpozostałych,aleprzedprawamidla"others"wchodząprawaużytkownikówigrupdefiniowanychwACL.Wypadkoweprawaobliczanesąjakosumawynikłazprawużytkownikaigrupdoktórychnależy.ACLpozwalaponadtodefiniowaćuprawnieniadomyślnedlanowopowstałychplikówwkatalogu(sąoneopcjąkatalogu).
Wszystkie poniższe komendy przyjmują opcję -R powodującą rekursywne wykonywanie zmian nadrzewkukatalogów/plikówrozpoczynającymsięwpodanejścieżce.
chown[opcje]właścicielścieżkazmianawłaścicielapliku
chgrp[opcje]grupaścieżkazmianagrupydoktórejnależyplikpliku
chmod[opcje]uprawnieniaścieżkazmianaprawadostępudopliku(ów)
getfacl[opcje][ścieżka]dczytuprawnieńzwiązanychzlistamikontrolidostępufACL
setfacl[opcje][ścieżka]ustawianieuprawnieńzwiązanychzlistamikontrolidostępufACL
Dodatkowonależywspomniećteżopoleceniachtakichjak:lsattr/chattr
wyświetla/modyfikujeatrybutyplikówzwiązanychzsystememplików(np.zabraniajakiejkolwiekmodyfikacjipliku)
getcap/setcapwyświetla / modyfikuje atrybuty plików związanych z właściwościami jądra (zasadniczo
zwiększonymi uprawnieniami programów je posiadających, ale bardziej ograniczonymi niżwykonanienaprawachrootprzezSUID)
Użytkownicy
id[użytkownik]informacjaoużytkowniku(m.in.grupydoktórychnależy)
whoamiinformacjaoaktualnymużytkowniku
wlubwhoinformacjaozalogowanychużytkownikach
lastostatniologującysięużytkownicy
lastbostatnienieudanelogowania
lastlogostatnielogowaniaużytkowników
passwd[użytkownik]zmianahasła
su[użytkownik]przełącza użytkownika (aby przełączony użytkownik miał dostęp do "naszego" x serwerawcześniejwydajemyxhostLOCAL:użytkownik)
sudoprogram pozwalający na wykonywanie uprzywilejowanych komend przez wyznaczonychużytkowników
Procesyizasoby
ps[opcje]wyświetlaaktualniedziałająceprocesyiinformacjeonichnp.kombinacjaopcji-Afpowodujewyświetleniewszystkichprocesówwrozszerzonym formaciewypisywania
pgrepwyświetlafiltrowanąlistęaktualniedziałającychprocesów
pstreewyświetladrzewoaktualniedziałającychprocesów
pwdxpodajekatalogroboczypodanegoprocesu
topmonitorowanieprocesówobciążającychCPU,pamięć,itd
iotopmonitorowanieprocesówobciążającychI/O
fuserinformacjeoprocesachkorzystającychzplików
lsofinformacjeoplikachotwartychprzezprogram(możnapodglądaćtakżew/proc/PID/fd/)
socklistwyświetlalistęotwartychsocketów
vmstatinformacjeoobciążeniusystemu
ipcsinformacjeowykorzystaniupamięciwspółdzielonej
kill[opcje]pidprzesyłasygnałdoprocesówopodanychPID
killall[opcje]nazwaprzesyłasygnałdoprocesówopasującejnazwie
timeczasdziałaniaprogramu
nice/renice/ionice/cpulimitzarządzaniepriorytetamiilimitamiprocesu
tasksetzarządzanieprzypisaniemprocesudoCPU/rdzenia
free
informacjaozajętościpamięci
Informacjeośrodowiskuisystemie
env/printenvzmienneśrodowiskowewypisywanieorazprzekazywaniedouruchamianegoprogramu
exportustawianieiusuwaniezmiennychśrodowiskowych
set/unsetustawianie,wyświetlanie,usuwaniezmiennych/funkcji/opcjiwśrodowiskupowłokibash
uptimeinformacjaotymjakdługodziałasystem...
unameinformacjaosystemie
lsb_releaseinformacjaosystemiezgodnymzLSB
getentinformacje z baz administracyjnych (typu użytkownicy, grupy, hosty), z uwzględnieniem ichkonfiguracjiw/etc/nsswitch.conf
Diagnostykasieci
Adresy
ipcalcorazsipcalckalkulatorIP(pozwalającynaobliczanieadresówsiecirozgłoszeniowych,zmianęnotacjiitd)
whoisinformacjezbazywhois(odomenielubadresieIP)
Dostępnośćitrasydohostów
ping[opcje]hostlubping6[opcje]hostsprawdzaniedostępnościhostazużyciemprotokołuICMP(obecniekomendaping6najczęściejjestrównoważna poleceniu ping z opcją -6 wymuszającą używanie jedynie IPv6, na starszychsystemachkomendapingmożenieobsługiwaćadresówIPv6iwtedykoniecznejeststosowaniedonichpoleceniaping6),ważniejszeopcje:-c n wykonaj n (domyślnie pyta do momentu przerwania przy pomocy np. Ctrl-C, lub sygnałuwysłanegozuzyciemkomendykill)-nniezamieniajadresuIPhostaktóryodpowiedziałnanazwędomenową
traceroute,traceroute6,tracepath,tracepath6,tcptraceroutelubtcptraceroute6sprawdzanieścieżkidohosta(wypisanielistyrouterówprzezktóreprzechodzipakietwdrodzedowskazanegohosta)Istnieją różne warianty tych poleceń (nawet pod tą samą nazwą), różnią się one stosowanymimechanizmami idomyślnymiopcjami.Generalniewszystkieuruchamiasięnazasadziepolecenie[opcje] host. Warianty z 6 na końcu nazwy będą używały jedynie adresów IPv6, natomiastpoleceniabez6nakońcunazwymogąpotrafićichużywaćlubnie.Wszystkiepopularnewariantypozwalają na podanie opcji -n wyłączającej zamienianie adresu IP hosta który odpowiedział najegonazwędomenową.Może zdarzyć się że śledzenie urwie się na jakimś hoście (np. z powodu jego konfiguracji lubbłędówwjegooprogramowaniusieciowym),możesięzdarzyćżeprzyużyciuinnejkomendyztejgrupy(lubzmianieopcji)udasięprześledzićdalszątrasępakietu.
mtr[opcje]hostsprawdzanie ścieżki do hosta (czyli podobnie jak traceroute i tracepath) w trybie ciągłym (zciągłym odświeżaniem) wraz z wypisywaniem informacji o stratach pakietów i opóźnieniach naposzczególnychodcinkach,ważniejszeopcje-nniezamieniajadresuIPhostaktóryodpowiedziałnanazwędomenową
nmapskanersieciowy-sprawdzaniedostępnychhostówwsieci,otwartychportów,itd
arpingnarzędziedopingowaniazwykorzystaniemzapytańARPzamiastICMPistnieją dwie zasadnicze odmiany: z iputils oraz z synscan; ta druga zawarta w debianowympakiecie"arping"umożliwiatakżepingowaniepoadresieMAC(alenieprzezRARP,boonniedotegosłuży),abytojednakdziałałohostdocelowyniemożeignorowaćpingówrozgłoszeniowych,metodaobejściaopisanajestwREADMEarping'a
arp-scanwyszukiwanie hostów w oparciu o zapytania ARP (można powiedzieć że jest to równoważneuruchamianiukomendyarpingwpętli)
DNS
dig[opcje]nazwa[typRekordu]narzędzia do uzyskania informacji z DNS, pozwala na określenie poprzez @adres serwera którychcemyodpytaćoraznaokreślenie(poprzezdrugiargument)typurekorduktórychcemyuzyskaćzamiast typu rekordu można podać: ANY (powoduje odpytanie o wszystkie rekordy) lub AXFR(powodujewysłanieprośbyotransfercałejstrefy,działajeżelidanyhostmaprawotransferucałejstrefyzdanegoserwera)
host[opcje]nazwa|ip[server]narzędziadozamianyadresówdomenowychnaIPiodwrotnieorazwyciąganiainnychinformacjizDNS(np.rekordyMX)
nslookup[opcje]nazwa|ip[server]narzędziadozamianyadresówdomenowychnaIPiodwrotnieorazwyciąganiainnychinformacjizDNS(np.rekordyMX)
dnstracerśledzenietrasyzapytańDNS
dnswalkdebugerDNS
IPv6
ndisc6testowanieICMPv6NeighborDiscovery
rdisc6testowanieICMPv6RouterDiscovery
rltraceroute6trasapakietówdodanegohostaIPv6zużyciemUDP/ICMP
tcpspray6pomiarprędkościłączazużyciemTCP/IPDiscard/Echo
na6/ns6wysyłaniepakietówNeighborAdvertisement/Solicitation
ra6/rs6wysyłaniepakietówRouterAdvertisement/Solicitation
ni6/rd6wysyłaniepakietówICMPv6NodeInformation/Redirect
scan6skanowaniesieciIPv6
debugowaniełącznościsieciowej
netcatlubnclubnetcat6program pozwalający na wysyłanie pakietów TCP i UDP z definiowaną przez nas zawartością,oraz odbiór pakietów TCP i UDP (słuchanie na wskazanym porcie), umożliwia m.in. testowanieusług sieciowych (takich jak smtp, www, jabber, ...); uwaga: występuje w kilku wersjachróżniącychsięopcjami
telnetprogram umożliwiający zdalny (nieszyfrowany, łącznie z hasłem!) dostęp do powłoki, a także(podobniejaknetcat)m.in.testowanieusługsieciowych
swaksnarzędziedotestowaniaSMTP
tcpdumpprzechwytuje komunikację sieciową celem analizy nagłówków lub pełnej zawartości pakietów(wsparcie dla niektórych z protokołów warst wyższych wymaga doinstalowania - np. obsługęDHCPzapewniadhcpdump)
wiresharklubtsharkprzechwytuje komunikację sieciową celem analizy nagłówków lub pełnej zawartości pakietów,wspiera dekodowanie wielu protokołów warstwy aplikacyjnej, wireshark posiada graficznyinterfejsużytkownika,tsharkjestwersjąkonsolową
informacjeowykorzystaniuiprędkościsieci
netstatinformacjeosieci
iptrafmonitorIPLAN
nloadgraficzne(ncurses)pokazywaniewykorzystania(prędkości)interfejsówsieciowych
ttcptestujeprędkośćpołączeniasieciowego(stronadomowa,najnowszawersjaorazmutacja)
iperfpomiarprędkościpołączeniasieciowego
Konfiguracjasieci
podstawowakonfiguracjainterfejsów
ipinformacjenatematinterfejsówsieciowych(adresówIP,etc)iroutingóworazichkonfiguracja
ifconfiginformacjenatematinterfejsówsieciowych(adresówIP,etc)orazichkonfiguracja
routekonfiguracjaroutingu
arpwyświetlanieimanipulowanietablicąprotokołuARP
dhclientkonfiguracjaautomatycznainterfejsuwoparciuoDHCP
konfiguracjamechanizmówjądrowychwLinuxie
vconfigkonfiguracja(tagowanych)VLANów
brctlkonfiguracjabridge'ów(softwarowegoswitchadziałającegowwarstwie2)
ifenslavekonfiguracjabondingu
iptablesjądroweregułyfiltrowaniairoutingupakietów
iptablesjądroweregułyfiltrowaniairoutingupakietówdlabridge'ów
iptablesjądroweregułyfiltrowaniairoutingupakietówwwarstwiedrugiejOSI
konfiguracjakartsieciowych(wtymWiFi)
ethtoolkonfiguracja kart ethernetowych pod względem takich parametrów jak prędkość transmisji,duplex,wakeonlan,etc
iwconfigkonfiguracja (większości - do części trzeba użyć wlanctl-ng) bezprzewodowych interfejsówsieciowych
wpa_supplicantkonfiguracjawiększościbezprzewodowychinterfejsówsieciowychzwsparciemdlaWPA
wpa_clikonfiguracjawiększościbezprzewodowychinterfejsówsieciowychzwsparciemdlaWPA
iwlistdodatkowe informacje z bezprzewodowych interfejsów sieciowych (przydatna zwłaszcza opcjascanpokazującadostępnesieci
Narzędziaprogramistyczne
clanglubgcckompilatorC
clang++lubg++kompilatorC++
ldlinker
python3lubpythoninterpreterPythona
cmakesystemgeneracjiplikówMakefile
makesystembudowaniaaplikacjiwoparciuoplikiMakefile
lddwyświetlaniewykorzystywanychprzezprogrambibliotekdynamicznych
ldconfigkonfiguracjabibliotekdynamicznych(m.in.określanieścieżekwjakichsąwyszukiwane),refreshbazydostępnychbibliotek;patrzteż/etc/ld.so.conf
git,hg,svnsystemykontroliwersji
Narzędziaadministracyjne
shutdownwyłączanie i restartowanie systemu (komputera), podobnie do bezpośredniego operowania napoziomachinit
partedlubfdiskoglądanieimodyfikowaniepodziałudyskunapartycje
mount/umountmontowanie/odmontowywaniesystemuplikówwartozwrócićuwagęnaopcjęmontowania-obindumożliwiającąmontowaniekataloguwinnymkataloguorazna-oremountumożliwiającązmianęparametrówpodmontowanegosystemuplików
chroot/fakechroot/schrootnarzędziadouruchamianiaprogramu/programówzpodmienionymkatalogiemgłównym
dd/ddrescuetworzeniekopiurządzenia/plikuobrazu(ddrescuezlepszątolerancjąbłędówodczytu)
aptlubaptitudemenagerpakietówsystemachopartychoDebiana
dpkgniskopoziomowenarzędziedozarządzaniapakietamideb
adduser/deluserorazaddgroup/delgroupzarządzanieużytkownikami
dmesglogijądra
lspcilistowanie urządzeń podłączonych do magistrali PCI, PCI-express, ... (aktualizacjia bazyidentyfikacyjnejupdate-pciids)
lsusblistowanieurządzeńpodłączonychdomagistraliUSB
lsscsilistowanieurządzeńobsługiwanychprzezpodsystemSCSI(m.in.SATA,SCSI,FC)
dmidecodeodczytinformacjiosprzęcie
ddcprobeodczytinformacjiomonitorze
smartctlodczytinformacjiS.M.A.R.T.dotyczącychdyskutwardego
hdparm/sdparmustawieniaparametrówdyskówtwardych(np.opcja-Sustawiaczaspojakimusypianyjestdysk)
hddtempnardzędziedokontrolitemperaturydyskutwardego
mbmon/xmbmonmonitorowanieparametrówpracypłytygłównej
sensorsdanezczujnikówwkomputerze(takiejaknapięcia,temperatury,prędkościwentylatorów)
acpistanzasilania/baterii
Innenarzędzia
echo/printfwypisujeargumentynastandardowewyjście
xargspobierzargumentyzstdin
mkfifotworzy łącze nazwa (specjalny plik który może być wykorzystywany do komunikacji międzyprocesaminazasadziepodobnejdo|)
seq
wypisujekolejneliczby(przydanenp.wfor)tee
zapisujestdindopodanegopliku,równocześniewypisującgonastdoutfile
rozpoznajetypplikuiconv
konwersjekodowańplikówtekstowychkonwert
konwersjekodowańplikówtekstowych–zarównopomiędzyróżnymikodowaniamidanegozbioruznaków, jak też pomiędzy kodowaniami nie pokrywającymi się czy też kodowaniami znaków 8bitowychnamniejszejilościbitów,naprzykład:konwertutf8-ascii"inteligentnie"usunieznakinieasciizplikukodowanegowutf-8(np.znaczkizpolskimiogonkamizamieninaodpowiednieznakiASCIIbeztychogonków);konwertqp-8bitpozwolizamienićkodowaniequotedprintablenanormalne8bitowe(rtf-8bitzrobitozkodowaniemrtf'u)
mewencode/mewdecodeprogram(stanowiącyczęśćpakieunarzędzidodatkowychdlakilentapocztowegoMew)doobsługikodowańmime(wtymQuoted-Printable,base64),m.in.zmieniakodowaniebase64na8bitowe
qprintprogramdokodowaniaidekodowania"Quoted-Printable"
base64programdokodowaniaidekodowaniabase64
stringswypisujesekwencjeznakówdrukowanych(określaniezawartościplikównietekstowych)
whichkomendazwracawykonywanąścieżkę/polecenieprzywykonywaniukomenda
datedataiczas,programtenpotrafitakżeprzeliczaćdatęiczas-np.date-d@847103830'+%Y-%m-%d %H:%M:%S', date -d '1996-11-04 11:37:10' '+%s', date -d '1996-11-04 11:37:10 +3week-2days'
calkalendarz
calcalboapcalczaawansowany kalkulator o składni podobnej do C umożliwiający wykonywanie mi.in. operacjilogicznych(wtymbinarnych)
bckalkulator(wartorozważyćutworzeniealiasualias'bc'='bc<(echoscale=3)'(abyzarazpostarciemieć3miejscapoprzecinku)lubalias'bc'='bc-l'(dlapełniejszejprecyzji)
numconvprogramdokonwersjisystemówliczbowychopróczsystemówpozycyjnychoróżnychpodstawachobsługujetakżeinnesystemyliczbowe-np.rzymski
gnuplotrysowaniewykresów
clearczyściterminal
resetprzywracaustawieniaterminala(np.gdypowyświetleniuplikubinarnegosądziwnekrzaczki)
sttykonfiguruje terminal (np. port szeregowy /dev/tyyS* , późniejmożemykorzystać z niegonp. zapomocącat,echo, ... iprzekierowańpotoków-np.cat/dev/ttyS0>~/serial.logbędzielogowałoinformacjezportudowskazanegopliku)
startxuruchamiaśrodowiskograficzne
xinituruchamia program w środowisku graficznym (wraz z startem środowiska), np. xinit -e__WYBRANY_PROGRAM__--:1uruchomiX'ynaekranie1(dawniejAlt+Ctrl+F8,obecnienaogółnabieżącymterminalu)awnichwskazanyprogram
xsetkonfigurowanie ekranu x-serwera, np. sleep 1; xset dpms force off spowoduje wyłączenie(uśpienie)monitora
Standardoweusługi
Systemy operacyjne zapewniają także szereg usług. Znaczna część z nich dostępna jest z poziomubibliotekistandardowejC(np.obsługaplików,komunikacjisieciowej,zamianynazwdomenowychoraznazwusługnaadresynumeryczne).Inneznichrealizowanesąpoprzezdedykowaneprocesydziałającew tle (bez bezpośredniej interakcji z użytkownikiem), tzw. daemon-y. Poniżej omówione zostałyniektórezusługzapewnianychprzezsystemoperacyjny.
Zamiananazwnaadresynumeryczne
BibliotekastandardowazapewniamożliwośćzamianynazwhostównaichnumeryIP,zamianynazwusługnanumeryportów.Funkcjonalnośćtakorzystazm.in.następującychplikówkonfiguracyjnych:/etc/services-mapowanienazwyusługinanumerportu/etc/hosts-mapowanienazwhostównanumeryIP(lokalnabaza)/etc/resolv.conf-adresyserwerówDNSdoktórychmogąbyćkierowanezapytaniaoadresyhostów
Pocztaelektroniczna
Typowo system zapewnia obsługę (co najmniej lokalnego) dostarczania poczty elektronicznej. Dowysyłania listów można skorzystać z komend mail lub sendmail. Z kolei komenda sendEmail pozwalatakżenawysyłaniepocztyprzezwskazanyserwerSMTP.
Planowaniezadań
Typowosystemzapewniausługęuruchamianiazadańozadanymczasie.Zusługitejmożnaskorzystaćprzypomocypoleceń:crontabpozwalaoglądaćiedytowaćtablicezaplanowanychzadańcyklicznych(dlacron'a)atpozwalajednorazowozaplanowaćzadanie
Plikikonfiguracyjnecrona/obsługiwanecrontab-emmająpostać:minutygodzinadzienMiesiacamiesiacdzienTygodniapolecenie.Wpisoznaczażepoleceniemazostaćwykonanejeżeliwszystkiewarunkibędąspełnione, jeżeli jakiś warunek nie jest nam potrzebny można użyć gwiazdki *, z kolei */n oznaczawykonywaniejeżelidanawartośćjestpodzielnaprzezn.Np.:*/203**1lsoznaczawykonaniekomendylswkażdyponiedziałekogodzinie3:003:20i3:40
Standardowewyjście,wyjściebłęduorazpowiadomienieoniezerowymkodziepowrotudomyślniesąwysyłane na lokalny adres mailowy użytkownika będącego właścicielem danego contaba. Niekiedydostępnyjesttakżeanacronpozwalającynamniejprecyzyjneplanowaniezadań
Zdalnydostęp-SSH
SerwerSSHzapewniazdalny,szyfrowanydostępdokomputeranaktórymjesturuchomionyzinnychhostów.UsługaSSHpozwalanakopiowanieplików(sftp,scp,rsyncoverssh),montowaniezdalnychsystemówplików(sshfs),tunelowanieprotokołuX'ów(serweraśrodowiskagraficznego,dziękiczemumożna używać zdalnych aplikacji z GUI) oraz tworzenie szyfrowanych tuneli (nasłuchujących napołączeniaprzychodzącetakpostronieklientassh,serwerassh,jakteżpełnychtuneliVPN).
PodsumowanieWkontaktachztechnologią,byciudobrym"komputerowcem",elektronikiem,...najważniejszewydajesiębyć bawienie się technologią, eksperymentowanie, łączenie i integrowanie różnych systemów itechnologii,poznawanienowego,zagłębianiesięwszczegółyabynietylkowiedzieć jaktoobsłużyć,aleteż wiedzieć jak działa, traktowanie problemów jako wyzwań, ... oraz czerpanie z tego radości. Dookreślenia kogoś o takiej postawie, takim podejściu do techniki, najlepszym terminem byłby haker,pomimoiżjesttoterminróżnierozumiany,uwieluosóbwywołującynegatywneskojarzenia,wydajesięonjednaknajbliższytakiejpostawieżyciowej.
Zajmowanie się technologią (a szczególnie z takimnastawieniem)oznacza taknaprawdęciągłeuczeniesię-jeżelisięnierozwijasz,jeżelizostajeszwmiejscutotaknaprawdęsięcofasz.Zatemjużodsamegopoczątku poznawania świata elektroniki, programowania, komputerów, sieci komputerowych, itp., przynauce tych dziedzin bardzo istotne (jeżeli nie najistotniejsze) wydaje się bawienie się tym, otwartepodejściedostawianychproblemów,eksperymentowanieisamodzielneszukanierozwiązań.
Niemawiększegosensuuczeniasięszczegółów,konkretnychimplementacji,itpnazapas.Jeżelimożemysobie tylko na to pozwolić warto uczyć się na "żywych" zastosowaniach (rozwiązując problemy, któregdzieś w jakiś sposób samoistnie się pojawiły), przy takiej nauce warto też pamiętać o ogromnychzasobachInternetu.Przypoznawaniuobsługibądźkonfiguracjijakiegośnowegonarzędziarównieistotnejak zapoznanie się z dokumentacją, podręcznikiem jest wypróbowanie różnorakich opcji, ich różnychkombinacji w praktyce, poszukanie takiego sposobu konfiguracji, użytkowania (takiego stylu) jaki jestnajbardziejodpowiednidlanasidlarozwiązywanegoproblemu.Wrozwiązywaniukonkretnychzagadnieńnajistotniejszejestwiedziećjaksiędotegozabraćiumiećdaćsobieradę.
Wydajesiężewłaśniewtychdziedzinachczęstoodwiedzyszczegółowej,ważniejszajestszerokawiedzaogólna(orazoczywiścieodpowiedniepredyspozycjeichęci),wrazzumiejętnościamiszukaniainformacji(i
wiedzągdzienależy jej szukać).Częstoniemanawetmożliwościposiadaniapełnejwiedzynapoczątkurozwiązywania jakiegoś problemu, istotniejsza jest ogólne zrozumienie "jak to działa", umiejętnośćkorzystania z dokumentacji, wyszukiwania i sprawdzania szczegółów oraz umiejętność kombinowania /informatyczny spryt. Ważna jest także sporą doza praktyki (rzeczywistość tworzy sytuacje które nieśniłyby się teoretykowi ...) i tak zwane obycie z techniką / technologią. Gdy napotka się jakiś problemnależy próbować go rozwiązać, eksperymentować, szukać porady (ale raczej na zasadzie "że chcemydostaćwędkęanierybę")inieżałowaćnatoczasu.
InformacjacyfrowaPodstawowym zadaniem chyba wszystkich systemów komputerowych i telekomunikacyjnych orazogromnej większości systemów elektronicznych jest przetwarzanie lub przekazywanie informacji.Obecnie jest to w znacznej większości informacja cyfrowa (w odróżnieniu od analogowej jest ona"skwantowana" - sygnałbędący jej źródłemzmieniającysięwsposóbciągłyzostałpoddanyprocesowipomiaruizamianynaliczbęoskończonejdokładności).Faktdyskretyzacjizbioruwartościoraz(możliwedo wprowadzenia dzięki postaci liczbowej) sumy kontrolne umożliwiają wierne kopiowanie informacji.Dziękiwprowadzeniutegododatkowegomatematycznegopoziomuwzapisieinformacjiodrywamysiępoczęści od ograniczeń naszej fizycznej rzeczywistości; "bity to nie atomy" i fizyka (w szczególnościkwantowa)ichniedotyczy.
Podstawową jednostką informacji jest bit, mogący przyjmować dwa rozróżnialne stany nazywanezazwyczajzero ijeden,będącyodpowiedziątyputak/nie.Przypomocymniejszejilościstanówniejestmożliweprzekazanieinformacji(pozorniemogłobywydawaćsiężeniekiedywystarczyjedenstan-np.podnosimynrazychorągiewkęiwtensposóbprzekazujemyliczbęn,jednaktutajteżjestukrytydrugistan - chorągiewka opuszczona). Z stanami tymi łatwo związać odpowiednie stany napięciowe nawejściach/wyjściachukładówelektronicznych-np.napięciepowyżejXvoltów("jestnapięcie")oznacza1,napięcie poniżej Y voltów ("brak napięcia") oznacza 0. Wydaje się że właśnie z tych dwóch powodówsystemdwójkowy (mający tylko dwie cyfry - 0 i 1) wraz z logikądwuwartościową zyskał tak dużezastosowaniewelektronicecyfrowejikomputerach.
ElektronikaElektronika (zarówno analogowa jak i cyfrowa) zajmuje się zasadniczo przetwarzaniem informacji wpostaci sygnałów elektrycznych. Podstawowymi pojęciami jest tutaj prąd (przepływ ładunku) oraznapięcie(różnicapotencjałówczylisiłatenprzepływwymuszająca).Elementyelektronicznepodzielićmożemynaelementybierne(oporniki,kondensatory,cewki,diody) -wpływającenaprzepływprąduwsposób nieregulowany oraz elementy aktywne (których działanie w odróżnieniu od biernych jestregulowane na drodze sygnałów elektrycznych). W elektronice (zwłaszcza cyfrowej) często dużoważniejszym pojęciem niż prąd jest napięcie, a dokładniej nawet tylko potencjał w odniesieniu doumownegopotencjałuzerowego-masy(GND).
Dlaprzetwarzaniadanychprzezwspółczesnąelektronikęnajważniejszymzpodstawowychjejelementówwydajesiębyćtranzystor-jesttoelementoregulowanympoprzezprzyłożenieodpowiedniegonapięciaoporze elektrycznym (może być zatem wykorzystywany jako elektronicznie sterowany przełącznik).Obecnie większość tranzystorów wchodzących w skład urządzeń znajduje się we wnętrzach układówscalonych,liczącychczęstotysiąceczynawetmilionytranzystorów.
Podstawowymidlatechnikicyfrowejukładamiscalonymisąbramkilogicznerealizująceposzczególnefunkcjelogicznenaprzetwarzanychsygnałachorazrejestrypozwalającenazapamiętaniestanu(jakiejśinformacji).Jednaktakżeibramkiustąpiłyjużmiejscaukładomprogramowalnymzłożonymztysięcytranzystorów, bramek i tym podobnych elementów - np. programowalnym układom logicznym,procesoromczyteżmikrokontrolerom(zawierającymtakżepamięćzmienną-dladanychprogramuorazpamięć do przechowywania samego programu); sprowadzając w zasadzie elektronikę opartą naelementachdyskretnychdorolipomocniczej.
Właśnieniczymmniejaniwięcejtylkotakimprogramowalnymurządzeniemelektronicznym,ozdolnoścido przetwarzania znacznych ilości informacji (w postaci liczb) w krótkim czasie (znacznej mocyobliczeniowej),jestwspółczesnykomputer.Złożonyonjestzasadniczozprocesora,pamięcioperacyjnej(wrazzukłademodpowiedzialnymzaumożliwieniedostępudoniejprocesorowi-kontrolerempamięci)ipamięcistałej (dysktwardy itp.)służącejdoprzechowywaniaprogramówidanych.Niezależnieodrolijakąpełni(maszynadopisaniaczygrania,serwerWWWczyteżserwernadzorującyprocesywreaktorzejądrowym,...)każdykomputertylkoiwyłączniewykonujejakiśprogram.
Poprzez powyższe twierdzenie, że komputer wykonuje tylko i wyłącznie program będący ciągieminstrukcji, nie twierdzę że nie może istnieć coś takiego jak sztuczna inteligencja, a nawet sztucznaświadomość. Obecnie istnieją systemy zdolne do samodzielnej nauki na podstawie historycznychdoświadczeń,istniejąsystemydecyzyjneorazwieleinnychrozwiązańktórewjakimśstopniumożnabyuważaćzainteligentne.Zproblememsztucznejinteligencjizwiązanajestgłównienieprecyzyjnośćtegoterminu (istnienie wielu sprzecznych definicji). Wydaje się, że nawet człowiek nie jest w stanieprzekonaćinnejosobyotymżejestistotąinteligentnąatymbardziejświadomągdytamtaprzyjmieinnezałożenie.
B
C
E
T1
AK
D1R3
2k
+5V
R2
1k
1 2S1
R1
25k
U1
1 2C1
100uF
R4
1k
P1
+5V
W rozumieniu elektroniki ważna jestumiejętność przeanalizowania prostegoukładu, ustalenia / zrozumienia jak ondziała.Dla przykładu: obok przedstawiony jestukład wykorzystujący zarówno elementycyfrowe, jak i analogowe do uzyskaniajakiegośefektu.Jakijestceldziałaniategoukładu?Jakondziaławszczegółach?
1. U1 jest dwu wejściową bramkąlogiczną AND (na wyjściu zwraca stan logiczny 1 gdy na obu wejściach ma stan logiczny 1,któremuwtymwypadkuodpowiadastanwysoki+5V),do jednegozwejśćpodłączony jest jakiśsygnałsterującyzzewnątrz(P1)dodrugiegopodłączonyjestnatomiastprzełącznikS1zwierającydomasy.
2. RezystorR1podłączonydo+5Vzapewniaiżgdyprzełącznikniejestzwartytodowejściabramkiprzyłożony jest stan wysoki (niektóre z układów scalonych mają takie rozwiązaniezaimplementowanewewnętrznie),agdyzwieramyS1toograniczapłynącyprąd-wtensposóbnawejściebramkimożebyćpodanelogiczne1lubzerobezkoniecznościstosowaniaprzełączaniaibezobawyozrobieniezwarcia.
3. Wyjście bramki poprzez kolejny opornik (R2), który ograniczaprądpobierany zwyjściaukładu,steruje tranzystorem NPN T1 (przewodzi on gdy napięcie miedzy bramką (B) a emiterem (E)przekroczyokreślonąwartość).
4. Wprowadzenie tranzystora w stan przewodzenia powoduje przepływ prądu przez LED D1 orazrezystorR3,któryograniczatenprąddowartościodpowiedniejdlaD1(oczywiścietakżeT1musibyćdostosowanydowartościtegoprądu);wartotutakżezwrócićuwagęnapolaryzacjęD1(LEDjakkażdadiodaprzewodzitylkowjednąstronę).
5. Kondensator C1 wraz z rezystorem R4 (a także R3) powoduje spowolnione wygaszanie D1 -kondensatorrozładowujesięprzezR4gdyT1przewodzi,natomiastpozaprzestaniuprzewodzeniaprzez T1 kondensator ten ładuje się przez R3 i R4 podtrzymując przez pewien czas świeceniediody(diodaprzygasapowoli,gdyżspadananiejnapięciewskutekprocesuładowaniaC1).
ProgramowanieProgram jest to ciąg instrukcji (głównie operacji matematycznych i logicznych), zapisany w językuzrozumiałymdladanegoprocesora(kodmaszynowypowstającywwynikukompilacjikodustworzonegow języku wyższego poziomu). Wśród tych instrukcji szczególne miejsce zajmują instrukcje skoków(warunkowych i bezwarunkowych), one właśnie umożliwiają warunkową realizację fragmentówprogramu oraz warunkowe powtarzanie (iterację) fragmentów programu. Za szczególny przypadekinstrukcji skoku można uważać instrukcję wywołania procedury, powodującą przekazanie stosownychinformacji i rozpoczęcie wykonywania podprogramu (poprzez warunkowe wywoływanie tej samejprocedury z jej wnętrza możemy otrzymać "konkurencyjny" do iteracji sposób powtarzania fragmentuprogramu-rekurencję.
Podstawądziałaniakażdegoprogramujestjakiśalgorytm, jesttopojęcietrochębardziejabstrakcyjneniż program (zwłaszcza rozumiany jako kod maszynowy) - ogólnie mówiąc jest to skończony ciągczynności prowadzących do zrealizowania jakiegoś zadania. Jak już wspomniałem oprócz kodumaszynowego (złożonego z numerów rozkazów i ich parametrów) są również języki programowania.Najbardziej podstawowym jest asembler, który pozwala używać łatwiej zrozumiałych dla człowiekanazw zamiast numerów instrukcji, rejestrów (w których procesor przechowuje wartości którymioperuje), ... . Jednak jego instrukcje odpowiadają niemalże w 100% instrukcjom procesora (kodowimaszynowemu), dlatego też jest bardzo silnie zależny od danej architektury sprzętowej (modeluprocesora), powoduje to problemy z przenoszeniem programów pisanych w asemblerze na innearchitektury, to było jednym z powodów stworzenia językówwyższego poziomu. W językach takichtreść algorytmu wyraża się przy pomocy poleceń danego języka będących bytami bardziejabstrakcyjnymiodinstrukcjiprocesora(np.pojęciezmiennejioperowanienaniejanienamiejscachwpamięci irejestrach).Obecnieasembleraużywasięwzastosowaniachwymagającychdużejwydajności(zarówno w oddzielnych aplikacjach jak i fragmentach większych programów) bądź dla urządzeń oniewielkichrozmiarachpamięci.
TelekomunikacjaOpróczprzetwarzaniainformacjilicznesystemyzajmująsięjejprzekazywaniem.Abymógłzajśćproceskomunikacji musi istnieć jakieś medium transmisyjne, które będzie odpowiedzialne za fizyczneprzekazaniesygnałuzawierającegoinformację.Wtelekomunikacjiprzekaztenodbywasięzazwyczajzwykorzystaniem zjawiska przepływu prądu przez przewodnik (tradycyjna łączność kablowa), bądźrozchodzenia się fali elektromagnetycznej (łączność radiowa, światłowody, ...). Bardzo istotne jestdopasowanieparametrówmediumtransmisyjnego,urządzeńnadawczychiodbiorczychdosygnałuktóryzamierzamy transmitować, na przykład w przypadku kabli jest to częstotliwość którą są one w stanie
przenosićbezzakłóceń(głównieonaodpowiadazaszybkośćtransmisji inajczęściej jestrzędukilkusetMHz) oraz impedancja (wyrażana w omach, sygnały które transmitujemy są sygnałami zmiennymidlategojestonaważnymparametremprzewodu...).Jednakpomimotozawszenależymiećświadomość,żetotylkokabel,któryprzewodzielektronyiniezależnieodparametrówjakośbędzietorobił....
Wtradycyjnychsystemachtelekomunikacyjnychsygnałbyłbezpośrednioinformacją,ajegodotarciedoodbiornika oznaczało że informacja jest przeznaczona dla niego (telefonia) bądź dla każdego (radio,telewizja - systemy rozgłoszeniowe). Obecnie coraz większą rolę odgrywają komutowane siecipakietowe, gdzie informacja nie jest tak ściśle związana z sygnałem. Dla przykładu w telefoniizrealizowanie każdego połączenia wymagało zestawienia go - odpowiedniego przełączenia styków wcentralach(komutacjiłączy);wInternecieinformacjapodążaćmożeróżnymidrogami(niejesttworzonadroga specjalnie dla danego połączenia) i na podstawie adresu odnaleźć host docelowy (jest tokomutacjapakietów).Wsieciachpakietowychwłaściwainformacja(jeżeli jestzbytdługa)dzielonajestna części, do każdej części dodawane są informacje kontrolne - nagłówek (zawierający m.in. adresodbiorcy). Tak utworzone pakiety podróżują niezależnie od siebie przez sieć do odbiorcy (bezzestawianiawtymceluspecjalnegofizycznegopołączenia).
Bardzoistotnymelementemjestadresacja(jestonaniezbędnaabyinformacjamogłabyćkierowanadokonkretnegohosta-inaczejmamysiećrozgłoszeniowa(np.telewizja)):każdyhostwsiecimusiposiadaćunikalny (w ramach tej sieci) adres (chyba zawsze o ustalonej długości - nie jestem w staniezagwarantować ze ktoś, gdzieś nie stworzył protokołu pakietowego z adresami zmiennej długości),częstowydzielasię równieżpodsieci,posiadająoneswójadres (naogół jest towspólnaczęśćadresuwszystkich hostów podsieci dopełniona zerami), adres określający ile adresów jest w podsieci () orazadresnaktóryreagowaćpowinienkażdyhostwtejpodsieci(adresrozgłoszeniowy).Wprzypadkuchybanajpopularniejszychobecniesieci IPwielośćpodsieci określana jestprzezmaskępodsieci, którapowykonaniu binarnego AND z dowolnym adresem hosta tej sieci da adres sieci. W związku z tym iżbinarnie maska składa się z nieprzerwanego ciągu jedynek oraz nieprzerwanego ciągu zer, jest onaczęstozapisywana jestwpostaciprefixowej, czyli liczbybitówmającychwartość jeden.Wsieciach IP(oprócz samego Internet Protocol - odpowiedzialnego za adresację itp) należy także wspomnieć oprotokołachtakichjak:ICMP-zapewniającymprzesyłkomunikatówtechnicznych,orazUDPczyTCP-umożliwiających przesył danych poprzez sieć IP (odpowiedzialne one są m.in. za adresację usług nadanymhościepoprzeznumeryportów,TCP czuwa takżenadpoprawnością transferu - kontroluje czydanedotarły i czydotarłynieuszkodzone).Protokół IPoprócznajbardziejdlaniego typowej transmisjijeden do jednego (unicast) umożliwia transmisję rozgłoszeniową (broadcast - jeden do wszystkich wsieci)imulticast(jedendowielu).
OczywiściesieciteleinformatycznetonietylkoIP-należykonieczniewspomniećoprotokołachwarstwwyższych - takich jakHTTP (siećWeb),SMTP (e-mail), ... - zapewniających realizację typowychusługsieciowychorazstandardachzwiązanychzkonkretnąrealizacjąsprzętowąsieci -np.ethernet (będącynajpopularniejszym standardem sieci lokalnych - LAN). Ze sprzętową realizacją sieci wiąże się m.in.pojęcietakiejaktopologiasieci-czylizasadałączeniahostów(gwiazda-wszystkiedojednegopunktu,drzewo - wiele gwiazd łączonych w gwiazdy, magistrala - od jednej linii każdy host, ...).Najpopularniejsząobecnietopologią(przekładającąsiętakżenainneinstalacje-np.elektryczną,gdziejednak dalej istotna jest magistrala) jest topologia gwiazdy, gdzie mamy doczynienia z punktamidystrybucyjnymi(wprofesjonalnympodejściurealizowanymiwoparciuoszafykrosowniczeispecjalnieprzeznaczonedotegocelupomieszczenia)odktórychodchodzątrasykablowe.Przyrealizacjisystemówtelekomunikacyjnych (i innych teleinformatycznych oraz elektrycznych) warto pamiętać o stosownejdokumentacjitakprzebiegutraskablowych,jakisamejinstalacjiorazpunktówdystrybucyjnychatakżeprzejrzystości i opisaniu samych instalacji. Warto tutaj także zwrócić uwagę na "nie informatyczne"bezpieczeństwo takich instalacji obejmujące takie zagadnienia jak zabezpieczenia przeciw pożarowe,przeciw przepięciowe oraz monitoring i kontrolę dostępu do pomieszczeń przeznaczonych nawspomnianeinstalacje.
OprogramowanieOczywiścieabysięzajmować,bawićkomputerami,elektroniką,sieciamitelekomunikacyjnymikoniecznajestwiedzanatematsamejobsługikomputerów-zwłaszczasystemówunix'owatych.Wtychsystemachposzczególne osoby pracują na własnych kontach (identyfikowanych loginem i chronionych hasłem),szczególnym przypadkiem jest konto super użytkownika "root" - służy ono do czynnościadministracyjnych i umożliwia zrobienie z systemem (niemalże) wszystkiego. Standardowo stosowanyjest też znany z adresów e-mail zapis z małpą - umożliwiający globalną identyfikację użytkownika [email protected]. Z użytkownikami związane są także uprawnienia - definiowane (w podstawowymwariancie) niezależnie dla właściciela, grupy i wszystkich innych w dziedzinach odczytu, zapisu iwykonania.
Powłoka tekstowaoparta jestnapoleceniach (będącychnajczęściejosobnymiprogramami)doktórychprzekazywane są opcje i argumenty (oddzielane są one - zarówno od siebie jak i od nazwy programuspacjami), opcje na ogół zaczynają się od myślnika (jednoliterowe) bądź dwóch myślników(wieloliterowe), ale są od tego wyjątki. Powłoka umożliwia także pracę w trybie wsadowym (nieinteraktywnym)-jesttojużjęzykskryptowysh/bash.Informacjeoprawiekażdymprogramie,większości
plików konfiguracyjnych oraz funkcjach biblioteki standardowej C można znaleźć w podręcznikusystemowym(polecenieman).
EpilogWspółczesna technika umożliwia korzystanie z komputera, a nawet tworzenie oprogramowania bezznajomości niskopoziomowych mechanizmów działania tych urządzeń. Wydaje się jednak, że abyzrozumieć współczesną technikę, być dobrym programistą, administratorem, ... poznanie tychmechanizmówwydaje się niezbędne (a na pewno jest bardzo pomocne) i jest też niewątpliwiebardzoprzydatnegdychcemyzrobićcoś"bliżejsprzętu"....
Przyrobieniuczegokolwiekwartopamiętaćostandardachinormachtechnicznych,onenaprawdęsą(wzdecydowanejwiększości) tworzonepo toabyułatwićwszystkimżycie (jakbywyglądał Internetgdybykażdyportalużywałwłasnychstandardówe-mailiwww?).Należyteżtaktworzyć,abytocozrobiliśmy,napisaliśmybyłoprzejrzysteizrozumiałedlainnychoraz(zaparęmiesięcyczylat)dlanassamych-abykod był czytelny, dobrze skomentowany, a cały projekt posiadał dobrą i szczegółowądokumentację(wiem że często się nie chce, ale naprawdę warto ...). Należy się także wystrzegać rozwiązańprzekombinowanych, stanowiących przerost formy nad treścią (trzymać się reguły KISS). Należypamiętać,żezanimzaczniemycośpisaćwartoposzukaćczyniemaczegośopodobnejfunkcji,bądźniemajakiśbibliotek,którezrobiązanaspołowępracy-niezawszewartoodkrywaćAmerykęnanowo;-).
Wszystkich czytelników zachęcam także do zapoznania się oprócz samego "vademecum" także zdolinkowanymimateriałamiorazprzedewszystkimdodużejporcjiobyciaztechnologią,samodzielnegozgłębiania wybranych zagadnień oraz dużej ilościpraktyki - bo to właśnie ona w tym wszystkim jestnajistotniejsza(atoniestetywymagadużoczasu).Ważnejestabyrobićtocosięlubi-zawszelepiejbyćdobrymsieciowcemzpowołanianiżkiepskimkoderem(inaodwrót).Dokładnykierunekkształcenianiejest bardzo istotny - lepiej żeby nie był zbyt odległy, ale i tak masy rzeczy trzeba się uczyć samemu.Wartomiećszerszespojrzenienabranże-tożespecjalizujeszsięnp.wsieciachnieoznaczaiżpodstawyprogramowania (zarówno web-owego jak i systemowego) czy też elektroniki i innych pokrewnychzagadnieńsązbędne -wręczprzeciwniemogąbyćdodatkowymatutem(nie tylkowCVale iwsamejpracy).ToczegosięnauczyszjestTwoje,alezdobytąwiedzę,doświadczeniewartonotować(gdyżzdarzasię ponownie odkrywać Amerykę i ze zdziwieniem stwierdzać "to ja się tym zajmowałem 10 lattemu???").
Literaturazakres
tematyczny nazwa autor licencja opis link
Elektronika
Elektronika LessonsInElectricCircuits
TonyR.Kuphaldt
DesignScienceLicense
Rozbudowanypodręcznikdoelektronikiodpodstaw EN
Elektronika Electronics wikibooks.org CC-SA Podręcznikdoelektroniki EN
Podstawyelektroniki
ElectronicsFundamentals wikibooks.org CC-SA Podręcznikpodstawelektroniki EN
Podstawyelektroniki PracticalElectronics wikibooks.org CC-SA
Przewodnikrozumieniaitworzeniaobwodówelektronicznych
EN
Podstawyelektroniki CircuitIdea wikibooks.org CC-SA Zbiórwyjaśnieńzasaddziałania
popularnychobwodów EN
Teoriaobwodów CircuitTheory wikibooks.org CC-SA Podręcznikdoteoriiobwodów EN
Teoriaobwodów Metodyanalizyobwodówliniowych
WojciechMeller CC-NC-SA Podręcznikdoteoriiobwodów PL
Elektronikaanalogowa AnalogueElectronics wikibooks.org CC-SA Podręcznikelektroniki
analogowej EN
Elektronikacyfrowa DigitalCircuits wikibooks.org CC-SA Podręcznikdoelektroniki
cyfrowej EN
Systemymikroprocesorowe MicroprocessorDesign wikibooks.org CC-SA Podręcznikprojektowania
systemówmikroprocesorowe EN
Systemymikroprocesorowe EmbeddedSystems wikibooks.org CC-SA Podręcznikdosystemów
wbudowanych EN
Automatyka ControlSystems wikibooks.org CC-SA Podręcznikdosystemówkontroliisterowania EN
Telekomunikacja CommunicationSystems wikibooks.org CC-SA Podręcznikdosystemówtelekomunikacyjnych EN
Podstawyinformatyki
Systemyoperacyjne PisanieOS Jarosław
Pelczariinni
CC-SA,oryginał:PD
Podręcznikprzybliżającyzagadnieniazwiązanezdziałaniemitworzeniemsystemówoperacyjnych
PL
Sterownikiurządzeń
LinuxDeviceDrivers,ThirdEdition
JonathanCorbet,AlessandroRubini,GregKroah-Hartman
CC-NC-SA
PodręcznikopisującyzagadnieniazwiązaneztworzeniemsterownikówurządzeńdlasystemuLinux
EN
Algorytmyistrukturydanych Algorithms wikibooks.org CC-SA Wprowadzeniedoalgorytmów EN
Algorytmyistrukturydanych DataStructures wikibooks.org CC-SA Wprowadzeniedostruktur
danych EN
Algorytmyistrukturydanych
AlgorithmImplementation wikibooks.org CC-SA Przykładyimplementacji
algorytmów EN
Językiprogramowania
C CProgramming wikibooks.org CC-SA PodręcznikprogramowaniawC EN
C ALittleCPrimer wikibooks.org CC-SA PodręcznikprogramowaniawC EN
C++ C++reference CC-SA PodręcznikreferencyjnydlaCiC++ EN
C++ C++Programming wikibooks.org CC-SA PodręcznikprogramowaniawC++ EN
CiC++ProgrammingLanguageConceptsUsingCandC++
wikibooks.org CC-SA Podręcznikwprowadzającydoprogramowania EN
Python ByteofPython/UkąśPythona SwaroopCH
CC-SA,przykłady:BSD
PodręcznikprogramowaniawPythonie
ENPL
Python DiveintoPython/ZanurkujwPythonie MarkPilgrim GNUFDL Podręcznikprogramowaniaw
PythonieENPL
PythonHowtoThinkLikeaComputerScientist:LearningwithPython
PeterWentworth,JeffreyElkner,AllenB.Downey,ChrisMeyers
GNUFDL PodręcznikprogramowaniawPythonie
ENEN
Python Non-Programmer'sTutorialforPython3
wikibooks.org CC-SA KursprogramowaniawPythonie
EN
PHP PHPProgramming wikibooks.org CC-SA PodręcznikprogramowaniawPHP EN
Bash AdvancedBash-ScriptingGuide
MendelCooper PD Podręczniktworzeniaskryptów
wbashu EN
AWK GAWK:EffectiveAWKProgramming
ArnoldD.Robbins GNUFDL PodręcznikdlajęzykaAWKw
odmianieGNU EN
AWK OpisjęzykaAWK T.Przechlewski
CC-BY-SAtype
WprowadzeniedoprogramowaniawAWK PL
AWK AWKReferenceCard/ŚciągadoAWK
ArnoldD.Robbins
CC-BY-SAtype
KartareferencyjnadlajęzykaAWK
ENPL
AWK AnAwkPrimer wikibooks.org CC-SA PodręcznikdlajęzykaAWK EN
JavaScript ProgrammingAjax wikibooks.org CC-SA PodręczniktechnologiiAjax EN
językiopisusprzętu ProgrammableLogic wikibooks.org CC-SA Podręcznikprogramowania
układówlogicznych EN
językiopisusprzętu VHDLforFPGADesign wikibooks.org CC-SA Podręcznikprogramowania
układówFPGAwVHDL EN
językiopisusprzętu
VHDLquickreferencecard
QualisDesignCorporation
CC-ND-SAtype KartareferencyjnaVHDL EN
Siecikomputerowe
TCP/IPLinuxNetworkAdministrator'sGuide,2ndEdition
OlafKirch,TerryDawson GNUFDL
PodręcznikopisującyzagadnieniazwiązanezsieciamiTCP/IPwsystemieLinux
ENPL
TCP/IPLinuxNetworkAdministrator'sGuide,3ndEdition
OlafKirch,TerryDawson CC-NC-SA
PodręcznikopisującyzagadnieniazwiązanezsieciamiTCP/IPwsystemieLinux
EN
TCP/IPComputernetworktechnologiesandservices
LorenzoDavid,LucaGhio
CC_SA
PodręcznikopisującyzagadnieniazwiązanezsieciamikomputerowymiTCP/IPiusługamisieciowymi
ENEN
TCP/IP Routingprotocolsandarchitectures LucaGhio CC_SA
Podręcznikopisującyzagadnieniazwiązanezroutingiemwsieciachkomputerowych
ENEN
Ethernet(LAN) LocalAreaNetworkdesign LucaGhio CC_SA
Podręcznikopisującyzagadnieniazwiązanezlokalnymisieciamikomputerowymi
ENEN
Telekomunikacja CommunicationNetworks wikibooks.org CC-SA
Podręczniksiecikomunikacyjnych(nietylkokomputerowychaletakżeradiowych,telewizyjnych,itp)
EN
Linux/BSD/Posix
PoleceniasystemówtypuPosix
UnixToolboxColinBarschel CC-SA
ZbiórużytecznychpoleceńsystemówUnix/Linux/BSD EN
Vim Ściągadovi T.Przechlewski
CC-SAtype
Kartareferencyjnadlaedytoravim PL
Vim Ściągadovi LaurentGrégoire GNUGPL Kartareferencyjnadlaedytora
vim EN
Debian DebianReference OsamuAoki GNUGPL PodręcznikDebiana EN
DebianTheDebianAdministrator'sHandbook
RaphaëlHertzog,RolandMas
CC-SA/GNUGPL
PodręcznikadministratoraDebiana EN
Debian DebianGNU/LinuxReferenceCard
W.MartinBorgert,HolgerWansing
GNUGPL KartareferencyjnadlaDebianGNU/Linux
ENPL
FreeBSD FreeBSDHandbook BSD-type PodręcznikdlasystemuFreeBSD
ENPL
Arch ArchLinuxWiki GNUFDL DokumentacjadlaArchLinux EN
PLDLinux Podręcznikużytkownika,administratoraitwórcy GNUFDL PodręcznikdlaPLDLinux
Distribution PL
Linux LinuxNetworking wikibooks.org CC-SA PodręczniksieciwśrodowiskuLinux EN
Językizapytańioznaczeń
SQL StructuredQueryLanguage wikibooks.org CC-SA Podręcznikdojęzykazapytań
bazdanychSQL EN
wyrażeniaregularne RegularExpressions wikibooks.org CC-SA Podręcznikwyrażeń
regularnych EN
XML XMLSchema wikibooks.org CC-SA PodręcznikSchcemyXML EN
LaTeX
TheNotSoShortIntroductiontoLaTeX/NiezakrótkiewprowadzeniedosystemuLaTeX
TobiasOetiker,HubertPartl,IreneHyna,ElisabethSchlegl
GNUGPL PodręcznikwprowadzającydosystemuskładutekstuLaTeX
ENPL
LaTeX LaTeX wikibooks.org CC-SA PodręcznikwprowadzającydosystemuskładutekstuLaTeX EN
Inne,ogólne,wielotematyczne
aparaturaprzemysłowa
LessonsInIndustrialInstrumentation
TonyR.Kuphaldt
DesignScienceLicense
Rozbudowanypodręcznikdoaparaturyprzemysłowejodpodstaw
EN
Wikipedia CC-SA Otwarta,wolna,wielojęzycznaencyklopedia
ENPL
opcode.eu.org RobertPaciorek
BSD/MIT-type
Serwisinternetowypoświęconyróżnymzagadnieniomzelektroniki,programowania,sieciiinstalacjibudynkowych
PL
Licencja
Copyright(c)2003-2020,RobertRyszardPaciorek<[email protected]>
Tojestwolnyiotwartydokument/oprogramowanie.Redystrybucja,użytkowaniei/lubmodyfikacjaSĄDOZWOLONEnawarunkachlicencjiMIT.
Thisisfreeandopendocument/software.Redistribution,useand/ormodifyAREPERMITTEDunderthetermsoftheMITlicense.
TheMITLicense:
Permissionisherebygranted,freeofcharge,toanypersonobtainingacopyofthissoftwareandassociateddocumentationfiles(the"Software"),todealintheSoftwarewithoutrestriction,includingwithoutlimitationtherightstouse,copy,modify,merge,publish,distribute,sublicense,and/orsellcopiesoftheSoftware,andtopermitpersonstowhomtheSoftwareisfurnishedtodoso,subjecttothefollowingconditions:
TheabovecopyrightnoticeandthispermissionnoticeshallbeincludedinallcopiesorsubstantialportionsoftheSoftware.
THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND,EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOFMERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEANDNONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERSBELIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINANACTIONOFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORINCONNECTIONWITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHESOFTWARE.