본문으로 이동
  • 현재 모든 문서는 작성 중입니다. 보시는 데 불편함이 있더라도 양해 부탁드립니다.

운영체제 기본/Linux의 파일 읽기: 두 판 사이의 차이

~ldmsys
mmap 파일 메모리 매핑 각론을 연결; 페이지 캐시 상세 확장은 보류
read 각론에 VFS 분기 연결만 보충하고 파일시스템 구현 문서로 연결
 
(같은 사용자의 중간 판 하나는 보이지 않습니다)
18번째 줄: 18번째 줄:
<code>current</code>는 현재 실행 중인 태스크를 나타낸다. <code>current->files</code>로 접근하는 <code>files_struct</code>에 파일 디스크립터 테이블이 연결되어 있고, <code>fdtable.fd</code>는 <code>struct file</code> 포인터의 배열이다. 같은 fd 값도 어느 테이블에서 찾는지에 따라 다른 열린 파일을 가리킬 수 있다.
<code>current</code>는 현재 실행 중인 태스크를 나타낸다. <code>current->files</code>로 접근하는 <code>files_struct</code>에 파일 디스크립터 테이블이 연결되어 있고, <code>fdtable.fd</code>는 <code>struct file</code> 포인터의 배열이다. 같은 fd 값도 어느 테이블에서 찾는지에 따라 다른 열린 파일을 가리킬 수 있다.


이 관계를 설명용 의사 코드로 줄이면 다음과 같다. 실제 소스의 연속된 인용이 아니며, 그대로 커널에 넣어 사용할 코드도 아니다.
파일 디스크립터 테이블의 참조 관계:


<pre>
<pre>
45번째 줄: 45번째 줄:
</pre>
</pre>


<code>ksys_read()</code>는 얻은 객체를 <code>vfs_read()</code>에 넘긴다. <code>vfs_read()</code>는 접근 모드, 사용자 버퍼 등에 관한 검사를 거쳐 읽기 구현을 선택한다. 분기만 뽑은 설명용 의사 코드는 다음과 같다.
<code>ksys_read()</code>는 얻은 객체를 <code>vfs_read()</code>에 넘긴다. <code>vfs_read()</code>는 접근 모드, 사용자 버퍼 등에 관한 검사를 거쳐 읽기 구현을 선택한다.


<pre>
<pre>
61번째 줄: 61번째 줄:


== 파일시스템으로 넘어가는 경계 ==
== 파일시스템으로 넘어가는 경계 ==
<code>vfs_read()</code>는 [[운영체제 기본/Linux의 파일시스템/VFS와 파일 객체|VFS의 공통 파일 연산]]을 통해 실제 구현으로 연결된다. 열린 파일에 어떤 연산표가 설정되는지는 <code>open()</code>과 파일시스템의 객체 구성에서 결정된다.
응용 프로그램에는 '''fd와 읽기 인터페이스'''가 보인다. 커널 내부에서는 '''테이블 조회로 객체를 찾고, 연산 테이블로 구현을 선택'''한다.
응용 프로그램에는 '''fd와 읽기 인터페이스'''가 보인다. 커널 내부에서는 '''테이블 조회로 객체를 찾고, 연산 테이블로 구현을 선택'''한다.


다만 함수 포인터를 호출하는 것만으로 읽기가 끝나는 것은 아니다. 선택된 구현 아래에서 파일시스템, 캐시, 장치 드라이버 등의 처리가 이어질 수 있다.
다만 함수 포인터를 호출하는 것만으로 읽기가 끝나는 것은 아니다. 선택된 구현 아래에서 파일시스템, 캐시, 장치 드라이버 등의 처리가 이어질 수 있다.
[[운영체제 기본/Linux의 파일시스템/ext4의 파일 읽기|ext4의 일반 파일 읽기]]는 공통 페이지 캐시로 이어진다. [[운영체제 기본/Linux의 파일시스템/procfs의 파일 읽기|/proc/uptime 읽기]]는 커널 상태로 문자열을 만든다. 같은 <code>read()</code>를 호출해도 데이터를 얻는 경로가 달라지는 지점이다.


== 관련 각론 ==
== 관련 각론 ==
* [[운영체제 기본/Linux의 파일시스템|Linux의 파일시스템]]: VFS, ext4, procfs와 공통 페이지 캐시.
* [[운영체제 기본/Linux의 파일 메모리 매핑|mmap을 통한 파일 읽기]]: 주소 영역 등록, 첫 메모리 접근, 파일 폴트와 PTE 설치.
* [[운영체제 기본/Linux의 파일 메모리 매핑|mmap을 통한 파일 읽기]]: 주소 영역 등록, 첫 메모리 접근, 파일 폴트와 PTE 설치.


== 참고 문헌 ==
== 참고 문헌 ==
<references />
<references />

2026년 10월 31일 (토) 08:18 기준 최신판

목차 · 관련 총론: 추상화, 파일과 입출력

응용 프로그램이 read(fd, buf, count)를 호출하면 커널은 fd로 열린 파일 객체를 찾고, 그 객체에 연결된 읽기 구현을 호출한다. 기준은 Linux v6.12다.

일반적인 read() 경로를 대상으로 한다. io_uring은 별도 경로이며, mmap을 통한 접근은 주소 공간 설정과 페이지 폴트로 이어진다.

fd에서 struct file까지

fd = 3
  |
  +--> current->files     (files_struct)
             |
             +--> fdt     (fdtable)
                    |
                    +--> fd[3] --> struct file

current는 현재 실행 중인 태스크를 나타낸다. current->files로 접근하는 files_struct에 파일 디스크립터 테이블이 연결되어 있고, fdtable.fd는 struct file 포인터의 배열이다. 같은 fd 값도 어느 테이블에서 찾는지에 따라 다른 열린 파일을 가리킬 수 있다.

파일 디스크립터 테이블의 참조 관계:

files = current->files;
table = files->fdt;
opened_file = table->fd[fd];

실제 ksys_read()는 fdget_pos()를 통해 객체를 얻는다. 그 아래의 fdget(), __fget_light()와 조회 함수들은 참조와 동시 접근을 처리한다. 위 그림에서는 이 부분을 생략했다. 직접 배열을 조회하는 코드에는 이러한 보호가 없으므로 실제 조회 함수를 대신할 수 없다.

소스:

struct file에서 읽기 연산까지

struct file의 f_op는 연산 함수들을 모은 file_operations를 가리킨다. 파일마다 응용 프로그램의 호출 형태를 바꾸는 대신, 커널 안에서 해당 대상에 맞는 연산을 선택하는 구조다.

struct file
    |
    +--> f_op (file_operations)
              |
              +--> read
              |
              +--> read_iter

ksys_read()는 얻은 객체를 vfs_read()에 넘긴다. vfs_read()는 접근 모드, 사용자 버퍼 등에 관한 검사를 거쳐 읽기 구현을 선택한다.

if (opened_file->f_op->read)
    opened_file->f_op->read(...);
else if (opened_file->f_op->read_iter)
    new_sync_read(...);

new_sync_read()는 read_iter 호출에 필요한 요청과 버퍼 정보를 구성한다. 사용 가능한 함수 포인터에 따라 한 경로를 선택한다.

소스:

파일시스템으로 넘어가는 경계

vfs_read()는 VFS의 공통 파일 연산을 통해 실제 구현으로 연결된다. 열린 파일에 어떤 연산표가 설정되는지는 open()과 파일시스템의 객체 구성에서 결정된다.

응용 프로그램에는 fd와 읽기 인터페이스가 보인다. 커널 내부에서는 테이블 조회로 객체를 찾고, 연산 테이블로 구현을 선택한다.

다만 함수 포인터를 호출하는 것만으로 읽기가 끝나는 것은 아니다. 선택된 구현 아래에서 파일시스템, 캐시, 장치 드라이버 등의 처리가 이어질 수 있다.

ext4의 일반 파일 읽기는 공통 페이지 캐시로 이어진다. /proc/uptime 읽기는 커널 상태로 문자열을 만든다. 같은 read()를 호출해도 데이터를 얻는 경로가 달라지는 지점이다.

관련 각론

참고 문헌