Mohon maaf sebelumnya jika postingan ini agak padat / berantakan, tapi saya kesulitan memformulasikannya dengan lebih baik ... Pada dasarnya, saya ingin mempelajari apa yang terjadi pada penulisan hard disk, dan saya ingin tahu:
- Apakah pemahaman saya di bawah ini benar - dan jika tidak, di mana saya salah?
- Apakah ada alat yang lebih baik untuk "menangkap" data log, tentang semua aspek yang terjadi pada PC, selama penulisan disk?
Secara lebih rinci - pertama, OS yang saya gunakan adalah:
$ 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
Jadi, saya memiliki sederhana berikut (misalnya pemeriksaan biasa untuk kegagalan operasi dilewati) Program user-space C, 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;
}
Saya membangun ini dengan gcc -g -O0 -o wtest wtest.c
. Sekarang, karena saya mencoba menulis /tmp
, saya perhatikan bahwa itu adalah direktori di bawah root /
- jadi saya periksa 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)
...
Jadi, sistem file root saya /
adalah satu partisi /dev/sda
perangkat (dan saya juga menggunakan partisi lain sebagai disk / mount "standalone"). Untuk menemukan driver untuk perangkat ini, saya menggunakan 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
...
Jadi, /dev/sda
hard disk tampaknya ditangani oleh ata_piix
(dan sd
) driver.
$ 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
Saya harus menarik dari syslog yang lebih lama karena saya banyak menangguhkan, tetapi di atas sepertinya potongan yang tepat dari syslog pada saat boot, di mana driver ata_piix
(dan sd
) menendang untuk pertama kalinya.
Titik kebingungan pertama saya adalah bahwa saya tidak dapat mengamati driver ata_piix
atau sebaliknya sd
:
$ 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
Jadi pertanyaan pertama saya adalah - mengapa saya tidak dapat mengamati ata_piix
modul di sini, hanya di log waktu boot? Apakah karena ata_piix
(dan sd
) dibangun sebagai driver bawaan pada kernel (monolitik), dan bukan dibangun sebagai modul .ko
kernel (yang dapat dimuat) ?
Benar - jadi sekarang, saya mencoba mengamati apa yang terjadi setelah menjalankan program dengan ftrace
pelacak fungsi bawaan Linux.
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
'
... dan di sini adalah potongan ftrace
log tentang write
:
4604.352690 | 0) wtest-31632 | | sys_write () { 4604.352690 | 0) wtest-31632 | 0,750 kami | 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 kami | } 4604.352697 | 0) wtest-31632 | 3.573 kami | } 4604.352697 | 0) wtest-31632 | 4.979 kami | } 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 kami | 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 kami | 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 kami | mutex_unlock (); 4604.352911 | 0) wtest-31632 | 0,727 kami | 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 kami | } 4604.352914 | 0) wtest-31632 | 0.685 kami | __fsnotify_parent (); 4604.352916 | 0) wtest-31632 | | fsnotify () { 4604.352916 | 0) wtest-31632 | 0.907 kami | __srcu_read_lock (); 4604.352918 | 0) wtest-31632 | 0.685 kami | __srcu_read_unlock (); 4604.352920 | 0) wtest-31632 | 3.958 kami | } 4604.352920 | 0) wtest-31632 | ! 228.409 us | } 4604.352921 | 0) wtest-31632 | ! 231.334 us | }
Ini adalah titik kedua kebingungan saya - saya dapat mengamati ruang-pengguna yang write()
dihasilkan dengan ruang-kernel sys_write()
, seperti yang diharapkan; dan di dalam sys_write()
, saya mengamati fungsi-fungsi yang berhubungan dengan keamanan (mis. apparmor_file_permission()
), fungsi tulis "generik" (mis. generic_file_aio_write()
), ext4
fungsi-fungsi yang berhubungan dengan filesystem (misal ext4_journal_start_sb()
) - tetapi saya tidak mengamati apapun yang berhubungan dengan ata_piix
(atau sd
) driver ?!
Halaman Tracing dan Profiling - Yocto Project menyarankan menggunakan blk
pelacak ftrace
untuk mendapatkan informasi lebih lanjut tentang operasi perangkat blok, tetapi tidak melaporkan apa-apa bagi saya dengan contoh ini. Juga, Linux Filesystem Drivers - Annon Inglorion (tutorfs) menyarankan bahwa filesystems (can?) Juga diimplementasikan sebagai modul / driver kernel, dan saya menduga itu ext4
juga berlaku.
Akhirnya, saya bisa bersumpah bahwa saya sebelumnya telah mengamati nama driver dalam tanda kurung di sebelah fungsi yang ditunjukkan oleh function_graph
pelacak, tapi saya kira saya telah mencampuradukkan hal-hal - itu mungkin dapat muncul seperti itu di tumpukan (kembali) jejak, tetapi tidak dalam grafik fungsi. Selanjutnya, saya dapat memeriksa /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]
...
... dan memeriksa dengan sumber Linux / driver / ata / ata_piix.c , konfirmasikan bahwa eg piix_init_sata_map
memang sebuah fungsi di ata_piix
. Yang mungkin harus memberi tahu saya bahwa: modul yang dikompilasi dalam kernel (sehingga mereka menjadi bagian dari kernel monolitik) "kehilangan" informasi tentang modul mana mereka berasal; akan tetapi, modul yang dapat dimuat yang dibangun sebagai .ko
objek kernel yang terpisah , menyimpan informasi tersebut (mis. yang [psmouse]
ditunjukkan di atas dalam tanda kurung siku). Dengan demikian, juga ftrace
hanya bisa menampilkan informasi "modul berasal", hanya untuk fungsi-fungsi yang berasal dari modul kernel yang dapat dimuat. Apakah ini benar?
Di atas dipertimbangkan, ini adalah pemahaman yang saya miliki tentang proses saat ini:
- Pada saat boot,
ata_piix
driver membuat pemetaan memori DMA (?) Antara/dev/sda
dan hard disk- karena ini, semua masa depan akses ke
/dev/sda
melaluiata_piix
akan transparan kepada kernel (yaitu, tidak dapat dilacak) - karena semua kernel akan melihat, hanya membaca / menulis ke lokasi memori (tidak harus memanggil fungsi kernel dapat dilacak tertentu), yang tidak dilaporkan olehfunction_graph
pelacak
- karena ini, semua masa depan akses ke
- Pada saat boot,
sd
driver selanjutnya akan "mem-parsing" partisi/dev/sda
, membuatnya tersedia, dan mungkin menangani pemetaan memori antara partisi <-> perangkat disk- sekali lagi, ini harus membuat operasi akses melalui
sd
transparan ke kernel
- sekali lagi, ini harus membuat operasi akses melalui
- Karena keduanya
ata_piix
dansd
dikompilasi dalam kernel, bahkan jika beberapa fungsinya akhirnya ditangkap olehftrace
, kami tidak dapat memperoleh informasi dari modul mana fungsi-fungsi tersebut berasal (terlepas dari korelasi "manual" dengan file sumber) - Kemudian,
mount
buat hubungan / ikatan antara partisi, dan driver sistem file yang sesuai (dalam hal iniext4
)- mulai saat ini, semua akses ke sistem file yang di-mount akan ditangani oleh
ext4
fungsi - yang dapat dilacak oleh kernel; tetapi sepertiext4
yang dikompilasi dalam kernel, pelacak tidak dapat memberi kami informasi modul yang berasal
- mulai saat ini, semua akses ke sistem file yang di-mount akan ditangani oleh
- Jadi, tulisan "generik" yang diamati, disebut melalui
ext4
fungsi, pada akhirnya akan mengakses lokasi memori, yang pemetaannya dilakukan olehata_piix
- tetapi selain itu,ata_piix
tidak mengganggu langsung dengan transfer data (mungkin sedang ditangani oleh DMA (di luar prosesor) (s), dan karenanya transparan untuk itu).
Apakah pemahaman ini benar?
Beberapa pertanyaan yang terkait:
- Dalam pengaturan saya di atas, saya dapat mengidentifikasi driver perangkat PCI (
ata_piix
) dan driver sistem file (ext4
); tetapi apakah ada driver karakter atau blok yang digunakan di suatu tempat di jalur eksekusi "tulis", dan jika demikian, yang mana mereka? - Manakah dari driver yang akan menangani caching (sehingga operasi disk yang tidak perlu dilewati atau dioptimalkan?)
- Saya tahu sebelumnya bahwa itu
/dev/shm
adalah sistem file dalam RAM;mount | grep shm
bagi saya melaporkan:none on /dev/shm type tmpfs (rw,nosuid,nodev)
. Apakah itu berarti bahwa - berbeda dengan/dev/sda
- sistemshm
file tidak memiliki pemetaan (DMA) dari alamatnya "sendiri" ke alamat bus ke perangkat; dan dengan demikian semua akses melaluitmpfs
driver filesystem berakhir di RAM yang sebenarnya?
sumber
Jawaban:
Anda terlalu banyak bertanya dalam satu pertanyaan — yah, secara teknis tidak, karena saya kira "apakah pemahaman ini benar" dapat dijawab dengan cepat: tidak. Tapi itu bukan jawaban yang berguna.
Pertama, Anda benar
ata_piix
dansd_mod
tampaknya sedang dikompilasi ke kernel Anda. Itu adalah pilihan yang Anda buat untuk mengkonfigurasi kernel — Anda dapat mengabaikannya, memasukkannya, atau memasukkannya sebagai modul. (Sama dengan ext4).Kedua, Anda menganggap menulis jauh lebih sederhana dari yang sebenarnya. Garis besar dasar cara kerja penulisan adalah bahwa kode sistem file menempatkan data untuk ditulis dalam memori, sebagai bagian dari buffer-cache, dan menandainya sebagai kebutuhan-untuk-ditulis ("kotor"). (Kecuali jika sudah terlalu banyak dalam RAM, dalam hal ini sebenarnya terpaksa melakukan tulis ...)
Kemudian, berbagai hal (seperti
bdflush
utas kernel) benar-benar membersihkan halaman yang kotor ke disk. Ini adalah ketika Anda akan melihat panggilan melalui sd, scsi, libata, ata_piix, io schedulers, PCI, dll. Meskipun ada kemungkinan DMA terlibat dalam write-out itu, itu adalah data yang akan ditransfer, dan mungkin perintah. Tetapi penulisan disk, setidaknya dalam SATA, ditangani dengan mengirim perintah yang pada dasarnya berarti "tulis sektor X dengan data Y". Tapi itu pasti tidak ditangani oleh pemetaan memori seluruh disk (pertimbangkan: Anda dapat menggunakan disk yang jauh lebih besar dari 4GiB pada mesin 32-bit).Caching ditangani oleh subsistem manajemen memori (bukan driver), dalam hubungannya dengan sistem file, lapisan blok, dll.
tmpfs
spesial, pada dasarnya sepenuhnya cache. Cache khusus yang tidak pernah dibuang atau ditulis kembali (meskipun dapat ditukar). Anda dapat menemukan kode dimm/shmem.c
dan beberapa tempat lain (cobaack-grep --cc CONFIG_TMPFS
temukan).Pada dasarnya, menulis ke disk melewati sebagian besar subsistem kernel; jaringan adalah satu-satunya yang saya pikir tidak terlibat dalam contoh Anda. Menjelaskannya dengan benar membutuhkan upaya sepanjang buku; Saya sarankan mencari satu.
sumber
sudo bash...
Pembilasan halaman kotor) dapat diamati, jika dalam skrip dalam OP: memori ftrace ditingkatkan (echo 8192 > $KDBGPATH/buffer_size_kb
); dansync ;
ditambahkan setelah./wtest ;
panggilan. Lalu saya bisa melihatflush-8
,kworker
(kthreadd
di bawah dalamps axf
), dansync
itu sendiri, sebagai proses dalamftrace
memanggil fungsi seperti misalnyaata_bmdma_setup()
(yang merupakan bagian darilibata
, yangata_piix
dibangun di atas), atauget_nr_dirty_inodes()
.Anda tidak perlu menebak konfigurasi Anda. Di mesin saya, saya punya
File konfigurasi untuk kernel ini terletak di
/boot/config-3.2.0-4-amd64
.Anda bertanya tentang
ata_piix
. Mencari.config
file di atas , kita lihatCONFIG_ATA_PIIX=m
. kami dapat mengkonfirmasi ini dengan melakukankalau tidak
Jadi setidaknya di kernel saya, ini adalah modul.
sumber
:)
Pada sistem saya,grep ATA_PIIX /boot/config-2.6.38-16-generic
kataCONFIG_ATA_PIIX=y
, yang mungkin berarti pada kernel ini,ata_piix
adalah membangun "in-kernel", dan bukan sebagai modul. Bersulang!