이 게시물이 약간 조밀하거나 어색한 경우 사전에 사과하지만 더 잘 공식화하는 데 어려움을 겪고 있습니다 ... 기본적으로 하드 디스크 쓰기시 발생하는 사항을 연구하고 싶습니다.
- 아래의 내 이해가 정확합니까? 아니면 어디에서 잘못 되었습니까?
- 디스크 쓰기 도중 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
장치 의 하나의 파티션입니다 (그리고 다른 파티션도 "독립형"디스크 / 마운트로 사용하고 있습니다). 이 장치의 드라이버를 찾으려면 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 우리 | 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 우리 | common_file_perm (); 4604.352696 | 0) wtest-31632 | 2.198 우리 | } 4604.352697 | 0) wtest-31632 | 3.573 우리 | } 4604.352697 | 0) wtest-31632 | 4.979 우리 | } 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 우리 | _cond_resched (); 4604.352703 | 0) wtest-31632 | 1.994 우리 | } 4604.352704 | 0) wtest-31632 | | __generic_file_aio_write () { ... 4604.352728 | 0) wtest-31632 | | file_update_time () { ... 4604.352732 | 0) wtest-31632 | 0.756 우리 | 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 우리 | _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 우리 | 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 우리 | iov_iter_advance (); 4604.352825 | 0) wtest-31632 | | generic_perform_write () { 4604.352826 | 0) wtest-31632 | 0.709 우리 | 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 우리 | __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 우리 | 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 우리 | mutex_unlock (); 4604.352911 | 0) wtest-31632 | 0.727 우리 | generic_write_sync (); 4604.352912 | 0) wtest-31632 | ! 212.259 우리 | } 4604.352913 | 0) wtest-31632 | ! 213.845 우리 | } 4604.352914 | 0) wtest-31632 | ! 215.286 us | } 4604.352914 | 0) wtest-31632 | 0.685 우리 | __fsnotify_parent (); 4604.352916 | 0) wtest-31632 | | fsnotify () { 4604.352916 | 0) wtest-31632 | 0.907 우리 | __srcu_read_lock (); 4604.352918 | 0) wtest-31632 | 0.685 우리 | __srcu_read_unlock (); 4604.352920 | 0) wtest-31632 | 3.958 우리 | } 4604.352920 | 0) wtest-31632 | ! 228.409 우리 | } 4604.352921 | 0) wtest-31632 | ! 231.334 우리 | }
이것은 나의 두 번째 혼란 지점입니다 . 예상대로 write()
커널 공간으로 인해 발생한 사용자 공간을 관찰 할 수 있습니다 sys_write()
. 그리고 내 sys_write()
, 내가 (예 : 보안 관련 기능을 관찰 apparmor_file_permission()
(예) "일반적인"쓰기 기능 generic_file_aio_write()
) ext4
(예를 들어, 관련 기능을 특정 파일 시스템 ext4_journal_start_sb()
) -하지만 난 할 수 없습니다 에 관련된 아무것도 관찰 ata_piix
(또는 sd
) 드라이버를?!
추적 및 프로파일 링-Yocto 프로젝트 페이지 에서는 블록 장치 작동에 대한 자세한 정보를 얻기 위해 blk
추적 프로그램을 사용할 것을 제안 ftrace
하지만이 예제에서는 아무 것도보고하지 않습니다. 또한 Linux 파일 시스템 드라이버-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
비아에 대한 모든 향후 액세스ata_piix
는 커널에 투명합니다 (즉, 추적 할 수 없음). 모든 커널이 볼 수 있기 때문에 메모리 위치에 대한 읽기 / 쓰기 (특정 추적 가능한 커널 함수를 호출 할 필요는 없음)입니다.function_graph
추적자 가보고하지 않습니다
- 이 때문에
- 부팅시
sd
드라이버는 파티션을 "파싱"하여 파티션을/dev/sda
사용 가능하게하고 파티션 <-> 디스크 장치 간의 메모리 매핑을 처리합니다.- 다시, 이것은
sd
커널을 통해 액세스 작업을 투명하게해야합니다.
- 다시, 이것은
- 모두 이후
ata_piix
및sd
끝내는 그 기능 중 일부에 의해 포착되는 경우에도에서 커널 컴파일ftrace
, 우리가에서 온 것 그 기능을 모듈있는 정보를 얻을 수 없다 (떨어져에서 소스 파일과 "수동"상관 관계) - 나중에
mount
파티션과 해당 파일 시스템 드라이버 (이 경우ext4
) 사이의 관계 / 바인딩을 설정합니다.- 이 시점부터 마운트 된 파일 시스템에 대한 모든 액세스
ext4
는 커널에 의해 추적 가능한 기능에 의해 처리됩니다 . 그러나ext4
커널 내에서 컴파일 된 것처럼 추적 프로그램은 원래 모듈 정보를 제공 할 수 없습니다.
- 이 시점부터 마운트 된 파일 시스템에 대한 모든 액세스
- 따라서
ext4
함수 를 통해 호출 된 "일반적인"쓰기 는 궁극적으로 매핑이 설정된 메모리 위치에 액세스합니다.ata_piix
그러나 그 이외의 경우ata_piix
데이터 전송을 직접 방해하지 않습니다 (아마도 DMA (프로세서 외부)에서 처리 함) (들), 따라서 투명합니다).
이 이해가 맞습니까?
관련 하위 질문 :
- 위의 설정에서 PCI 장치 드라이버 (
ata_piix
)와 파일 시스템 드라이버 (ext4
)를 식별 할 수 있습니다 . "쓰기"실행 경로 어딘가에 사용되는 문자 또는 블록 드라이버가 있습니까? 그렇다면 어떤 것입니까? - 캐싱을 처리 할 드라이버는 무엇입니까 (따라서 불필요한 디스크 작업을 건너 뛰거나 최적화 하시겠습니까?)
- 전에는
/dev/shm
RAM의 파일 시스템 이라는 것을 알고 있습니다 .mount | grep shm
나를 위해 보고서 :none on /dev/shm type tmpfs (rw,nosuid,nodev)
. 합니까 그 평균이 - 달리/dev/sda
-shm
파일 시스템이 간단하게하는 장치에 버스 주소 "자신의"adrresses에서 (DMA) 매핑이 부족; 따라서tmpfs
파일 시스템 드라이버 를 통한 모든 액세스 는 실제 RAM으로 끝나는가?