| Write/Read/Open 처리 과정 이해
[정리]
1. 주제
- Linux Write/Read/Open의 처리 과정에 대한 이해
2. 전체 내용 요약
1) Write
[1) Write]
I/O에 대해 크게 2가지로 direct i/o와 buffered i/o 나눠짐
무조건적으로 block layer를 거치는 것은 아님. buffered I/O를 하게 되면 block layer를 접근하지 않음
buffered 되는 것들은 크게 두 가지로 data block과 meta 정보임
이 두개의 정보를 buffering하기 위해 page cache를 할당 받아 사용
앞 시간에서 배운 anonymous page와 page cache의 차이점은 아래와 같음
anonymous page : file과는 상관 없으며, stack, heap 같은 것이 예임
page cache: disk block이 유지되는 곳. data block의 내용일 수도 있고, inode 같은 meta 정보일 수도 있음
pagecache: buffers + cached, 파일 관련된 내용이 저장된 곳이며, anonymous page와 구분해 파악 필요
## 하나의 task가 anonymous page를 차지하고 있는 크기 확인 법
$ cat /proc/$$/status | grep An
$$는 현재 bash의 pid 번호를 나타내며, 현재 bash가 차지하고 있는 anonymous page의 크기를 RssAnon과 같음
B. Buffered write
Buffered I/O의 3단계는 아래와 같으며 이후에선 buffered I/O에 대해 실습을 진행 함
1) write_begin : pagecache 준비
2) user data copy : pagecache 쓰기
3) write_end : pagecache dirty 작업
<Buffered i/o write 실습>
<buffered i/o write 실습>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp = fopen("hello.txt", "w");
if (fp) {
fprintf(fp, "hello linux filesystem\n");
fclose(fp);
sync();
}
}
$ sudo uftrace record -K 30 -d write.uftrace.data ./write
$ uftrace tui (기존에는 replay로 봤는데, tui로 접었다 폈다를 할 수 있음)
fwrite 부분에 sys_write가 없는 이유는? 왜 fclose 부분에 있을까?
fwrite는 sys_write를 호출 안하는 것이 아님. 상황마다 상이함. 어떤 경우에선 fclose에, 어떤 경우에는 fwrite에 sys_write가 존재 할 수 있음. printf가 compile 시점에 여러가지 방법으로 설정되듯이 sys_write도 fopen/fclose 모두에서 호출될 수 있음
generic_perform_write는 bufferd_i/o를 실행시키는 핵심 함수.
앞에서 언급된 fs의 write_begin과 write_end가 포함되어 있음
mark_buffer_dirty : dirty bit 체크 하는 부분 (data)
mark_inode_dirty : dirty bit 체크 하는 부분 (inode)
stat을 통해 file의 변경사항을 볼 수 있음
<위의 과정에 tracing 결과에 실제 코드로 확인 실습>
sys_write -> ... -> __vfs_write -> .. -> file->f_op->write_iter => ext4_file_write_iter를 호출 함
ext4_file_write_iter -> __generic_file_write_iter -> generic_perform_write
최종 generic_perform_write에서 write_begin과 copy_from_user 그리고 write_end가 존재한다.
밑의 세 가지 부분에 대해 코드 상으로 더 확인할 것이다.
1) write_begin : ext4_da_write_begin
- page caching을 위해 page buffer가 write_begin에서 어디 부분에서 할당되는지
2) copy from user : iov_iter_copy_from_user_atomic
- copy_from_user 부분에서 실제 write가 어디에서 진행되는지
3) write_end : ext4_da_write_end
- write_end에서 data (+meta)가 어디에서 dirty가 체크 되는지
1) page caching을 위해 실제 page buffer를 할당 받는 위치는create_page_buffers이다.
2) kmap으로 addr 할당 받은 후 memcpy_from_page를 통해 copy from user를 수행 한다.
...
3-1) Data에 대한 dirty 체크
...
3-2) inode에 대한 dirty 체크
write 추적에 대한 uftrace 첨부 파일