この投稿が少々密集している場合は事前におApび申し上げますが、それをより適切に定式化するのに苦労しています...
- 以下の私の理解は正しいですか?そうでない場合、どこが間違っていますか?
- ディスク書き込み中にPCで発生するすべての側面について、ログデータを「キャプチャ」するためのより良いツールはありますか?
より詳細に-まず、私が使用しているOSは次のとおりです。
$ 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
だから、私は次の簡単な(たとえば、操作の失敗の通常のチェックがスキップされる)ユーザースペース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;
}
私はこれをビルドしgcc -g -O0 -o wtest wtest.c
ます。今、私はに書き込もうとしているので/tmp
、それはルートの下のディレクトリであることに注意して/
ください-私はチェックし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)
...
したがって、私のルートファイルシステム/
は/dev/sda
デバイスの1つのパーティションです(そして、他のパーティションも「スタンドアロン」ディスク/マウントとして使用しています)。このデバイスのドライバーを見つけるには、次を使用します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
...
したがって、/dev/sda
ハードディスクは明らかにata_piix
(およびsd
)ドライバーによって処理されます。
$ 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
私は多くのことを中断として古いのsyslogからプルする必要がありますが、上記のブート時のsyslogから適切なスニペット、のように思えるata_piix
(とsd
初めて中)ドライバキック。
混乱の私の最初のポイントは、私はそう観察することができないということですata_piix
か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
だから私の最初の質問は- ata_piix
ブート時のログでのみここでモジュールを観察できないのはなぜですか?ので、それはata_piix
(とがsd
)として構築されているビルトイン(モノリシック)カーネル内のドライバ(ロード可能)として構築されるのとは対照的に.ko
、カーネルモジュール?
そうです-だから今、ftrace
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
'
...そして、これは以下ftrace
に関するログの断片です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 | }
これが混乱の2番目のポイントです- 予想どおりwrite()
、kernel-space sys_write()
で生じたユーザー空間を観察できます。内でsys_write()
、セキュリティ関連の機能(例apparmor_file_permission()
)、「汎用」書き込み機能(例generic_file_aio_write()
)、ext4
ファイルシステム関連の機能(例ext4_journal_start_sb()
)を観察しますが、ドライバー(または)に関連するものは観察しませんか?!ata_piix
sd
トレースとプロファイリング-Yocto Projectページでは、blk
トレーサーを使用してftrace
ブロックデバイスの操作に関する詳細情報を取得することを推奨していますが、この例では何も報告されません。また、Linux Filesystem Drivers-Annon Inglorion(tutorfs)は、ファイルシステムをカーネルモジュール/ドライバーとして実装(できる?)する(提案する)ことを提案していますが、それも当てはまると思いext4
ます。
最後に、function_graph
トレーサーによって示された関数の隣にある角括弧でドライバー名を以前に観察したことを誓うことができましたが、私は物事を混同していたと思います-それはおそらくスタック(バック)トレースでそのように見えるかもしれませんが、関数グラフで。さらに、私は検査することができます/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]
...
...そして、ソースLinux / drivers / ata / ata_piix.cで確認し、例えばpiix_init_sata_map
が実際にの関数であることを確認しata_piix
ます。それはおそらく私に言う必要があります:カーネルでコンパイルされるモジュール(したがって、モノリシックカーネルの一部になります)は、どのモジュールからの情報を「失う」。ただし、個別の.ko
カーネルオブジェクトとして構築されたロード可能モジュールは、その情報を保持します(たとえば、[psmouse]
上記の角括弧内)。したがって、ftrace
ロード可能なカーネルモジュールからの機能についてのみ、「発信元モジュール」情報のみを表示することもできます。これは正しいです?
上記を考慮して、これは私が現在プロセスについて持っている理解です:
- 起動時に、
ata_piix
ドライバー/dev/sda
は、ハードディスクとの 間にDMA(?)メモリマッピングを確立します- このため、今後の
/dev/sda
via へのすべてのアクセスata_piix
はカーネルに対して透過的です(つまり、追跡可能ではありません)-すべてのカーネルが参照するため、メモリ位置への読み取り/書き込みのみです(特定の追跡可能なカーネル関数の呼び出しとは限りません)。function_graph
トレーサーによって報告されません
- このため、今後の
- ブート時に、
sd
ドライバーはさらにのパーティションを「解析」し、/dev/sda
それらを利用可能にし、パーティション間のメモリマッピングを処理します<->ディスクデバイス- 繰り返しますが、これ
sd
により、カーネルに対して透過的なアクセス操作が可能になります。
- 繰り返しますが、これ
- 両方以来
ata_piix
とsd
終わるん、その機能の一部はによって捕獲された場合でも、カーネル内にコンパイルされているftrace
、我々はから来るこれらの機能をどのモジュールの情報を得ることができない(離れてからソースファイルと「マニュアル」の相関関係) - 後で
mount
、パーティションと対応するファイルシステムドライバー(この場合ext4
)の 間の関係/バインディングを確立します- この時点から、マウントされたファイルシステムへのアクセスはすべて
ext4
、カーネルによって追跡可能な関数によって処理されます。しかし、ext4
カーネル内でコンパイルされているように、トレーサーは元のモジュール情報を提供できません
- この時点から、マウントされたファイルシステムへのアクセスはすべて
- したがって、
ext4
関数を介して呼び出される観察された「汎用」書き込みは、最終的にマッピングが確立されたメモリ位置にアクセスしますata_piix
が、それ以外は、ata_piix
データ転送に直接干渉しません(おそらくDMA(プロセッサの外部で処理されます(s)、したがって透過的です)。
この理解は正しいですか?
関連するサブ質問:
- 上記のセットアップでは、PCIデバイスドライバー(
ata_piix
)とファイルシステムドライバー(ext4
)を識別できます。しかし、「書き込み」実行パスのどこかで使用されるキャラクターまたはブロックドライバーはありますか? - これらのドライバーのどれがキャッシングを処理します(したがって、不必要なディスク操作はスキップまたは最適化されますか?)
- 私は以前から
/dev/shm
RAMのファイルシステムであることを知っています。mount | grep shm
私のレポート:none on /dev/shm type tmpfs (rw,nosuid,nodev)
。それとは対照的に/dev/sda
、shm
ファイルシステムには単に「独自の」アドレスからデバイスへのバスアドレスへの(DMA)マッピングがありません。したがって、tmpfs
ファイルシステムドライバを介したすべてのアクセスは、実際のRAMで行われますか?