Ich entschuldige mich im Voraus, wenn dieser Beitrag ein wenig unübersichtlich ist, aber es fällt mir schwer, ihn besser zu formulieren.
- Ist mein Verständnis unten richtig - und wenn nicht, wo gehe ich falsch?
- Gibt es ein besseres Tool zum "Erfassen" von Protokolldaten zu allen Aspekten, die auf dem PC während eines Schreibvorgangs auftreten?
Genauer gesagt: Das Betriebssystem, das ich verwende, ist:
$ uname -a
Linux mypc 2.6.38-16-generic #67-Ubuntu SMP Thu Sep 6 18:00:43 UTC 2012 i686 i686 i386 GNU/Linux
So habe ich folgendes einfaches (zB die üblichen Prüfungen auf Betriebsstörungen werden übersprungen) User-Space-C-Programm wtest.c
:
#include <stdio.h>
#include <fcntl.h> // O_CREAT, O_WRONLY, S_IRUSR
int main(void) {
char filename[] = "/tmp/wtest.txt";
char buffer[] = "abcd";
int fd;
mode_t perms = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
fd = open(filename, O_RDWR|O_CREAT, perms);
write(fd,buffer,4);
close(fd);
return 0;
}
Ich baue das mit gcc -g -O0 -o wtest wtest.c
. Da ich nun versuche zu schreiben /tmp
, stelle ich fest, dass es sich um ein Verzeichnis unter dem Stammverzeichnis handelt /
- also überprüfe ich Folgendes mount
:
$ mount
/dev/sda5 on / type ext4 (rw,errors=remount-ro,commit=0)
...
/dev/sda6 on /media/disk1 type ext4 (rw,uhelper=hal,commit=0)
/dev/sda7 on /media/disk2 type ext3 (rw,nosuid,nodev,uhelper=udisks,commit=0,commit=0,commit=0,commit=0,commit=0,commit=0)
...
Mein Root-Dateisystem /
ist also eine Partition des /dev/sda
Geräts (und ich verwende auch andere Partitionen als "eigenständige" Festplatten / Mounts). Um den Treiber für dieses Gerät zu finden, benutze ich hwinfo
:
$ hwinfo --disk
...
19: IDE 00.0: 10600 Disk
...
SysFS ID: /class/block/sda
SysFS BusID: 0:0:0:0
...
Hardware Class: disk
Model: "FUJITSU MHY225RB"
...
Driver: "ata_piix", "sd"
Driver Modules: "ata_piix"
Device File: /dev/sda
...
Device Number: block 8:0-8:15
...
Die /dev/sda
Festplatte wird also anscheinend vom ata_piix
(und sd
) Treiber verwaltet.
$ grep 'ata_piix\| sd' <(gunzip </var/log/syslog.2.gz)
Jan 20 09:28:31 mypc kernel: [ 1.963846] ata_piix 0000:00:1f.2: version 2.13
Jan 20 09:28:31 mypc kernel: [ 1.963901] ata_piix 0000:00:1f.2: PCI INT B -> GSI 19 (level, low) -> IRQ 19
Jan 20 09:28:31 mypc kernel: [ 1.963912] ata_piix 0000:00:1f.2: MAP [ P0 P2 P1 P3 ]
Jan 20 09:28:31 mypc kernel: [ 2.116038] ata_piix 0000:00:1f.2: setting latency timer to 64
Jan 20 09:28:31 mypc kernel: [ 2.116817] scsi0 : ata_piix
Jan 20 09:28:31 mypc kernel: [ 2.117068] scsi1 : ata_piix
Jan 20 09:28:31 mypc kernel: [ 2.529065] sd 0:0:0:0: [sda] 488397168 512-byte logical blocks: (250 GB/232 GiB)
Jan 20 09:28:31 mypc kernel: [ 2.529104] sd 0:0:0:0: Attached scsi generic sg0 type 0
Jan 20 09:28:31 mypc kernel: [ 2.529309] sd 0:0:0:0: [sda] Write Protect is off
Jan 20 09:28:31 mypc kernel: [ 2.529319] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
Jan 20 09:28:31 mypc kernel: [ 2.529423] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
Jan 20 09:28:31 mypc kernel: [ 2.674783] sda: sda1 sda2 < sda5 sda6 sda7 sda8 sda9 sda10 >
Jan 20 09:28:31 mypc kernel: [ 2.676075] sd 0:0:0:0: [sda] Attached SCSI disk
Jan 20 09:28:31 mypc kernel: [ 4.145312] sd 2:0:0:0: Attached scsi generic sg1 type 0
Jan 20 09:28:31 mypc kernel: [ 4.150596] sd 2:0:0:0: [sdb] Attached SCSI removable disk
Ich muss aus älterem Syslog ziehen, da ich viel aussetze, aber das obige scheint das richtige Snippet aus dem Syslog beim Booten zu sein, wo der ata_piix
(und sd
) Treiber zum ersten Mal einschaltet.
Mein erster Punkt der Verwirrung ist, dass ich die ata_piix
oder sd
Fahrer nicht anders beobachten kann :
$ lsmod | grep 'ata_piix\| sd'
$
$ modinfo sd
ERROR: modinfo: could not find module sd
$ modinfo ata_piix
ERROR: modinfo: could not find module ata_piix
Meine erste Frage lautet also: Warum kann ich das ata_piix
Modul hier nicht nur in Startprotokollen beobachten ? Liegt es daran, dass ata_piix
(und sd
) als integrierte Treiber im (monolithischen) Kernel erstellt werden und nicht als (ladbare) .ko
Kernelmodule?
Ich versuche jetzt zu beobachten, was passiert, wenn das Programm mit dem in ftrace
Linux integrierten Funktionstracer ausgeführt wird.
sudo bash -c '
KDBGPATH="/sys/kernel/debug/tracing"
echo function_graph > $KDBGPATH/current_tracer
echo funcgraph-abstime > $KDBGPATH/trace_options
echo funcgraph-proc > $KDBGPATH/trace_options
echo 0 > $KDBGPATH/tracing_on
echo > $KDBGPATH/trace
echo 1 > $KDBGPATH/tracing_on ; ./wtest ; echo 0 > $KDBGPATH/tracing_on
cat $KDBGPATH/trace > wtest.ftrace
'
... und hier ist ein Auszug aus dem ftrace
Protokoll über write
:
4604.352690 | 0) wtest-31632 | | sys_write () { 4604.352690 | 0) wtest-31632 | 0,750 us | fget_light (); 4604.352692 | 0) wtest-31632 | | vfs_write () { 4604.352693 | 0) wtest-31632 | | rw_verify_area () { 4604.352693 | 0) wtest-31632 | | security_file_permission () { 4604.352694 | 0) wtest-31632 | | apparmor_file_permission () { 4604.352695 | 0) wtest-31632 | 0,811 us | common_file_perm (); 4604.352696 | 0) wtest-31632 | 2.198 us | } 4604.352697 | 0) wtest-31632 | 3,573 us | } 4604.352697 | 0) wtest-31632 | 4.979 us | } 4604.352698 | 0) wtest-31632 | | do_sync_write () { 4604.352699 | 0) wtest-31632 | | ext4_file_write () { 4604.352700 | 0) wtest-31632 | | generic_file_aio_write () { 4604.352701 | 0) wtest-31632 | | mutex_lock () { 4604.352701 | 0) wtest-31632 | 0,666 us | _cond_resched (); 4604.352703 | 0) wtest-31632 | 1.994 us | } 4604.352704 | 0) wtest-31632 | | __generic_file_aio_write () { ... 4604.352728 | 0) wtest-31632 | | file_update_time () { ... 4604.352732 | 0) wtest-31632 | 0,756 us | mnt_want_write_file (); 4604.352734 | 0) wtest-31632 | | __mark_inode_dirty () { ... 4604.352750 | 0) wtest-31632 | | ext4_mark_inode_dirty () { 4604.352750 | 0) wtest-31632 | 0,679 us | _cond_resched (); 4604.352752 | 0) wtest-31632 | | ext4_reserve_inode_write () { ... 4604.352777 | 0) wtest-31632 | | __ext4_journal_get_write_access () { ... 4604.352795 | 0) wtest-31632 | | ext4_mark_iloc_dirty () { ... 4604.352806 | 0) wtest-31632 | | __ext4_journal_stop () { ... 4604.352821 | 0) wtest-31632 | 0,684 us | mnt_drop_write (); 4604.352822 | 0) wtest-31632 | + 93.541 us | } 4604.352823 | 0) wtest-31632 | | generic_file_buffered_write () { 4604.352824 | 0) wtest-31632 | 0,654 us | iov_iter_advance (); 4604.352825 | 0) wtest-31632 | | generic_perform_write () { 4604.352826 | 0) wtest-31632 | 0,709 us | iov_iter_fault_in_readable (); 4604.352828 | 0) wtest-31632 | | ext4_da_write_begin () { 4604.352829 | 0) wtest-31632 | | ext4_journal_start_sb () { ... 4604.352847 | 0) wtest-31632 | 1,453 us | __block_write_begin (); 4604.352849 | 0) wtest-31632 | + 21.128 us | } 4604.352849 | 0) wtest-31632 | | iov_iter_copy_from_user_atomic () { 4604.352850 | 0) wtest-31632 | | __kmap_atomic () { ... 4604.352863 | 0) wtest-31632 | 0,672 us | mark_page_accessed (); 4604.352864 | 0) wtest-31632 | | ext4_da_write_end () { 4604.352865 | 0) wtest-31632 | | generic_write_end () { 4604.352866 | 0) wtest-31632 | | block_write_end () { ... 4604.352893 | 0) wtest-31632 | | __ext4_journal_stop () { ... 4604.352909 | 0) wtest-31632 | 0,655 us | mutex_unlock (); 4604.352911 | 0) wtest-31632 | 0,727 us | generic_write_sync (); 4604.352912 | 0) wtest-31632 | ! 212.259 us | } 4604.352913 | 0) wtest-31632 | ! 213.845 us | } 4604.352914 | 0) wtest-31632 | ! 215.286 us | } 4604.352914 | 0) wtest-31632 | 0,685 us | __fsnotify_parent (); 4604.352916 | 0) wtest-31632 | | fsnotify () { 4604.352916 | 0) wtest-31632 | 0,907 us | __srcu_read_lock (); 4604.352918 | 0) wtest-31632 | 0,685 us | __srcu_read_unlock (); 4604.352920 | 0) wtest-31632 | 3.958 us | } 4604.352920 | 0) wtest-31632 | ! 228.409 us | } 4604.352921 | 0) wtest-31632 | ! 231.334 us | }
Dies ist mein zweiter Punkt der Verwirrung - ich kann den User-Space beobachten, der sich erwartungsgemäß write()
mit einem Kernel-Space ergibt sys_write()
; und in der sys_write()
ich sicherheitsrelevante Funktionen (zB beobachten apparmor_file_permission()
), „generische“ Schreibfunktionen (zB generic_file_aio_write()
), ext4
Dateisystem verwandte Funktionen (zB ext4_journal_start_sb()
) - aber ich weiß nicht beobachte alles im Zusammenhang mit ata_piix
(oder sd
) -Treiber?
Auf der Seite Nachverfolgung und Profilerstellung - Yocto Project wird vorgeschlagen , den blk
Tracer in ftrace
zu verwenden, um weitere Informationen über den Betrieb von Blockgeräten zu erhalten. In diesem Beispiel wird jedoch nichts gemeldet . Außerdem schlagen Linux-Dateisystemtreiber - Annon Inglorion (tutorfs) vor, dass Dateisysteme auch als Kernelmodule / -treiber (implementiert) werden (können?), Und ich vermute, dass dies auch der Fall ist ext4
.
Schließlich hätte ich schwören können, dass ich früher den Treibernamen in eckigen Klammern neben der vom function_graph
Tracer angezeigten Funktion gesehen habe , aber ich glaube, ich hatte etwas verwechselt - es kann wahrscheinlich in Stack- (Back-) Traces so aussehen, aber nicht im Funktionsgraphen. Außerdem kann ich Folgendes einsehen /proc/kallsyms
:
$ grep 'piix\| sd\|psmouse' /proc/kallsyms
...
00000000 d sd_ctl_dir
00000000 d sd_ctl_root
00000000 d sdev_class
00000000 d sdev_attr_queue_depth_rw
00000000 d sdev_attr_queue_ramp_up_period
00000000 d sdev_attr_queue_type_rw
00000000 d sd_disk_class
...
00000000 t piix_init_sata_map
00000000 t piix_init_sidpr
00000000 t piix_init_one
00000000 t pci_fixup_piix4_acpi
...
00000000 t psmouse_show_int_attr [psmouse]
00000000 t psmouse_protocol_by_type [psmouse]
00000000 r psmouse_protocols [psmouse]
00000000 t psmouse_get_maxproto [psmouse]
...
... und überprüfe mit Linux / drivers / ata / ata_piix.c , ob zB piix_init_sata_map
tatsächlich eine Funktion in ist ata_piix
. Was mir wahrscheinlich sagen sollte: Module, die im Kernel kompiliert sind (damit sie Teil des monolithischen Kernels werden), "verlieren" die Informationen darüber, von welchem Modul sie stammen; Bei den ladbaren Modulen, die als separate .ko
Kernelobjekte erstellt wurden, bleiben diese Informationen jedoch erhalten (z. B. [psmouse]
oben in eckigen Klammern angegeben). Somit ftrace
könnten auch nur "Ursprungsmodul" -Informationen angezeigt werden, und zwar nur für die Funktionen, die von ladbaren Kernelmodulen stammen. Ist das richtig?
Unter Berücksichtigung des oben Gesagten ist dies das Verständnis, das ich derzeit von dem Prozess habe:
- Beim Booten erstellt der
ata_piix
Treiber eine DMA-Speicherzuordnung (?) Zwischen/dev/sda
und der Festplatte- Aus diesem Grund sind alle zukünftigen Zugriffe auf
/dev/sda
Viaata_piix
für den Kernel transparent (dh nicht nachvollziehbar) - da jeder Kernel nur Lese- / Schreibzugriffe auf Speicherorte ausführen würde (nicht unbedingt Aufrufe bestimmter nachvollziehbarer Kernelfunktionen) werden vomfunction_graph
Tracer nicht gemeldet
- Aus diesem Grund sind alle zukünftigen Zugriffe auf
- Beim Booten
sd
"analysiert" der Treiber außerdem die Partitionen von/dev/sda
, stellt sie zur Verfügung und verarbeitet möglicherweise die Speicherzuordnungen zwischen den Partitionen <-> Plattenlaufwerken- Auch dies sollte die Zugriffsoperationen über
sd
für den Kernel transparent machen
- Auch dies sollte die Zugriffsoperationen über
- Da beide
ata_piix
undsd
im Kernel kompiliert sindftrace
, können wir keine Informationen darüber erhalten, von welchem Modul diese Funktionen stammen würden (abgesehen von der "manuellen" Korrelation mit Quelldateien) , auch wenn einige ihrer Funktionen erfasst werden. - Baut später
mount
eine Beziehung / Bindung zwischen einer Partition und dem entsprechenden Dateisystemtreiber auf (in diesem Fallext4
)- Ab diesem Zeitpunkt würden alle Zugriffe auf das bereitgestellte Dateisystem von
ext4
Funktionen verwaltet, die vom Kernel nachverfolgt werden können. aber wieext4
im Kernel kompiliert wird, kann der Tracer gibt uns nicht die Ursprungsmodul Informationen
- Ab diesem Zeitpunkt würden alle Zugriffe auf das bereitgestellte Dateisystem von
- Somit würden die beobachteten "generischen" Schreibvorgänge, die über
ext4
Funktionen aufgerufen werden , letztendlich auf Speicherorte zugreifen, deren Zuordnung durchata_piix
- aber anders als das - festgelegt wird,ata_piix
die Datenübertragung nicht direkt stören (sie wird wahrscheinlich von DMA (außerhalb des Prozessors) verarbeitet (s) und damit für sie transparent).
Ist dieses Verständnis richtig?
Einige verwandte Unterfragen:
- In meinem obigen Setup kann ich einen PCI-Gerätetreiber (
ata_piix
) und einen Dateisystemtreiber (ext4
) identifizieren . Aber gibt es Zeichen- oder Blocktreiber, die irgendwo im Ausführungspfad "Schreiben" verwendet werden, und wenn ja, welche? - Welcher dieser Treiber würde das Caching handhaben (so dass unnötige Festplattenoperationen übersprungen oder optimiert werden?)
- Ich kenne von
/dev/shm
vorhin ein Dateisystem im RAM;mount | grep shm
für mich berichtet:none on /dev/shm type tmpfs (rw,nosuid,nodev)
. Bedeutet das, dass/dev/sda
demshm
Dateisystem - im Gegensatz zu - einfach die (DMA-) Zuordnung von "seinen" Adressen zu Busadressen zu einem Gerät fehlt? und somittmpfs
landen alle Zugriffe über den Dateisystemtreiber im eigentlichen RAM?
quelle
Antworten:
Sie haben in einer Frage viel zu viel gefragt - nun ja, technisch gesehen nicht, da ich denke, dass "dieses Verständnis richtig ist", kann dies schnell beantwortet werden: Nein. Aber das ist keine nützliche Antwort.
Erstens haben Sie Recht
ata_piix
und werdensd_mod
anscheinend in Ihren Kernel kompiliert. Das ist eine Wahl, die Sie treffen, um den Kernel zu konfigurieren - Sie können ihn weglassen, einschließen oder als Modul einschließen. (Dasselbe mit ext4).Zweitens haben Sie angenommen, dass Schreibvorgänge viel einfacher sind als sie tatsächlich sind. Der grundlegende Umriss der Funktionsweise eines Schreibvorgangs besteht darin, dass der Dateisystemcode die zu schreibenden Daten als Teil des Puffercaches in den Speicher legt und sie als zu schreibend markiert ("unsauber"). (Es sei denn, es befindet sich bereits zu viel davon im RAM. In diesem Fall ist es tatsächlich gezwungen, den Schreibvorgang auszuführen ...)
Später werden
bdflush
die verschmutzten Seiten von verschiedenen Dingen (wie dem Kernel-Thread) auf die Festplatte geschrieben. Dies ist der Fall, wenn Aufrufe über sd, scsi, libata, ata_piix, io-Scheduler, PCI usw. angezeigt werden. Es ist zwar sehr wahrscheinlich, dass DMA an dieser Ausgabe beteiligt ist, es handelt sich jedoch um die zu übertragenden Daten und möglicherweise um den Befehl. Festplattenschreibvorgänge werden jedoch zumindest in SATA durch Senden von Befehlen behandelt, die im Grunde genommen "Sektor X mit Daten Y schreiben" bedeuten. Es wird jedoch definitiv nicht durch die Speicherzuordnung der gesamten Festplatte verarbeitet.Die Zwischenspeicherung wird vom Speicherverwaltungssubsystem (kein Treiber) in Verbindung mit dem Dateisystem, der Blockschicht usw. übernommen.
tmpfs
ist speziell, es ist im Grunde ganz Cache. Es ist nur ein spezieller Cache, der niemals verworfen oder zurückgeschrieben wird (obwohl er ausgetauscht werden kann). Sie können den Code anmm/shmem.c
und an mehreren anderen Stellen finden (versuchen Sieack-grep --cc CONFIG_TMPFS
, sie zu finden).Grundsätzlich durchläuft das Schreiben auf die Festplatte einen Großteil der Subsysteme des Kernels. Networking ist die einzige große Sache, an die ich denken kann, die nicht in Ihr Beispiel verwickelt ist. Um es richtig zu erklären, ist ein Aufwand in Buchgröße erforderlich. Ich empfehle, nach einem zu suchen.
quelle
sudo bash...
Skript im OP: ftrace memory erhöht wird (echo 8192 > $KDBGPATH/buffer_size_kb
); undsync ;
wird nach dem./wtest ;
Anruf hinzugefügt . Dann kann ich sehenflush-8
,kworker
(unterkthreadd
inps axf
), undsync
selbst, wie Prozessen in denftrace
Anruffunktionen wie zBata_bmdma_setup()
(der Teil istlibata
, derata_piix
auf Builds), oderget_nr_dirty_inodes()
.Sie müssen nicht raten, wie Ihre Konfiguration lautet. Auf meiner Maschine habe ich
Die Konfigurationsdatei für diesen Kernel befindet sich unter
/boot/config-3.2.0-4-amd64
.Sie fragten nach
ata_piix
. Beim Durchsuchen der obigen.config
Datei sehen wirCONFIG_ATA_PIIX=m
. wir können dies dadurch bestätigenAlternative
Zumindest in meinem Kernel handelt es sich also um ein Modul.
quelle
:)
Auf meinem Systemgrep ATA_PIIX /boot/config-2.6.38-16-generic
heißt dasCONFIG_ATA_PIIX=y
, was auf diesem Kernel wohl heißen sollteata_piix
, "In-Kernel" bauen, und nicht als Modul. Prost!