Allgemeine Daten zu Linux, Tipps und Tricks und Systemeinstellungen: Unterschied zwischen den Versionen
(2 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
= Kommandozeile = | == Kommandozeile == | ||
== Versionen herausfinden == | === Versionen herausfinden === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Zeile 18: | Zeile 18: | ||
|} | |} | ||
== Wichtige Befehle und Kniffs == | === Wichtige Befehle und Kniffs === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Zeile 50: | Zeile 50: | ||
|} | |} | ||
== Wichtige Befehle kurz erklärt == | === Wichtige Befehle kurz erklärt === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Zeile 64: | Zeile 64: | ||
|} | |} | ||
== Nice to know == | === Nice to know === | ||
Nicht so wichtig, doch manchmal doch nützlich. | Nicht so wichtig, doch manchmal doch nützlich. | ||
{| class="wikitable" | {| class="wikitable" | ||
Zeile 87: | Zeile 87: | ||
|} | |} | ||
== Netzwerk == | === Netzwerk === | ||
ifconfig/iwconfig erledigt das meiste: | ifconfig/iwconfig erledigt das meiste: | ||
{| class="wikitable" | {| class="wikitable" | ||
Zeile 102: | Zeile 102: | ||
|} | |} | ||
== Remotezugriff auf Rechner == | === Remotezugriff auf Rechner === | ||
=== Einloggen per SSH === | ==== Einloggen per SSH ==== | ||
ssh benutzername@server <br /> | ssh benutzername@server <br /> | ||
Falls danach das Serverzertifikat kommt (wenn korrekt), bestätigen, Passwort eingeben und schon ist man eingeloggt. | Falls danach das Serverzertifikat kommt (wenn korrekt), bestätigen, Passwort eingeben und schon ist man eingeloggt. | ||
=== Zugang friert ein === | ==== Zugang friert ein ==== | ||
Beim Shell-Zugriff auf einen Linux-Rechner kann es vorkommen, dass der Bildschirm einfriert. Meistens liegt das Problem nur an einer falsche Tastenkombination. Denn drückt man versehentlich [Ctrl-S], stoppt das System jegliche Ausgabe. Erst durch die Tastenkombination [Ctrl-Q] wird dieser Zustand aufgehoben. | Beim Shell-Zugriff auf einen Linux-Rechner kann es vorkommen, dass der Bildschirm einfriert. Meistens liegt das Problem nur an einer falsche Tastenkombination. Denn drückt man versehentlich [Ctrl-S], stoppt das System jegliche Ausgabe. Erst durch die Tastenkombination [Ctrl-Q] wird dieser Zustand aufgehoben. | ||
= KDE = | == KDE == | ||
Nützliche Programme: | Nützliche Programme: | ||
{| class="wikitable" | {| class="wikitable" | ||
Zeile 119: | Zeile 119: | ||
|} | |} | ||
= 32Bit/64Bit = | == 32Bit/64Bit == | ||
== 32Bit Programme unter 64Bit System == | === 32Bit Programme unter 64Bit System === | ||
http://www.tippscout.de/linux-ubuntu-programm-nicht-gefunden_tipp_5406.html | http://www.tippscout.de/linux-ubuntu-programm-nicht-gefunden_tipp_5406.html | ||
== Kernel == | |||
Der Kernel ist das Herz von Linux und stellt alle notwendigen Betriebssystem-Funktionen zur Verfügung. | |||
=== Kernel-Treiber-Grundlagen === | |||
Im [https://embetronicx.com/linux-device-driver-tutorials/ Kernel-Treiber-Tutorial] wird aufgezeigt, wie Kernel-Treiber arbeiten und wie sie aufgebaut sind. Grundsätzlich gibt es den User-Space, wo sich die Programme befinden und den Kernel-Space, in dem auch die Treiber sind. Über die System-Schnittstelle können Programme mit dem Kernel kommunizieren und Funktionen aufrufen, welche dann vom Kernel über die Treiber an die Hardware weitergeleitet werden. | |||
LKM (Linux Kernel Modul) sind Module, welche dynamisch nach/während des Systemstarts zum Grundkernel hinzugefügt werden. Dies hat den Vorteil, dass man sie nicht in die Sourcen hinein kompilieren muss. LKM werden (unter anderem) für folgende Bereiche verwendet: | |||
* Gerätetreiber (Hardware) | |||
* Dateisystem-Treiber (Festplatten, Memorykarten, Netzwerksysteme wie Samba) | |||
* Systemaufrufe (Datei lesen, Prozess stoppen, System neu starten) | |||
Folgende Unterschiede bestehen zwischen Benutzerprogrammen und Kernel-Modulen: | |||
* Unterschiedlicher Adressbereich im Speicher. Dadurch werden Module vor Programmen geschützt. | |||
* Höhere Ausführungsprivilegien als normale Programme. | |||
* Die Module werden nicht nacheinander ausgeführt, sondern registrieren sich einfach, damit sie später aufgerufen werden können. | |||
* Für die Erstellung werden unterschiedliche Header-Dateien verwendet. | |||
Der Unterschied zwischen einem Kernelmodul und einem Gerätetreiber besteht darin, dass das Modul zur Laufzeit mit <code>insmod</code> oder <code>modprobe</code> hinzugefügt werden kann, während Gerätetreiber fix im Kernel einkompiliert sind. Geräte werden in Linux immer als Datei angesprochen. Gerätetreiber lassen sich in folgende Gruppen aufteilen. | |||
==== Zeichengeräte ==== | |||
Lesen Daten Zeichen für Zeichen ein. Beispiele sind die Tastatur, die Maus oder serielle Drucker. Wird ein Gerät von jemandem benutzt, so kann niemand anders darauf zugreifen. Der gleichzeitige Zugriff ist blockiert. Beim Schreiben auf das Gerät werden die Daten synchronisiert. Für die Kommunikation mit anderen Geräten werden häufig Zeichengerätetreiber verwendet. Diese Geräte kann man entsprechend auch nicht mounten. | |||
Character Device | |||
==== Blockgeräte ==== | |||
Im Gegensatz zu Zeichengeräten werden hier Zeichen blockweise gelesen und geschrieben. Entsprechend ist dieser Typ hilfreich, wenn man massenweise Daten zu verarbeiten hat. Alle Massenmedien wie HDD/SDD, Memorysticks oder CD/DVD sind Blockgeräte. Beim Formatieren wird das Gerät blockweise aufgeteilt. Daten werden meist asynchron geschrieben (mit Puffer) und brauchen die CPU intensiv. Die Geräte können bei Bedarf angeschlossen <code>mount</code> oder abgekoppelt <code>umount</code> werden. | |||
==== Netzwerkgeräte ==== | |||
Diese Geräte senden und erhalten Pakete in einem Datenstrom. Neben Netzwerkkarten können die Geräte auch in SOftware ausgeführt sein wie das Loopback-Gerät oder VPN-Verbindungen. | |||
=== Modulaufbau === | |||
/******************************************** | |||
* \file driver.c | |||
* \details Simple hello world driver | |||
* \author EmbeTronicX | |||
*********************************************/ | |||
#include<linux/kernel.h> | |||
#include<linux/init.h> | |||
#include<linux/module.h> | |||
MODULE_LICENSE("GPL"); | |||
MODULE_AUTHOR("EmbeTronicX <embetronicx@gmail.com>"); | |||
MODULE_DESCRIPTION("A simple hello world driver"); | |||
MODULE_VERSION("2:1.0"); | |||
/* Module Init function */ | |||
static int __init hello_world_init(void) { | |||
printk(KERN_INFO "Welcome to EmbeTronicX\n"); | |||
printk(KERN_INFO "This is the Simple Module\n"); | |||
printk(KERN_INFO "Kernel Module Inserted Successfully...\n"); | |||
return 0; | |||
} // end init | |||
/* Module Exit function */ | |||
static void __exit hello_world_exit(void) { | |||
printk(KERN_INFO "Kernel Module Removed Successfully...\n"); | |||
} // end exit | |||
module_init(hello_world_init); | |||
module_exit(hello_world_exit); | |||
Das Modul besitzt zwei Konstruktoren, welche beim Start (<code>insmod modulname</code>) und beim Beenden (<code>rmmod modulname</code>) aufgerufen werden. Die Headerdateien stellen Standardmodule zur Verfügung, welche man verwenden kann, um die Lizenz usw. einzubinden, welche bei <code>modinfo</code> ausgegeben werden. | |||
Wie im Kommentar am Anfang gezeigt, wird diese Datei als "driver.c" gespeichert. Der Name sollte hierbei der Hardware für den Treiber entsprechen, so dass man weiss, was für eine Art Treiber kompiliert wird. | |||
==== Ausgabe (printk) ==== | |||
Da <code>printf</code> eine Funktion des Userspace ist, kann sie nicht verwendet werden. Mit <code>printk</code> gibt es eine entsprechende Funktion im Kernel. Dort kann mit dem ersten Parameter festgelegt werden, auf welcher Stufe der folgende Ausgabetext erfolgt (KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG). <code>printk(KERN_INFO "Willkommen im Treiber");</code> Die Ausgaben des Kernels kann man mit <code>dmesg</code> anschauen und filtern nach der Ausgabestufe. Neuere Kernelversionen erlauben die Verwendung der APIs anstatt von <code>printk</code>. Der Aufruf wird dann mit <code>pr_info("test info message\n")</code> durchgeführt (pr_debug, pr_info, pr_warn, pr_err, pr_cont). <code>pr_cont</code> führt eine vorhergehende Meldung auf der gleichen Linie im Logbuch weiter. | |||
=== Modul erstellen und testen === | |||
Um das Modul zu kompilieren, erstellt man am besten zuerst ein Makefile. | |||
obj-m += driver.o | |||
ifdef ARCH | |||
#You can update your Beaglebone path here. | |||
KDIR = /home/embetronicx/BBG/tmp/lib/modules/5.10.65/build | |||
else | |||
KDIR = /lib/modules/$(shell uname -r)/build | |||
endif | |||
all: | |||
make -C $(KDIR) M=$(shell pwd) modules | |||
clean: | |||
make -C $(KDIR) M=$(shell pwd) clean | |||
Wie man sieht, kann man den Pfad für die Kompilierung abhängig von einer Architektur machen und wenn diese nicht gefunden wird, einen Standardpfad nehmen. Die Objektdatei entsprechend dem Treibernamen wählen. | |||
Möchte man nicht nur für die Architektur kompilieren auf der man den Vorgang durchführt, so kann man dies nun mitgeben. <code>sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-</code> Sonst genügt ein einfaches <code>sudo make</code>. | |||
Neben der Objektdatei wird auch eine Kernelobjektdatei generiert, welche die Endung <code>.ko</code> hat. Diese kann nun einfach mit <code>sudo insmod modulname.ko</code> geladen werden. Ein anschliessendes <code>lsmod</code> zeigt, dass das Modul (zuoberst) aufgeführt wird und mit <code>dmesg</code> sieht man auch die Nachrichten, die im Modul generiert wurden. Das Laden kann nur im Erstellungsverzeichnis gemacht werden, solange man das Modul nicht öffentlich verfügbar macht, was später gezeigt wird. | |||
Das Entladen mit <code>sudo rmmod modulname</code> (geht ohne Dateiendung) und eine anschliessende Kontrolle mit <code>dmesg</code> sollte zeigen, dass das Entfernen auch sauber funktioniert. | |||
Die Zusatzangaben lassen sich auch sauber mit <codesudo modinfo driver.ko</code> erfragen (auch hier muss das .ko angegeben werden). | |||
==== Parameter ans Modul übergeben ==== | |||
Wie jedem c-Programm kann man auch einem Kernelmodul Argumente mitgeben. Dies ist notwendig, wenn man den Treiber individualisieren möchte. Wenn es etwa verschiedene Varianten der Hardware gibt und man so einfach angeben kann, welche Variante verwendet wird, wenn die Hardware diese Daten nicht selber liefert. Als Beispiel etwa ein LED-Array, das 8x8 oder 4x16 oder 8x16 usw. LEDs umfassen kann. | |||
Damit die Variablen auch korrekt verarbeitet werden, muss man beachten, welche Berechtigungen es dafür gibt. Diese werden folgendermassen unterschieden: S_IWUSR, S_IRUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP. | |||
Wie man sieht, wird hier das Konzept der Dateien integriert mit Lesen(R), Schreiben(W) und Ausführen(X). Dann wird noch zwischen dem Benutzer(USR) und der Gruppe(GRP) unterschieden. Das S_I am Anfang ist ein allgemeiner Header und könnte "secure identity" bedeuten. Die Berechtigungen kombiniert man mit dem Pipe-Zeichen "|", welches für ein "oder" steht. | |||
Für die Verarbeitung stehen folgende drei Makros zur Verfügung: | |||
* module_param() -> Zur initialisierung der übergebenen Argumente. Neben dem Namen muss der Typ und die Berechtigungsmaske aus obigen Werten übergeben werden. Das Makro muss ausserhalb jeder Funktion stehen und wird normalerweise direkt unterhalb des Headers platziert. Original definiert ist es in <code>linux/moduleparam.h</code> als <code>module_param(name, type, perm);</code>. Der Aufruf geschieht beispielhaft als <code>module_param(valueETX, int, S_IWUSR|S_IRUSR);</code>. Folgende Typen stehen zur Verfügung: int, long, short, uint, ulong, ushort, charp (Pointer auf char im Speicher für Zeichenkettten), bool, invbool (invertiertes bool) | |||
* module_param_array() -> Mit diesem Makro übergibt man ein Array mit Argumenten an den Kernel anstatt eines einzelnen Wertes. <code>module_param_array(name, type, num, perm);</code> "name" ist der Name des Arrays (und der Parameter), "type" ist der Typ der Array-Elemente, "num" ist ein (optionaler) integer, der NULL sein kann und "perm" ist die Berechtigung, die oben gezeigt wurde und wie bei einer Variable hier fürs gesamte Array angewendet wird. | |||
* module_param_cb() -> Man kann nicht nur Werte übergeben, sondern auch benachrichtigt werden, wenn ein Wert geändert wurde. Hat man etwa eine Temperaturfunktion, so kann man mit diesem Makro dafür sorgen, dass man benachrichtigt wird, wenn der Wert ändert. Dies geschieht dadurch, dass beim Erstellen des Wertes mit <code>module_param()</code> eine entsprechende Datei unterhalb des Treibers erstellt wird (/sys/module/<modulname>/parameters/<Argumentname>). Durch das Makro wird nun geschaut, wann sich dieser Wert ändert. Es könne nur Variablen kontrolliert werden, die mit diesem Modul erstellt werden. "Normale" Varaiblen aus den anderen Modulen kann man nach der Übergabe nicht mehr "beobachten". | |||
Die folgende Datei zeigt eine erweiterte Version, welche die oben besprochenen Parameter implementiert. | |||
/*************************************** | |||
* \file driver2.c | |||
* \details Simple hello world driver | |||
* \author EmbeTronicX | |||
* *************************************/ | |||
#include<linux/kernel.h> | |||
#include<linux/init.h> | |||
#include<linux/module.h> | |||
#include<linux/moduleparam.h> | |||
MODULE_LICENSE("GPL"); | |||
MODULE_AUTHOR("EmbeTronicX <embetronicx@gmail.com>"); | |||
MODULE_DESCRIPTION("A simple hello world driver"); | |||
MODULE_VERSION("1.0"); | |||
int valueETX, arr_valueETX[4]; // Variable mit int und int-Arry mit 4 Werten | |||
char *nameETX; // String-Variable | |||
int cb_valueETX = 0; // Überwachung der valueETX-Variable | |||
module_param(valueETX, int, S_IRUSR|S_IWUSR); // Integer-Wert definieren | |||
module_param(nameETX, charp, S_IRUSR|S_IWUSR); // String | |||
module_param_array(arr_valueETX, int, NULL, S_IRUSR|S_IWUSR); // Integer-Array | |||
/*----------------------Module_param_cb()--------------------------------*/ | |||
int notify_param(const char *val, const struct kernel_param *kp) { | |||
int res = param_set_int(val, kp); // Use helper for write variable | |||
if(res == 0) { | |||
printk(KERN_INFO "Call back function called...\n"); | |||
printk(KERN_INFO "New value of cb_valueETX = %d\n", cb_valueETX); | |||
return 0; | |||
} // end if | |||
return -1; | |||
} // end notify_param() | |||
const struct kernel_param_ops my_param_ops = { // dieser Aufruf sorgt dafür, dass auf die | |||
.set = ¬ify_param, // Use our setter ... | |||
.get = ¶m_get_int, // .. and standard getter | |||
}; | |||
module_param_cb(cb_valueETX, &my_param_ops, &cb_valueETX, S_IRUGO|S_IWUSR); // Der Modulaufruf bekommt Leserechte für den Besitzer und die Gruppenbesitzer (siehe oben im Artikel) -> siehe auch https://lwn.net/Articles/696227/ | |||
/* Module init function */ | |||
static int __init hello_world_init(void) { | |||
int i; | |||
printk(KERN_INFO "ValueETX = %d \n", valueETX); | |||
printk(KERN_INFO "cb_valueETX = %d \n", cb_valueETX); | |||
printk(KERN_INFO "NameETX = %s \n", nameETX); | |||
for (i = 0; i < (sizeof arr_valueETX / sizeof (int)); i++) { | |||
printk(KERN_INFO "Arr_value[%d] = %d\n", i, arr_valueETX[i]); | |||
} // end for | |||
printk(KERN_INFO "Kernel Module Inserted Successfully...\n"); | |||
return 0; | |||
} // end hello_world_init() | |||
/* Module Exit function */ | |||
static void __exit hello_world_exit(void) { | |||
printk(KERN_INFO "Kernel Module Removed Successfully...\n"); | |||
} // end hello_world_exit() | |||
module_init(hello_world_init); | |||
module_exit(hello_world_exit); | |||
Der untere Teil besteht wieder aus den Standard-Konstruktoren, während oben nach der Variablendeklaration und deren Übergabe ans Makro noch eine Funktion folgt, welche die Verarbeitung der Callback-Variable übernimmt und hier einfach eine entsprechende Meldung ins Kernellog generiert. | |||
Das Modul kann nun mit den Parametern aufgerufen werden: <code>sudo insmod hello_world_module.ko valueETX=14 nameETX="EmbeTronicX" arr_valueETX=100,102,104,106</code> Auch hier liefert <code>dmesg</code> wieder die notwendigen Ausgaben. Diesmal mit allen Parametern. Um den Callback zu testen, wird die Callback-Variable <code>cb_valueETX</code> auf 13 gesetzt mit <code>sudo sh -c "echo 13 > /sys/module/hello_world_module/parameters/cb_valueETX"</code> und ein anschliessendes <code>dmesg</code> zeigt, dass die Überwachungsfunktion aufgerufen wurde und den Wert zurückgegeben hat. | |||
[[Kategorie:Computer]][[Kategorie:Linux]][[Kategorie:Software]][[Kategorie:Hardware]] | [[Kategorie:Computer]][[Kategorie:Linux]][[Kategorie:Software]][[Kategorie:Hardware]] |
Aktuelle Version vom 1. September 2022, 12:46 Uhr
Kommandozeile
Versionen herausfinden
Was herausfinden | Befehl | Ausgabe, Bemerkungen |
---|---|---|
Betriebsysstem | uname -m | x86_64 -> 64-Bit-System, i686 -> 32-Bit-Linux |
Prozessorinfo | cat /proc/cpuinfo | |
Würde ein 64-Bit System funktionieren? | grep lm | leer -> funktioniert nicht, 1-2 Zeilen -> würde funktionieren |
Grafikkarte | /usr/sbin/hwinfo --gfxcard | |
Kernelversion | cat /proc/version | Kurzversion: uname -r oder uname -a |
PHP Version | less | Mit dem Parameter -r kann php interactiv direkt in der Shell oder in Scripts verwendet werden. |
Wichtige Befehle und Kniffs
Was herausfinden | Befehl | Ausgabe, Bemerkungen |
---|---|---|
Dateien suchen | locate <Datei> | http://www.tippscout.de/linux-dateien-finden_tipp_5.html Ist auf dem Raspi standardmässig nicht installiert. Installieren mit dem Paketnamen sudo apt-get install mlocate Da der Befehl in einer internen Datenbank sucht, kann man sich diese mit sudo updatedb aktualisieren lassen.
|
Dateien suchen | find <Verzeichnis> <Parameter> <Datei> | Alle Dateien in allen Unterverzeichnissen ab dem aktuellen Verzeichnis finden, welche die mitgegebene Dateiendung haben: find . -name '*.ogg' Man kann dem Befehl auch Optionen wie Dateigrösse oder Bearbeitungszeitpunkt mitgeben. Siehe dazu den Link oben bei locate.
|
Suche in man Pages | man Programm /Suchbegriff | man bash /prompt bringt Hilfe zum Programm bash und geht zum ersten Eintrag in dem prompt erwähnt wird. Mit / und Enter geht es zum nächsten Eintrag. |
Rechnen in der Kommandozeile | Einfach Rechnung direkt eingeben | |
"unbekannten" Befehl herausfinden | apropos Thema | Findet Befehle, welche indexiert wurden zum entsprechenden Thema. apropos sql findet Befehle zum Thema und danach kann man sich über man die genaue Verwendung anzeigen lassen. |
chown auf ganze Verzeichnisse | chown -R Verzeichnis . | Nicht den * verwenden, da dieser als "erweiterer" der Shell übernommen wird und sich dann im Hauptverzeichnis falsch auswirkt. Mit dem "." hingegen meint man das aktuelle Verzeichnis und so wirkt der Befehl korrekt. |
Log-Dateien live beobachten | tail -f Logdatei | Abbruch mit Ctrl-c. tail ohne -f zeigt einfach die letzten Zeilen einer Datei an und beendet dann automatisch. |
Befehl abbrechen während Eingabe | Einfach Ctrl-C drücken | |
Programm im aktuellen Verzeichnis starten | ./Programmname | Verhindert, dass falsche Programme unabsichtlich nach einem Hack gestartet werden. Daher müssen Programme in lokalen Verzeichnissen explitit aufgerufen werden, solange dieser nicht in $path gespeichert ist. |
Festplattenplatz | df -h | h steht für "human readable". Dieser Parameter kann vielfach auch bei anderen Programmen verwendet werden. |
Prozesse anschauen | top | |
Prozesse beenden | killall Programmname | Bei hartnäckigen: killall -KILL Programmname |
Dateimanager | mc | Midnight Commander ist evtl. installiert. Funktioniert wie der Norton Commander. Falls nicht farbig -> mc -c |
Wichtige Befehle kurz erklärt
Befehl | Beispiel | Bemerkungen |
---|---|---|
Befehlstabelle | http://blog.addison-wesley.de/wp-content/uploads/2010/2877_Kommandoreferenz-Poster.pdf | |
alias | Alias von einem Befehl: alias wwwneu=´/etc/rc.d/init.d/apache restart´ | Definiert einen Namen für einen Befel oder eine Befehlsreihenfolge: http://www.tippscout.de/linux-aliase-sparen-tipparbeit_tipp_736.html oder http://www.tippscout.de/komplizierte-linux-befehle-als-alias-definieren_tipp_3311.html |
find | Dateien von gestern suchen: find . -name '*.doc' -type f -mtime -1 | Findet Dateien: http://www.tippscout.de/linux-dateien-nach-datum-finden_tipp_2047.html |
locate | Datei suchen: locate... | http://www.tippscout.de/linux-dateien-finden_tipp_5.html |
Nice to know
Nicht so wichtig, doch manchmal doch nützlich.
Was herausfinden | Befehl | Ausgabe, Bemerkungen |
---|---|---|
Wie lange läuft der Rechner schon | uptime | |
Linux schnell herunterfahren | halt | sonst: shutdown -h now |
Linux schnell neu starten | reboot | sonst: shutdown -r now |
Funktionstasten simulieren | ESC->Zahl | Entspricht der jeweiligen Funktionstaste. Je nach Linuxversion und PC/MAC notwendig. ESC anschliessend 2 -> Entspricht F2. |
Liste aller Pakete unter Ubuntu/Debian | dpkg | http://www.tippscout.de/linux-ubuntu-liste-pakete_tipp_5455.html |
Wer ist auf dem System auch noch angemeldet | who | |
Speicher ermitteln | free | -m zeigt in Megabyte und zusätzlich -t koppelt noch mit Auslagerungsspeicher |
Mail von Konsole versenden | mail -s"Testmail" foo@foo.bar | kein Abstand nach -s und meist werden solche Mails wegen Spamgefahr vom Provider verworfen. |
Netzwerk
ifconfig/iwconfig erledigt das meiste:
Befehl | Auswirkung | Ausgabe, Bemerkungen |
---|---|---|
ifconfig -a | Anzeige, welche Netzwerkschnittstellen welche IP-Konfiguration haben | |
Linux schnell herunterfahren | halt | |
ifconfig eth0 192.168.0.2 netmask 255.255.255.0 | IP manuell zuweisen | |
iwconfig | Konfiguration des WLANs |
Remotezugriff auf Rechner
Einloggen per SSH
ssh benutzername@server
Falls danach das Serverzertifikat kommt (wenn korrekt), bestätigen, Passwort eingeben und schon ist man eingeloggt.
Zugang friert ein
Beim Shell-Zugriff auf einen Linux-Rechner kann es vorkommen, dass der Bildschirm einfriert. Meistens liegt das Problem nur an einer falsche Tastenkombination. Denn drückt man versehentlich [Ctrl-S], stoppt das System jegliche Ausgabe. Erst durch die Tastenkombination [Ctrl-Q] wird dieser Zustand aufgehoben.
KDE
Nützliche Programme:
Einsatz | Name | Bemerkungen |
---|---|---|
Systemauslastung anzeigen | ksim |
32Bit/64Bit
32Bit Programme unter 64Bit System
http://www.tippscout.de/linux-ubuntu-programm-nicht-gefunden_tipp_5406.html
Kernel
Der Kernel ist das Herz von Linux und stellt alle notwendigen Betriebssystem-Funktionen zur Verfügung.
Kernel-Treiber-Grundlagen
Im Kernel-Treiber-Tutorial wird aufgezeigt, wie Kernel-Treiber arbeiten und wie sie aufgebaut sind. Grundsätzlich gibt es den User-Space, wo sich die Programme befinden und den Kernel-Space, in dem auch die Treiber sind. Über die System-Schnittstelle können Programme mit dem Kernel kommunizieren und Funktionen aufrufen, welche dann vom Kernel über die Treiber an die Hardware weitergeleitet werden. LKM (Linux Kernel Modul) sind Module, welche dynamisch nach/während des Systemstarts zum Grundkernel hinzugefügt werden. Dies hat den Vorteil, dass man sie nicht in die Sourcen hinein kompilieren muss. LKM werden (unter anderem) für folgende Bereiche verwendet:
- Gerätetreiber (Hardware)
- Dateisystem-Treiber (Festplatten, Memorykarten, Netzwerksysteme wie Samba)
- Systemaufrufe (Datei lesen, Prozess stoppen, System neu starten)
Folgende Unterschiede bestehen zwischen Benutzerprogrammen und Kernel-Modulen:
- Unterschiedlicher Adressbereich im Speicher. Dadurch werden Module vor Programmen geschützt.
- Höhere Ausführungsprivilegien als normale Programme.
- Die Module werden nicht nacheinander ausgeführt, sondern registrieren sich einfach, damit sie später aufgerufen werden können.
- Für die Erstellung werden unterschiedliche Header-Dateien verwendet.
Der Unterschied zwischen einem Kernelmodul und einem Gerätetreiber besteht darin, dass das Modul zur Laufzeit mit insmod
oder modprobe
hinzugefügt werden kann, während Gerätetreiber fix im Kernel einkompiliert sind. Geräte werden in Linux immer als Datei angesprochen. Gerätetreiber lassen sich in folgende Gruppen aufteilen.
Zeichengeräte
Lesen Daten Zeichen für Zeichen ein. Beispiele sind die Tastatur, die Maus oder serielle Drucker. Wird ein Gerät von jemandem benutzt, so kann niemand anders darauf zugreifen. Der gleichzeitige Zugriff ist blockiert. Beim Schreiben auf das Gerät werden die Daten synchronisiert. Für die Kommunikation mit anderen Geräten werden häufig Zeichengerätetreiber verwendet. Diese Geräte kann man entsprechend auch nicht mounten. Character Device
Blockgeräte
Im Gegensatz zu Zeichengeräten werden hier Zeichen blockweise gelesen und geschrieben. Entsprechend ist dieser Typ hilfreich, wenn man massenweise Daten zu verarbeiten hat. Alle Massenmedien wie HDD/SDD, Memorysticks oder CD/DVD sind Blockgeräte. Beim Formatieren wird das Gerät blockweise aufgeteilt. Daten werden meist asynchron geschrieben (mit Puffer) und brauchen die CPU intensiv. Die Geräte können bei Bedarf angeschlossen mount
oder abgekoppelt umount
werden.
Netzwerkgeräte
Diese Geräte senden und erhalten Pakete in einem Datenstrom. Neben Netzwerkkarten können die Geräte auch in SOftware ausgeführt sein wie das Loopback-Gerät oder VPN-Verbindungen.
Modulaufbau
/******************************************** * \file driver.c * \details Simple hello world driver * \author EmbeTronicX *********************************************/ #include<linux/kernel.h> #include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("EmbeTronicX <embetronicx@gmail.com>"); MODULE_DESCRIPTION("A simple hello world driver"); MODULE_VERSION("2:1.0"); /* Module Init function */ static int __init hello_world_init(void) { printk(KERN_INFO "Welcome to EmbeTronicX\n"); printk(KERN_INFO "This is the Simple Module\n"); printk(KERN_INFO "Kernel Module Inserted Successfully...\n"); return 0; } // end init /* Module Exit function */ static void __exit hello_world_exit(void) { printk(KERN_INFO "Kernel Module Removed Successfully...\n"); } // end exit module_init(hello_world_init); module_exit(hello_world_exit);
Das Modul besitzt zwei Konstruktoren, welche beim Start (insmod modulname
) und beim Beenden (rmmod modulname
) aufgerufen werden. Die Headerdateien stellen Standardmodule zur Verfügung, welche man verwenden kann, um die Lizenz usw. einzubinden, welche bei modinfo
ausgegeben werden.
Wie im Kommentar am Anfang gezeigt, wird diese Datei als "driver.c" gespeichert. Der Name sollte hierbei der Hardware für den Treiber entsprechen, so dass man weiss, was für eine Art Treiber kompiliert wird.
Ausgabe (printk)
Da printf
eine Funktion des Userspace ist, kann sie nicht verwendet werden. Mit printk
gibt es eine entsprechende Funktion im Kernel. Dort kann mit dem ersten Parameter festgelegt werden, auf welcher Stufe der folgende Ausgabetext erfolgt (KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG). printk(KERN_INFO "Willkommen im Treiber");
Die Ausgaben des Kernels kann man mit dmesg
anschauen und filtern nach der Ausgabestufe. Neuere Kernelversionen erlauben die Verwendung der APIs anstatt von printk
. Der Aufruf wird dann mit pr_info("test info message\n")
durchgeführt (pr_debug, pr_info, pr_warn, pr_err, pr_cont). pr_cont
führt eine vorhergehende Meldung auf der gleichen Linie im Logbuch weiter.
Modul erstellen und testen
Um das Modul zu kompilieren, erstellt man am besten zuerst ein Makefile.
obj-m += driver.o ifdef ARCH #You can update your Beaglebone path here. KDIR = /home/embetronicx/BBG/tmp/lib/modules/5.10.65/build else KDIR = /lib/modules/$(shell uname -r)/build endif all: make -C $(KDIR) M=$(shell pwd) modules clean: make -C $(KDIR) M=$(shell pwd) clean
Wie man sieht, kann man den Pfad für die Kompilierung abhängig von einer Architektur machen und wenn diese nicht gefunden wird, einen Standardpfad nehmen. Die Objektdatei entsprechend dem Treibernamen wählen.
Möchte man nicht nur für die Architektur kompilieren auf der man den Vorgang durchführt, so kann man dies nun mitgeben. sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
Sonst genügt ein einfaches sudo make
.
Neben der Objektdatei wird auch eine Kernelobjektdatei generiert, welche die Endung .ko
hat. Diese kann nun einfach mit sudo insmod modulname.ko
geladen werden. Ein anschliessendes lsmod
zeigt, dass das Modul (zuoberst) aufgeführt wird und mit dmesg
sieht man auch die Nachrichten, die im Modul generiert wurden. Das Laden kann nur im Erstellungsverzeichnis gemacht werden, solange man das Modul nicht öffentlich verfügbar macht, was später gezeigt wird.
Das Entladen mit sudo rmmod modulname
(geht ohne Dateiendung) und eine anschliessende Kontrolle mit dmesg
sollte zeigen, dass das Entfernen auch sauber funktioniert.
Die Zusatzangaben lassen sich auch sauber mit <codesudo modinfo driver.ko erfragen (auch hier muss das .ko angegeben werden).
Parameter ans Modul übergeben
Wie jedem c-Programm kann man auch einem Kernelmodul Argumente mitgeben. Dies ist notwendig, wenn man den Treiber individualisieren möchte. Wenn es etwa verschiedene Varianten der Hardware gibt und man so einfach angeben kann, welche Variante verwendet wird, wenn die Hardware diese Daten nicht selber liefert. Als Beispiel etwa ein LED-Array, das 8x8 oder 4x16 oder 8x16 usw. LEDs umfassen kann.
Damit die Variablen auch korrekt verarbeitet werden, muss man beachten, welche Berechtigungen es dafür gibt. Diese werden folgendermassen unterschieden: S_IWUSR, S_IRUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP. Wie man sieht, wird hier das Konzept der Dateien integriert mit Lesen(R), Schreiben(W) und Ausführen(X). Dann wird noch zwischen dem Benutzer(USR) und der Gruppe(GRP) unterschieden. Das S_I am Anfang ist ein allgemeiner Header und könnte "secure identity" bedeuten. Die Berechtigungen kombiniert man mit dem Pipe-Zeichen "|", welches für ein "oder" steht.
Für die Verarbeitung stehen folgende drei Makros zur Verfügung:
- module_param() -> Zur initialisierung der übergebenen Argumente. Neben dem Namen muss der Typ und die Berechtigungsmaske aus obigen Werten übergeben werden. Das Makro muss ausserhalb jeder Funktion stehen und wird normalerweise direkt unterhalb des Headers platziert. Original definiert ist es in
linux/moduleparam.h
alsmodule_param(name, type, perm);
. Der Aufruf geschieht beispielhaft alsmodule_param(valueETX, int, S_IWUSR|S_IRUSR);
. Folgende Typen stehen zur Verfügung: int, long, short, uint, ulong, ushort, charp (Pointer auf char im Speicher für Zeichenkettten), bool, invbool (invertiertes bool) - module_param_array() -> Mit diesem Makro übergibt man ein Array mit Argumenten an den Kernel anstatt eines einzelnen Wertes.
module_param_array(name, type, num, perm);
"name" ist der Name des Arrays (und der Parameter), "type" ist der Typ der Array-Elemente, "num" ist ein (optionaler) integer, der NULL sein kann und "perm" ist die Berechtigung, die oben gezeigt wurde und wie bei einer Variable hier fürs gesamte Array angewendet wird. - module_param_cb() -> Man kann nicht nur Werte übergeben, sondern auch benachrichtigt werden, wenn ein Wert geändert wurde. Hat man etwa eine Temperaturfunktion, so kann man mit diesem Makro dafür sorgen, dass man benachrichtigt wird, wenn der Wert ändert. Dies geschieht dadurch, dass beim Erstellen des Wertes mit
module_param()
eine entsprechende Datei unterhalb des Treibers erstellt wird (/sys/module/<modulname>/parameters/<Argumentname>). Durch das Makro wird nun geschaut, wann sich dieser Wert ändert. Es könne nur Variablen kontrolliert werden, die mit diesem Modul erstellt werden. "Normale" Varaiblen aus den anderen Modulen kann man nach der Übergabe nicht mehr "beobachten".
Die folgende Datei zeigt eine erweiterte Version, welche die oben besprochenen Parameter implementiert.
/*************************************** * \file driver2.c * \details Simple hello world driver * \author EmbeTronicX * *************************************/ #include<linux/kernel.h> #include<linux/init.h> #include<linux/module.h> #include<linux/moduleparam.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("EmbeTronicX <embetronicx@gmail.com>"); MODULE_DESCRIPTION("A simple hello world driver"); MODULE_VERSION("1.0"); int valueETX, arr_valueETX[4]; // Variable mit int und int-Arry mit 4 Werten char *nameETX; // String-Variable int cb_valueETX = 0; // Überwachung der valueETX-Variable module_param(valueETX, int, S_IRUSR|S_IWUSR); // Integer-Wert definieren module_param(nameETX, charp, S_IRUSR|S_IWUSR); // String module_param_array(arr_valueETX, int, NULL, S_IRUSR|S_IWUSR); // Integer-Array /*----------------------Module_param_cb()--------------------------------*/ int notify_param(const char *val, const struct kernel_param *kp) { int res = param_set_int(val, kp); // Use helper for write variable if(res == 0) { printk(KERN_INFO "Call back function called...\n"); printk(KERN_INFO "New value of cb_valueETX = %d\n", cb_valueETX); return 0; } // end if return -1; } // end notify_param() const struct kernel_param_ops my_param_ops = { // dieser Aufruf sorgt dafür, dass auf die .set = ¬ify_param, // Use our setter ... .get = ¶m_get_int, // .. and standard getter }; module_param_cb(cb_valueETX, &my_param_ops, &cb_valueETX, S_IRUGO|S_IWUSR); // Der Modulaufruf bekommt Leserechte für den Besitzer und die Gruppenbesitzer (siehe oben im Artikel) -> siehe auch https://lwn.net/Articles/696227/ /* Module init function */ static int __init hello_world_init(void) { int i; printk(KERN_INFO "ValueETX = %d \n", valueETX); printk(KERN_INFO "cb_valueETX = %d \n", cb_valueETX); printk(KERN_INFO "NameETX = %s \n", nameETX); for (i = 0; i < (sizeof arr_valueETX / sizeof (int)); i++) { printk(KERN_INFO "Arr_value[%d] = %d\n", i, arr_valueETX[i]); } // end for printk(KERN_INFO "Kernel Module Inserted Successfully...\n"); return 0; } // end hello_world_init() /* Module Exit function */ static void __exit hello_world_exit(void) { printk(KERN_INFO "Kernel Module Removed Successfully...\n"); } // end hello_world_exit() module_init(hello_world_init); module_exit(hello_world_exit);
Der untere Teil besteht wieder aus den Standard-Konstruktoren, während oben nach der Variablendeklaration und deren Übergabe ans Makro noch eine Funktion folgt, welche die Verarbeitung der Callback-Variable übernimmt und hier einfach eine entsprechende Meldung ins Kernellog generiert.
Das Modul kann nun mit den Parametern aufgerufen werden: sudo insmod hello_world_module.ko valueETX=14 nameETX="EmbeTronicX" arr_valueETX=100,102,104,106
Auch hier liefert dmesg
wieder die notwendigen Ausgaben. Diesmal mit allen Parametern. Um den Callback zu testen, wird die Callback-Variable cb_valueETX
auf 13 gesetzt mit sudo sh -c "echo 13 > /sys/module/hello_world_module/parameters/cb_valueETX"
und ein anschliessendes dmesg
zeigt, dass die Überwachungsfunktion aufgerufen wurde und den Wert zurückgegeben hat.