• Keine Ergebnisse gefunden

Technische Praxis der Computersysteme 1

N/A
N/A
Protected

Academic year: 2021

Aktie "Technische Praxis der Computersysteme 1"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Technische Praxis der Computersysteme 1

6. Programme, Prozesse, Speicher

Thomas Leitner <thomas.leitner@univie.ac.at>

Fakultät für Mathematik, Universität Wien Wintersemester 2012

Letzte Änderung: 2013-09-20 20:46:08 +0200

Inhalt

Programme Prozesse

Speichermanagement

Programme

Ein Programm besteht aus Dateien, die Anweisungen für den Prozessor enthalten. Normalerweise haben die Programme keine Dateierweiterung (wie z.B.

.exe

unter Windows).

Es gibt auch Bibliotheken – Sammlungen von Anweisungen –, die von Programmen verwendet werden können. Diese Bibliotheken findet man üblicherweise in

/lib

und

/usr/lib

und haben die Dateiendung

.o

oder

.so

.

Unix-ähnliche Systeme verwenden üblicherweise das ELF-Format für ausführbare Binärprogramme und Bibliotheken.

Darüber hinaus erlaubt der Kernel das Ausführen von Textdateien (müssen mit dem sogenannten Shebang beginnen) und durch das

binfmt_misc

Kernelmodul auch das direkte Ausführen von beliebigen Programmtypen, wie z.B.

Java JAR-Dateien.

Programme - ELF

Beispiel ELF-Binärprogramm

ls

:

$ file /bin/ls

/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24,

BuildID[sha1]=0x214a38d0db472db559f0dabf0ae97f82fea83e03, stripped

$ readelf -h /bin/ls ELF Header:

Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64

Data: 2's complement, little endian Version: 1 (current)

OS/ABI: UNIX - System V ABI Version: 0

Type: EXEC (Executable file)

Machine: Advanced Micro Devices X86-64 Version: 0x1

Entry point address: 0x4045a4

Start of program headers: 64 (bytes into file) Start of section headers: 104048 (bytes into file) Flags: 0x0

...

Programme - Skripts

Ein ausführbares Skript muss mit dem sogenannten Shebang beginnen, das ist die Zeichenfolge

#!

. Der Rest der Zeile gibt das Programm an, mit dem das Skript ausgeführt werden soll.

Dadurch können Skripte transparent und genauso einfach wie echte Binärprogramme ausgeführt werden. Die Shell selbst (Shell-Skripts) und viele Programmiersprachen (z.B. Ruby, Python, Perl, …) verwenden diesen Mechanismus.

Beispiel für ein ausführbares Skript in der Programmiersprache Ruby:

$ file scripts/hallo_welt.rb

hallo_welt.rb: a ruby script, ASCII text executable

$ cat scripts/hallo_welt.rb

#!/usr/bin/env ruby

(2)

puts "Hallo Welt!"

$ scripts/hallo_welt.rb Hallo Welt!

Programme - Andere Binärdateien

Quelltextdateien einiger Programmiersprachen werden in ein Zwischenformat übersetzt, das nicht direkt auf der CPU ausführbar, dafür aber sehr portabel ist. Zu diesen Programmiersprachen gehört z.B. Java. Dieses Zwischenformat wird dann von einer „virtuellen Maschine“, einem speziellen Binärprogramm, interpretiert (bei Java ist das die JVM).

Das

binfmt_misc

Kernelmodul erlaubt das Registrieren solcher Binärformate und damit die transparente Ausführung von Programmen in diesen Formaten.

Beispiel: Registriertes Java-JAR-Format

$ ls /proc/sys/fs/binfmt_misc/

cli jar python2.7 register status wine

$ cat /proc/sys/fs/binfmt_misc/jar enabled

interpreter /usr/bin/jexec flags:

offset 0

magic 504b0304

$ hexdump -n 4 -e '4/1 "%02X " 1/ "\n"' \

> /usr/lib/jvm/java-7-openjdk-common/jre/lib/charsets.jar 50 4B 03 04

Prozesse

Ein Prozess ist eine Instanz eines Programms. Es kann daher ein Programm mehrmals gestartet werden und es so mehrere Instanzen eines Programmes gleichzeitig geben. Auch können mehrere verschiedene Programme gleichzeitig ausgeführt werden (Multitasking).

Zu einem Prozess gehört die Prozessumgebung (auch Prozesskontext genannt), welche unter anderem folgende Inhalte umfasst:

Die Prozess-ID (PID) und die Vater-Prozess-ID (PPID) Ein gewisser Speicherbereich

Die UID des Besitzers des Prozesses

Die EUID (effektive UID), welche den Zugang zu Ressourcen regelt Die Umgebungsvariablen

Der Kernel stellt über das

proc

-Dateisystem Informationen zu jedem Prozess in dem Verzeichnis

/proc/PID

dar.

Prozesse - Lebenszyklus 1

Beim Booten des Betriebssystem wird der sogenannte

init

-Prozess gestartet. Er ist die Wurzel des Prozessbaums.

Das Starten eines neuen Prozesses funktioniert über das fork-Modell:

Der aktuelle Prozess benutzt den Systemaufruf

fork()

, um eine Kopie von sich selbst mit neuer PID und neuer Prozessumgebung anzulegen (manche Inhalte der Prozessumgebung, wie die Umgebungsvariablen, werden weitergegeben, andere, wie der Speicherbereich, nicht).

Der aktuelle Prozess (der Vaterprozess) bekommt als Rückgabewert des Systemaufrufs die PID des Kindprozesses, der Kindprozess den Wert 0 zurück.

Der Kindprozess kann jetzt entweder den Code des Vaterprozesses weiter ausführen oder neuen Programmcode mittels des Systemaufrufs

exec()

(oder einer seiner Varianten) ausführen.

Prozesse - Lebenszyklus 2

Um die Zuordnung eines Kindprozesses zu einem Vaterprozess zu gewährleisten, gibt es die Parent PID (PPID).

Dadurch entsteht ein Prozessbaum, an dessen Wurzel der

init

-Prozess steht.

Wenn ein Prozess beendet wird, endet die Ausführung des Prozesses, aber es bleibt etwas von dem Prozess noch übrig, unter anderem der Rückgabewert. Der Vaterprozess ist dafür verantwortlich, auf seine Kindprozesse zu warten (mittels des Systemaufrufs

wait()

und seiner Varianten).

Terminiert ein Kindprozess und wurde kein

wait()

ausgeführt, so ist der Kindprozess zu einem Zombieprozess geworden. Solche Zombieprozesse werden nach der Terminierung des Vaterprozesses an den

init

-Prozess übergeben, der automatisch auf sie wartet und sie damit entfernt.

(3)

Prozesse - Scheduling, Interrupts und Prioritäten 1

Da auf einer CPU nicht mehrere Prozesse gleichzeitig ausgeführt werden können, müssen die Prozesse für kurze Zeitabschnitte hintereinander ausgeführt werden.

Die Hardware kann mittels Interrupts die Ausführung von Prozessen unterbrechen und kurzzeitig die Kontrolle an das Betriebssystem übergeben. Solche Interrupts werden zum Beispiel durch IO-Aktivitäten ausgelöst (Maus, Tastatur, Festplatte, …), aber es gibt auch periodische Interrupts. Das Betriebssystem wertet den Interrupt aus und reicht die Informationen an die entsprechenden Prozesse weiter.

Ein periodischer Interrupt wird vom Kernel dazu genutzt, um allen Prozessen Rechenzeit gerecht zur Verfügung zu stellen (Scheduling, preemptives Multitasking). Es gibt dabei mehrere auswählbare Strategien, je nachdem ob es sich um ein Serversystem, ein Desktopsystem oder z.B. ein Echtzeitsystem handelt.

Anmerkung: Früher war nur kooperatives Multitasking möglich, d.h. jeder Prozess musste sich selbst unterbrechen.

Funktionierte das nicht, frohr das System ein.

Prozesse - Scheduling, Interrupts und Prioritäten 2

Um unabhängig vom Scheduling Prozessen mehr oder weniger Rechenzeit zu geben, ist jedem Prozess eine sogenannte Scheduling-Priorität (der nice-Wert) zugeordnet. Diese reicht von -20 bis 20 mit einem Standardwert für normale Benutzer von 0.

Je negativer die Scheduling-Priorität ist, desto mehr Rechenzeit bekommt der Prozess. Umgekehrt: je positiver, desto weniger Rechenzeit. Bei eine Scheduling-Priorität von 20 läuft der Prozess praktisch nur mehr dann, wenn kein anderer Prozess Rechenzeit braucht.

Ein normaler Benutzer kann seine Prozesse nur herabstufen, d.h. ihnen geringere Priorität mittels einem höheren Wert für die Scheduling-Priorität einräumen (er ist freundlicher – nicer – zu anderen Prozessen). Der root-Benutzer darf beliebigen Scheduling-Prioritäten setzen.

Die Scheduling-Priorität kann entweder beim Starten eines Programmes mit Hilfe von

nice

festgelegt werden oder im nachhinein mittels

renice

.

Prozesse - Signale

Um mit Prozessen zu kommunizieren, muss man ihnen Signale schicken. Damit kann man ihnen z.B. sagen, dass sie sich beenden sollen.

Signale können von einem Prozess abgefangen und verarbeitet/ignoriert werden. Wird das nicht gemacht, wird die Standardaktion für das Signal ausgeführt.

Ein Signal hat einen Namen und eine Nummer. Ein Liste aller Signale findet man in der Manpage (

man 7 signal

).

Hier ist eine Tabelle der oft benötigten Signale:

Name Nummer Bemerkung

HUP 1 Hangup (Prozess wird beendet) INT 2 Interrupt (Prozess wird beendet)

KILL 9 Prozess beenden (kann nicht ignoriert werden) TERM 15 Prozess beenden

CONT 18 Gestoppten Prozess wieder starten STOP 19 Prozess stoppen

Mit Hilfe des Befehls

kill

werden Signale an Prozesse gesandt.

Befehle für Prozesse 1 (ps)

ps - Zeigt Prozessinformationen an

Viele unterschiedliche Ausgabe- und Prozessselektionsmöglichkeiten, z.B.:

ps

→ Informationen zu eigenen Prozessen im aktuellen Terminal

ps ax

→ Informationen zu allen Prozessen

Zusätzlich mit

l

oder

u

→ Selektion wie oben, nur noch mehr Informationen

$ ps l

F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND 0 1515 2383 2344 20 0 17788 1164 poll_s Ss+ pts/1 0:00 tmux attach

0 1515 2387 2385 20 0 4392 612 wait Ss+ pts/3 0:00 sh -c weechat-curses 0 1515 2388 2385 20 0 32512 13852 wait Ss pts/4 0:00 -bash

0 1515 2389 2387 20 0 344108 37176 poll_s Sl+ pts/3 0:00 weechat-curses

»

»

(4)

Befehle für Prozesse 2 (pstree, kill)

Befehle für Prozesse 3 (pgrep, pkill, top)

Befehle für Prozesse 4 (nice, renice)

0 1515 4447 2385 20 0 32472 13764 n_tty_ Ss+ pts/0 0:00 -bash 0 1515 4942 2388 20 0 9744 1044 - R+ pts/4 0:00 ps l

$ ps u

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND thomas 2383 0.0 0.0 17788 1164 pts/1 Ss+ 07:29 0:00 tmux attach

thomas 2387 0.0 0.0 4392 612 pts/3 Ss+ 07:29 0:00 sh -c weechat-curses thomas 2388 0.0 0.1 32512 13852 pts/4 Ss 07:29 0:00 -bash

thomas 2389 0.0 0.4 344108 37176 pts/3 Sl+ 07:29 0:00 weechat-curses thomas 4447 0.0 0.1 32472 13764 pts/0 Ss+ 08:19 0:00 -bash

thomas 4949 0.0 0.0 18176 1276 pts/4 R+ 08:31 0:00 ps u

pstree - Zeigt die Prozesshierarchie an.

Ohne Argument wird vom

init

-Prozess aus angezeigt, sonst von dem Prozess mit der angegebenen PID.

Optionen:

-p

→ PID anzeigen,

-a

→ Befehlsargumente anzeigen,

-n

→ numerisch, nicht nach Namen sortieren,

-s

→ Elternprozesse des angegeben Prozesses anzeigen.

$ pstree -aps $$

init,1

└─tmux,2385 attach └─bash,2388

└─pstree,5329 -aps 2388 kill - Sendet ein Signal an einen oder mehrere Prozesse.

Signale können entweder über die Nummer oder den Namen angegeben werden.

Prozesse werden über die PID angegeben.

Nur eine Option wichtig:

-signal

(also z.B. numerisch

-9

oder mit Namen

-KILL

)

$ kill -9 2389

»

»

»

»

»

»

»

pgrep, pkill - Prozesse suchen oder ihnen ein Signal schicken.

Gesucht wird nach Prozessen, auf deren Namen der reguläre Ausdruck passt.

Optionen:

-f

→ Die gesamte Kommandozeile eines Befehls verwenden, nicht nur den Namen,

-u

→ Nur Prozesse mit der angegebenen effektiven UID

$ pgrep bash 2388

4447

$ pkill -9 bash top - Prozesse interaktiv anzeigen.

Zeigt alle Prozesse an und aktualisiert die Liste laufend.

Mit Hilfe von

<

und

>

kann man die Sortierung ändern,

R

dreht die Sortierreihenfolge um,

q

beendet man das Programm,

h

zeigt die Hilfe an.

»

»

»

»

»

nice - Programm mit anderer Scheduling-Priorität laufen lassen.

Argumente sind der Programmname und die Parameter für das Programm.

Option

-n

gibt die Änderung in Relation zur aktuellen Priorität an (default 10).

Ohne Optionen und Argumente wird die aktuelle Priorität ausgegeben.

$ nice 0

$ nice nice 10

$ nice -n 3 nice 3

$ nice -n -3 nice

nice: cannot set niceness: Permission denied 0

renice - Scheduling-Priorität laufender Programme ändern.

Erstes Argument (mit optionalen

-n

davor) ist die neue Priorität, danach kommen die PIDs.

$ sleep 10 &

[1] 5727

$ renice 10 5727

»

»

»

»

»

»

(5)

Speichermanagement 1

Der Arbeitsspeicher (RAM) wird vom Kernel verwaltet und den Prozessen zugeteilt. Dabei benutzt der Linux-Kernel das Konzept eines virtuellen Speichers.

Virtuelle Speicheradressen werden von der CPU mit Unterstützung des Kernels auf physische Adressen abgebildet, damit die CPU direkt mit ihnen umgehen kann. Falls einer virtuellen Speicheradresse noch keine physische

Speicheradresse zugeordnet ist, informiert die CPU durch einen page fault (ein spezieller Interrupt) den Kernel, der die Daten dann in den physischen Speicher lädt.

Beim Starten eines Programmes, wird der Prozess in den Arbeitsspeicher geladen, der viel schneller als permanente Medien wie Festplatten ist. Der Kernel reserviert dabei einen genügend großen Bereich für den Prozess.

Jeder Prozess glaubt, den ganzen Speicher für sich alle zu haben, und für den Prozess spielt es keine Rolle, wo seine Daten im physischen Speicher geladen sind bzw. ob sie überhaupt schon geladen sind.

Gemeinsam benutzte Ressourcen wie Bibliotheken oder der Programmcode von einem Programm, das mehrmals gestartet worden ist, werden einmal geladen und die Prozesse greifen transparent durch den virtuellen Speicherbereich darauf zu.

Speichermanagement 2

Der Kernel kann auch nicht benötigten Speicher auf die Festplatte in eine Swap-Partition oder Swap-Datei auslagern.

Sobald der Speicher wieder benötigt wird (angezeigt durch einen page fault), lädt der Kernel diesen Speicher wieder.

Zusätzlich benutzt der Kernel den freien physischen Arbeitsspeicher zum Zwischenspeichern (cachen) von schon einmal geladenen Daten von der Festplatte und anderen Daten. Damit ist der wiederholte Zugriff auf diese Daten viel schneller.

Durch das Benutzen eines virtuellen Speicherbereichs erhöht sich auch die Sicherheit, weil Prozesse nicht außerhalb davon Speicher manipulieren können.

Befehle für Speichermanagement (free, swapon, swapoff)

Copyright und Lizenz

Copyright: Thomas Leitner thomas.leitner@univie.ac.at

Basiert teilweise auf den Folien von Harald Schilly harald.schilly@univie.ac.at Lizenz: Creative Commons CC BY-NC-SA

„Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 3.0 Österreich.“ - http://creativecommons.org/licenses/by-nc-sa/3.0/at/

5727 (process ID) old priority 0, new priority 10

free - Zeigt den freien und benutzten Speicher an.

Optionen:

-b

/

-k

/

-m

/

-g

→ Anzeige in Byte, Kilobyte (default), Megabyte oder Gigabyte

$ free

total used free shared buffers cached Mem: 7969624 3488688 4480936 0 291712 1172900 -/+ buffers/cache: 2024076 5945548

Swap: 3905532 0 3905532 swapon, swapoff - Aktivieren bzw. deaktiveren von Swap-Speicher

Nur der root-Benutzer kann Änderungen vornehmen.

Option

-s

von

swapon

zeigt die aktuellen Swap-Speicher an.

$ swapon -s

Filename Type Size Used Priority /dev/sda5 partition 3905532 0 -1

$ sudo swapoff /dev/sda5

$ swapon -s

Filename Type Size Used Priority

$ sudo swapon /dev/sda5

»

»

»

»

»

Referenzen

ÄHNLICHE DOKUMENTE

receptor inactivation, the cascade will quickly attain a in a strongly activated pathway, upstream phospha- tases have a greater effect on signaling time and dura- quasi-steady

Moving mirror Light source.

Shell-interne Befehle, diese entsprechen keinem Programm Alias, das ist ein Synonym für einen Befehl (nur in der Shell gültig) (Systemweite) Programme.. Shell-Skripte (systemweit

Operator || : Befehl2 wird nur dann ausgeführt, wenn Befehl1 einen Rückgabewert ungleich 0 hat!. Der Rückgabewert ist der Rückgabewert des letzten,

Der Rückgabewert ist in beiden Fällen der Rückgabewert des letzten ausgeführten Befehls der Liste2, oder 0, falls von Liste2 kein Befehl ausgeführt worden ist. Wir schreiben nun

→ Ausdruck kann einmal oder keinmal vorkommen (entspricht {0,1} ) + → Ausdruck kommt einmal oder mehrmals vor (entspricht {1,} ).. * → Ausdruck kommt keinmal, einmal oder

sehr nützlich, wenn man auf einem Server einen länger dauernden Befehl ausführen will, aber die Netzwerkverbindung zum Server nicht stabil ist oder man nicht das Ende abwarten

EHRLICHKEIT ENDLOS WINDIG SCHICKSAL SCHEINBAR HALTLOS REICHTUM FROSTIG LEHRLING FLEISSIG GESCHWINDIGKEIT VERWANDTSCHAFT LAUNISCH HEITERKEIT EHRLICH EINSAMKEIT