Layered Structure

  • 드라이버 : 물리디스크 => 논리디스크로 추상화
  • FS : 논리 디스크 블럭들을 파일이라는 객체로 추상화
  • 시스템콜 : 인터페이스로 추상화
  • VFS : specific한 파일 시스템을 통일된 인터페이스로 추상화
  • 라이브러리 : 시스템콜 추상화
    • 커널로 진입해서 brk()로 반복해서 할당받으면 비효율적이므로 4096B를 미리 할당받음
    • 다른 mlloc이 오면 제공

  • ext2,3,4 FAT를 통합한 인터페이스로 사용자에게 제공해야한다.
  • block driver : I/O 스케줄링 , Request 통합
  • 라이브러리 => 시스템콜 , 모드스위치 필요 / 인텔에서는 trap
  • 파일시스템에서는 커널스레드 사용, 락, 세마포어
  • 파일시스템에서 데이터를 읽어올 때 페이지 캐시, 버퍼를 통해 읽어옴
    • 페이지 : 4KB
    • 버퍼캐시 : 필요한 아이노드 사이즈만큼 // ex)bread
    • 블럭레이어 : I/O

VFS

  • 소프트웨어 계층
  • 사용자 프로세스와 특정한 파일시스템의 중간 역할을 하는 레이어
    • 직접 호출하는 것이 아니라 함수 포인터를 활용한다.

VFS가 필요한 이유

  • 3개의 파일 시스템이 있다. 각각 파일시스템마다 open 함수가 다르고 inode 구조가 다르다.
  • 각각 호출하려면 너무 힘들다.
  • 층을 도입. ==> VFS (open으로 통일)
  • 사용자가 입력한 open을 inode를 통해 어느 파일시스템에 존재하는 open인지 조사를 함.
  • type를 판단해서 매핑을 함
  • 다양한 오퍼레이션을 정의

VFS에서 사용하고 있는 핵심적인 자료구조

  1. struct_file : 사용자관점)open된 파일 관리
  • file operations: open, read, write, lseek, ioctl
  1. struct_inode : FS관점) mode , inode number
  • create , link , unlink , mkdir , lookup
  1. address_number : 파일을 read ,write시 페이지로 매핑됨 ==> 읽어온 페이지들을 페이지 캐시로 관리.
  • address_space operations: readpage, writepage, set_page_dirty
  1. struct_dentry : 파일 이름에서 아이노드까지 연결 관리
  • dentry operations: d_hash, d_compare (for lookup), revalidate, ..
  1. struct_super_block : 파일시스템 자체를 관리.
  • superblock operations: statfs, sync_fs, alloc_inode, write_inode, …

  • 태스크 스트럭트 => 파일 디스크립터 => 터미널 가리킴 => 파일 스트럭쳐 => 5가지 자료구조
  • open된 파일들의 offset이 파일 스트럭쳐에 존재
  • dentry를 따라가면 inode를 가리키는 포인터가 존재.
    • inode가 어느 파일에 있는지 슈퍼블럭을 가리키는 필드가 있음.
    • 매핑 : 어느 어드레스 스페이스인지를 가리킬 수 있음
    • address는 페이지들의 집합. 위의 네모들이 해당 오프셋에 대응되는 데이터를 특정 페이지에 담아온다.

정리) 각각 자료구조는 오퍼레이션을 가지고 있다. 파일스트럭쳐는 파일 오퍼레이션 , 아이노드를 따라가면 아이노드 오퍼레이션: 아이노드를 생성하는 오퍼레이션 ....

파일시스템 입장에서 필요한 오퍼레이션

  • open/create: open, mkdir, link, lookup, alloc_inode, alloc_block, …
  • read/write: read, write, readdir, get_block, bio_submit, bread, …
  • page cache: readpage, writepage, set_dirty, …
  • mount: mount, fs_type, fill_super, …

  • hello.c의 아이노드를 알아낼 수 있는 인터페이스가 필요하다.
    • lookup사용 , 아이노드 할당 , 블럭 할당 등의 오퍼레이션이 필요
    • getblock : offset을 적용한 디스크 블럭의 위치 파악
    • biosubmit : 블럭i/o를 블록 드라이버에 보냄

파일시스템이 커널의 어떤 요소들과 상호작용?


1. System call: open, read, readdir, …
2. Page cache (buffer cache): readpage, …
3. Block driver: submit_bio, …
4. FS Initialization: mount, fs_type, …

  • 파일시스템을 통해 상호작용함

정리

  • read()가 vfs read를 호출 => 파일오퍼레이션 자료구조를 통해 normal한 read로 체크
  • normal한 read면 new_sync_read()로 이동
  • 여기서 specific한 fs로 이동. ext2일 경우 ext2_files_read_iter()로 이동
  • 여기서 direct i/o or page cache를 검색하는 부분으로 올라옴
  • 이후 버퍼를 뒤지고 발견이 되면 get_pages , 없으면 no_cache_page
  • 이후 버퍼드 리드 페이지 라는 함수를 부르게되고, 페이지를 할당받아서 lru에 집어넣고
    • 그 페이지를 인자로하여 readpage()를 호출함. // address_space operations
    • 여기서 vfs 인터페이스가 specific한 인터페이스로 매핑을 한다.
      ==> ext2_readpage
    • mpage_readpage 호출
    • ext2 get_block을 인자로 넘겨서 어느위치에 몇번 디스크 블록을 접근하면 되는지 완성해 준다. 그리고 submit_bio를 불러서 블럭레이어를 통해서 디바이스 드라이버로 들어간다.

0개의 댓글