Bu yazı biraz yoğun / dağınıksa önceden özür dilerim, ama daha iyi formüle etmekte zorlanıyorum ... Temel olarak, bir sabit disk yazma üzerine neler olduğunu incelemek istiyorum ve bilmek istiyorum:
- Aşağıdaki anlayışım doğru mu - değilse, nerede yanlış gidiyorum?
- Bir disk yazma sırasında, bilgisayarda meydana gelen tüm yönler hakkında günlük verilerini "yakalamak" için daha iyi bir araç var mı?
Daha ayrıntılı olarak - ilk olarak, kullandığım işletim sistemi:
$ 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
Yani, aşağıdaki basit (örneğin işlemlerin başarısızlığı için olağan kontroller atlanır) kullanıcı alanı C programı var 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;
}
Bunu ile inşa ediyorum gcc -g -O0 -o wtest wtest.c
. Şimdi, yazmaya çalıştığımdan beri /tmp
, kök altında bir dizin olduğuna dikkat /
ediyorum - bu yüzden kontrol ediyorum 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)
...
Bu yüzden, kök dosya sistemim cihazın /
bir bölümüdür /dev/sda
(ve diğer bölümleri de "bağımsız" diskler / bağlar olarak kullanıyorum). Bu aygıtın sürücüsünü bulmak için şunu kullanıyorum 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
...
Yani, /dev/sda
sabit disk görünüşte sürücü ata_piix
(ve sd
) tarafından ele alınmaktadır .
$ 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
Ben çok askıya olarak eski syslog çekmek zorunda, ama yukarıda ata_piix
(ve sd
) sürücü ilk kez başladığında , önyükleme zamanında sistem pasajı uygun snippet gibi görünüyor .
İlk kafa karışıklığım, ata_piix
veya sd
sürücüleri başka türlü gözlemleyemem :
$ 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
Öyleyse ilk sorum - ata_piix
modülü burada neden göremiyorum , sadece önyükleme zamanı günlüklerinde? Çünkü ata_piix
(ve sd
) (yüklenebilir) .ko
çekirdek modülleri olarak inşa edilmesinin aksine (monolitik) çekirdeğe yerleşik sürücüler olarak mı inşa edilmiş ?
Tamam - şimdi, programı ftrace
Linux yerleşik işlev izleyicisi ile çalıştırdıktan sonra neler olduğunu gözlemlemeye çalışıyorum .
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
'
... ve işte ftrace
günlükle ilgili bir pasaj write
:
4604.352690 | 0) wtest-31632 | | sys_write () { 4604.352690 | 0) wtest-31632 | 0.750 bize | 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 bize | } 4604.352697 | 0) wtest-31632 | 3.573 bize | } 4604.352697 | 0) wtest-31632 | 4.979 bize | } 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 bize | ) (_Cond_resched; 4604.352703 | 0) wtest-31632 | 1.994 bize | } 4604.352704 | 0) wtest-31632 | | __generic_file_aio_write () { ... 4604.352728 | 0) wtest-31632 | | file_update_time () { ... 4604.352732 | 0) wtest-31632 | 0.756 bize | 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 bize | ) (_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 bize | ) (Mnt_drop_write; 4604.352822 | 0) wtest-31632 | + 93.541 bize | } 4604.352823 | 0) wtest-31632 | | generic_file_buffered_write () { 4604.352824 | 0) wtest-31632 | 0.654 bize | iov_iter_advance (); 4604.352825 | 0) wtest-31632 | | generic_perform_write () { 4604.352826 | 0) wtest-31632 | 0.709 bize | 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 bize | ) (__Block_write_begin; 4604.352849 | 0) wtest-31632 | + 21.128 bize | } 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 bize | ) (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 bize | ) (Mutex_unlock; 4604.352911 | 0) wtest-31632 | 0.727 bize | generic_write_sync (); 4604.352912 | 0) wtest-31632 | ! 212.259 bize | } 4604.352913 | 0) wtest-31632 | ! 213.845 bize | } 4604.352914 | 0) wtest-31632 | ! 215.286 bize | } 4604.352914 | 0) wtest-31632 | 0.685 bize | __fsnotify_parent (); 4604.352916 | 0) wtest-31632 | | fsnotify () { 4604.352916 | 0) wtest-31632 | 0.907 bize | ) (__Srcu_read_lock; 4604.352918 | 0) wtest-31632 | 0.685 bize | ) (__Srcu_read_unlock; 4604.352920 | 0) wtest-31632 | 3.958 bize | } 4604.352920 | 0) wtest-31632 | ! 228.409 bize | } 4604.352921 | 0) wtest-31632 | ! 231.334 bize | }
Bu benim ikinci karışıklık noktam - Beklendiği gibi write()
bir çekirdek alanı ile sonuçlanan kullanıcı alanını gözlemleyebilirim sys_write()
; ve içinde sys_write()
, ben (örn güvenlikle ilgili işlevleri gözlemlemek apparmor_file_permission()
(örn), "jenerik" yazma fonksiyonları generic_file_aio_write()
,) ext4
(örn ilgili işlevleri dosya sistemi ext4_journal_start_sb()
) - ama do not ile ilgili her şeyi gözlemlemek ata_piix
(veya sd
) sürücülerin?!
Sayfa İzleme ve profil oluşturma - Yocto Projesi kullanarak anlaşılacağı blk
içinde izleyici ftrace
blok aygıt operasyon hakkında daha fazla bilgi almak için, ancak bu örnekle benim için hiçbir şey bildirir. Ayrıca, Linux Dosya Sistemi Sürücüleri - Annon Inglorion (tutorfs) , dosya sistemlerinin çekirdek modülleri / sürücüleri olarak da (can?) Uygulandığını ve bunun da böyle olduğunu tahmin ediyorum ext4
.
Son olarak, daha önce function_graph
izleyicinin gösterdiği işlevin yanındaki köşeli parantezlerde sürücü adını gözlemlediğime yemin edebilirdim , ama sanırım bir şeyler karıştırdım - muhtemelen yığın (geri) izlerinde böyle görünebilir, ancak değil fonksiyon grafiğinde. Ayrıca şunları da inceleyebilirim /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]
...
... ve kaynak Linux / drivers / ata / ata_piix.c ile kontrol ederek , örneğin piix_init_sata_map
gerçekten bir işlev olduğunu doğrulayın ata_piix
. Muhtemelen bana şunu söylemelidir: çekirdekte derlenen modüller (böylece monolitik çekirdeğin bir parçası olurlar) hangi modülden geldikleri bilgisini "kaybederler"; bununla birlikte, ayrı .ko
çekirdek nesneleri olarak inşa edilen yüklenebilir modüller bu bilgiyi korur (örneğin [psmouse]
, köşeli parantez içinde gösterilmiştir). Bu nedenle, ftrace
sadece yüklenebilir çekirdek modüllerinden gelen işlevler için yalnızca "kaynak modül" bilgilerini gösterebilir. Bu doğru mu?
Yukarıdakiler dikkate alındığında, şu anda bu süreçle ilgili sahip olduğum anlayış:
- Önyükleme zamanında
ata_piix
sürücü/dev/sda
ve sabit disk arasında bir DMA (?) Bellek eşlemesi oluşturur- bu nedenle, gelecekteki tüm erişimleri
/dev/sda
aracılığıata_piix
(izlenebilir değildir) çekirdeğe şeffaf olacak - çekirdek görecekti tüm beri, sadece (ille değil spesifik izlenebilir çekirdek fonksiyonları çağrıları) bellek konumlarına yazar / okur, hangifunction_graph
izleyici tarafından rapor edilmez
- bu nedenle, gelecekteki tüm erişimleri
- Önyükleme zamanında,
sd
sürücü ayrıca bölümlerini "ayrıştırır",/dev/sda
kullanılabilir hale getirir ve muhtemelen bölümler <-> disk aygıtı arasındaki bellek eşlemelerini işler.- yine, erişim işlemlerini
sd
çekirdeğe şeffaf hale getirmelidir
- yine, erişim işlemlerini
- Her ikisi de
ata_piix
vesd
çekirdek içinde derlendiğinden, işlevlerinden bazıları yakalansa bileftrace
, bu işlevlerin hangi modülden geleceği hakkında bilgi alamayız (kaynak dosyalarıyla "manuel" korelasyon dışında) - Daha sonra
mount
bir bölüm ile ilgili dosya sistemi sürücüsü arasında bir ilişki / bağ kurar (bu durumdaext4
)- bu noktadan sonra, bağlı dosya sistemine tüm erişim
ext4
, çekirdek tarafından izlenebilir işlevler tarafından gerçekleştirilecektir; ancakext4
çekirdekte derlendiği gibi , izleyici bize kaynak modül bilgilerini veremez
- bu noktadan sonra, bağlı dosya sistemine tüm erişim
- Dolayısıyla,
ext4
işlevler aracılığıyla çağrılan gözlenen "genel" yazma işlemleri sonuçta eşlemesi tarafından oluşturulan bellek konumlarına erişecektirata_piix
- ancak bunun dışındaata_piix
veri aktarımlarına doğrudan müdahale etmez (muhtemelen DMA tarafından işlenir (işlemcinin dışında) ve dolayısıyla şeffaftır).
Bu anlayış doğru mu?
İlgili bazı sorular:
- Yukarıdaki kurulumumda bir PCI aygıt sürücüsü (
ata_piix
) ve bir dosya sistemi sürücüsü (ext4
); ancak "yazma" yürütme yolunda bir yerde kullanılan karakter ya da blok sürücüleri var mı? - Bu sürücülerden hangileri önbelleğe almayı işleyebilir (böylece gereksiz disk işlemleri atlanır veya optimize edilir?)
- Bundan önce
/dev/shm
RAM'de bir dosya sistemi olduğunu biliyorum ;mount | grep shm
Benim için raporlar:none on /dev/shm type tmpfs (rw,nosuid,nodev)
. Demek oluyor o - aksine/dev/sda
-shm
dosya sistemi basitçe bir cihaz doğru otobüs adreslerine "kendi" adrresses (DMA) eşleştirmesini yoksun; ve böylecetmpfs
dosya sistemi sürücüsü üzerinden tüm erişim gerçek RAM ile sonuçlanır?