Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

132199
1107
135860


[리눅스커널] 가상파일시스템/디버깅: 파일 객체 함수 오퍼레이션 확인하기(1) 13. 가상 파일 시스템

이번 소절에서 유저 어플리케이션에서 다음 함수를 호출하면 커널 가상 파일시스템에서 어떤 함수를 호출하는지 알아봅니다.
open
write
read
lseek
fsync
close 

실습 패치 코드 작성해보기 

소스 코드는 다음과 같으니 같이 입력해 봅시다.
01 #include <stdio.h>
02 #include <stdlib.h>
03 #include <unistd.h>
04 #include <sys/types.h>
05 #include <signal.h>
06 #include <string.h>
07 #include <fcntl.h>
08
09 #define FILENAME_NAME "/home/pi/sample_text.text"
10
11 int main() 
12 {
13    int fd = 0;
14    ssize_t read_buf_size;
15    off_t new_file_pos;
16
17    char buf[256];
18    char string[] = "Raspbian Linux!\n";
19
20   memset(buf, 0x0, sizeof(buf));
21    
22    fd = open(FILENAME_NAME, O_RDWR);
23   
24    read_buf_size = read(fd, buf, 256);
25    printf("%s", buf);
26
27    write(fd, string, strlen(string));
28    
29    new_file_pos = lseek(fd, (off_t)0, SEEK_SET);
30    
31    read_buf_size = read(fd, buf, 256);
32    printf("read again \n");
33    printf("[+]read buffer: %s \n", buf);
34
35   write(fd, string, strlen(string));
36   if ( -1 == fsync(fd)) {
37 printf( "fsync() fails"); 
38 exit(0);
39   }
40
41   close(fd);
42
43    return 0;
44 }


위 프로그램은 /home/pi/sample_text.text 파일을 읽고 쓰는 동작입니다.
따라서 다음과 같이 /home/pi 디렉토리로 이동해 "touch sample_text.text" 명령어를 입력해 파일을 먼저 만들어야 합니다.
root@raspberrypi:/home/pi# touch sample_text.text


코드 내용은 어렵지 않으니 간단히 리뷰하는 수준으로 설명을 드리겠습니다.

22~25번째 줄 코드를 보겠습니다.
22    fd = open(FILENAME_NAME, O_RDWR);
23   
24    read_buf_size = read(fd, buf, 256);
25    printf("%s", buf);

22번째 줄 코드에서 "/home/pi/sample_text.text" 파일을 오픈한 후 파일 디스크립터를 fd로 얻어옵니다. 이후 24번째 코드를 실행해 버퍼인 buf 변수를 통해 "/home/pi/sample_text.text" 내용을 읽어 터미널에 출력하는 동작입니다.

다음 27~29번째 줄 코드입니다.
27    write(fd, string, strlen(string));
28    
29    new_file_pos = lseek(fd, (off_t)0, SEEK_SET);

write() 함수를 호출해 "Raspbian Linux!\n" 스트링을 sample_text.text 파일 쓰기 버퍼에 써줍니다. 이후 lseek() 함수를 호출해 파일 포인터 위치를 가장 앞부분에 설정합니다.

이어서 31~33번째 줄 코드를 보겠습니다.
31    read_buf_size = read(fd, buf, 256);
32    printf("read again \n");
33    printf("[+]read buffer: %s \n", buf);

read() 함수를 호출해 sample_text.text 파일 버퍼를 읽어서 터미널에 출력합니다. 

다음 35~39번째 줄 코드를 보겠습니다.
35   write(fd, string, strlen(string));
36   if ( -1 == fsync(fd)) {
37 printf( "fsync() fails"); 
38 exit(0);
39   }

write() 함수를 호출해 "Raspbian Linux!\n" 스트링을 sample_text.text 파일 쓰기 버퍼에 써줍니다. 다음 36번째 줄 코드와 같이 fsync() 함수를 호출해 저장매체와 동기화를 수행합니다.

마지막 41번째 줄 코드를 보겠습니다.
41   close(fd);

close() 함수를 호출해 파일 디스크립터를 닫는 동작입니다.

리눅스 시스템 프로그램을 한번이라도 해본 분이면 이해할 수 있는 수준의 코드입니다.

위에서 소개한 코드를 rpi_vfs_file_operation.c 파일로 저장합니다.
코드를 입력했으니 컴파일을 해볼 차례입니다. 컴파일을 쉽게 하기 위해 다음과 같이 코드를 작성하고 파일 이름을 Makefile으로 저장합시다.
vfs_file_proc: rpi_vfs_file_operation.c
gcc -o vfs_file_proc rpi_vfs_file_operation.c

이후 다음과 같이 make 명령어를 입력해 rpi_vfs_file_operation.c 소스 파일을 컴파일합시다.
root@raspberrypi:/home/pi# make
gcc -o vfs_file_proc rpi_vfs_file_operation.c
오타없이 코드를 입력하면 위와 같은 메시지가 출력되면서 vfs_file_proc 파일이 생성될 것입니다. rpi_vfs_file_operation.c 소스 파일의 실행 파일 이름은 vfs_file_proc입니다.

ftrace 설정해보기 

이번에는 ftrace 설정 방법을 소개합니다.
01 #!/bin/bash
02
03 echo 0 > /sys/kernel/debug/tracing/tracing_on
04 sleep 1
05 echo "tracing_off" 
06
07 echo 0 > /sys/kernel/debug/tracing/events/enable
08 sleep 1
09 echo "events disabled"
10
11 echo  secondary_start_kernel  > /sys/kernel/debug/tracing/set_ftrace_filter
12 sleep 1
13 echo "set_ftrace_filter init"
14
15 echo function > /sys/kernel/debug/tracing/current_tracer
16 sleep 1
17 echo "function tracer enabled"
18
19 echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
20 echo 1 > /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/enable
21 echo 1 > /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/enable
22 sleep 1
23 echo "event enabled"
24
25 echo ext4_file_open ext4_file_write_iter > /sys/kernel/debug/tracing/set_ftrace_filter
26 echo ext4_file_read_iter ext4_llseek >> /sys/kernel/debug/tracing/set_ftrace_filter
27 echo ext4_sync_file __close_fd >> /sys/kernel/debug/tracing/set_ftrace_filter
28 sleep 1
29 echo "set_ftrace_filter enabled"
30
31 sleep 1
32 echo "set_ftrace_filter enabled"
33
34 echo 1 > /sys/kernel/debug/tracing/options/func_stack_trace
35 echo 1 > /sys/kernel/debug/tracing/options/sym-offset
36 echo "function stack trace enabled"
37
38 echo 1 > /sys/kernel/debug/tracing/tracing_on
39 echo "tracing_on"
이전 장에서 소개한 ftrace 설정 명령어와 다른 부분 위주로 살펴보겠습니다.

먼저 다음 명령어를 봅시다.
19 echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
20 echo 1 > /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/enable
21 echo 1 > /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/enable

open, read, write, lseek, fsync, close 시스템 콜 동작을 확인하기 위해 프로세스 스케줄링과 시스템 콜 ftrace 이벤트를 키는 명령어입니다.

이어서 함수 필터를 설정하는 25~27번째 줄 명령어를 보겠습니다.
25 echo ext4_file_open ext4_file_write_iter > /sys/kernel/debug/tracing/set_ftrace_filter
26 echo ext4_file_read_iter ext4_llseek >> /sys/kernel/debug/tracing/set_ftrace_filter
27 echo ext4_sync_file __close_fd >> /sys/kernel/debug/tracing/set_ftrace_filter


위 명령어에서 26~27번째 줄 볼드체로 된 부분과 같이 ">>" 기호를 입력합시다. 만약 ">>" 대신 ">" 기호를 입력하면 윗 줄에 있는 명령어로 설정한 함수 필터 정보가 지워집니다.


위 명령어는 set_ftrace_filter에 다음 함수를 설정합니다.
ext4_file_open()
ext4_file_write_iter()
ext4_file_read_iter()
ext4_llseek()
ext4_sync_file()
__close_fd()

함수 이름이 조금 친숙해 보이지 않아요? 모두 13.3 절에서 분석한 ext4 파일시스템 파일 오퍼레이션 함수입니다.

위에서 소개한 ftrace 설정 명령어를 rpi_vfs_file_trace.sh 이름으로 저장합시다.

ftrace 로그 추출하는 방법 알아보기 

실습 코드 실행 파일(vfs_file_proc)이 준비됐고 ftrace 설정 방법을 확인했습니다. 이어서 ftrace 를 설정하고 vfs_file_proc 파일을 실행할 차례입니다.

먼저 rpi_vfs_file_trace.sh 셸 스크립트를 실행해 ftrace를 설정합시다.
root@raspberrypi:/home/pi # ./rpi_vfs_file_trace.sh

다음 "./vfs_file_proc" 명령어를 입력해 vfs_file_proc 파일을 실행합니다.
root@raspberrypi:/home/pi # ./vfs_file_proc
read again 
[+]read buffer: Raspbian Linux!

다음 ftrace 받는 방법을 소개합니다.
#!/bin/bash

echo 0 > /sys/kernel/debug/tracing/tracing_on
echo "ftrace off"

sleep 3

cp /sys/kernel/debug/tracing/trace . 
mv trace ftrace_log.c

위 명령어를 입력해 get_ftrace.sh 셸 스크립터로 저장합니다. 
이후 다음 명령어로 이 셸 스크립트를 실행하면 같은 폴더에 ftrace 로그를 저장한 ftrace_log.c 파일이 생성됩니다. 
root@raspberrypi:/home/pi # ./get_ftrace.sh 


"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)


Reference(가상 파일시스템)

가상 파일시스템 소개
파일 객체
파일 객체 함수 오퍼레이션 동작
프로세스는 파일객체 자료구조를 어떻게 관리할까?
슈퍼블록 객체
아이노드 객체
덴트리 객체
가상 파일시스템 디버깅



핑백

덧글

댓글 입력 영역