FS

OS

  • 자원 관리자
    • 물리 자원 : CPU 메모리 디스크 네트워크
    • 추상화 자원 : 프로세스 , 스레드 , 페이지 , 파일 , 소켓
  • 컴퓨팅 계산 환경 제공
    • 시스템콜 지원 : fork brk open socket

자원 관리

  • CPU => 프로세스로 관리
  • 메모리 => 가상메모리, 페이지로 관리
  • 디스크 => 파일시스템으로 관리
  • 디바이스 => 디바이스 드라이버
  • 네트워크 - 소켓 TCP IP
  • 물리적인 자원을 논리적으로 만들어서 관리하는 것이 OS
  • OS는 자원들에 대한 API(시스템 콜)을 지원하여 자원을 사용할 수 있도록 한다.

FS

  • 운영체제의 한 구성요소. 스토리지 관리. (디스크, 플래시 메모리)
    • DRAM VS Storage
      1. 속도 2. 휘발성 3. 인터페이스 4. 용량
    • 플래시 메모리 - 마이크로 세컨드 , 디스크 : 밀리초
    • DRAM : 휘발성 DISK : 비휘발성
    • 바이트 단위 접근 : cpu로 접근 가능 - DRAM
    • 섹터 단위 접근 : Storage - 디스크 내용을 메모리로 올리고 이후 접근 가능

FS의 목표

  • 고성능

    • 병목현상 : 느리기 때문에 전체 시스템에 병목이 되는 경우가 있음
    • EX) 컴퓨터를 하다가 우우웅 소리가 나면서 마우스가 동작X => I/O 스토리지가 병목
  • 많은 수의 파일을 지원해야함

    • 큰용량
    • 특히 빅데이터 시대에서 그 중요성이 커짐
  • 일관성

    • 비휘발성
    • 문제가 발생하지 않도록 유지해야한다. - 재부팅해도 여전하다.
  • 스토리지 인식

    • 최적화 ,신뢰성 보장
    • 원래는 바이트단위로 파일시스템이 동작했으니 NVM을 위해서는 다르게 파일시스템이 설계되어야함.
    • 스토리지의 특성에 따라 파일시스템을 다르게 설계해야한다.
    • 플래시 메모리 , NVM , NETWORK , Disk
    • ISP
  • 스몰 스토리지 지원

    • ioT, USB
  • Example of FS in Linux
    Ext2/3/4: block group, journaling, extent-based FS
    FAT, exFAT: FAT based FS
    F2FS: Flash friendly FS
    Btrfs: COW based FS, strong consistency
    NFS, GFS, Ceph, ..: FS for distributed systems
    XFS: Extent and journaling based FS, Parallel I/Os (scalable)
    Nilfs: LFS in Linux
    Fuse: User-level FS
    NOVA: NVM-aware FS
    Zonefs: FS for ZNS SSDs
    QNX4/QNX6: FS for QNX OS
    Logical: proc, sysfs, debugfs,

    추상화와 층 구조

층 구조

  • 추상화 : 일반화 과정, 어떠한 정보를 감추고 특정한 목적에 부합되는 정보만 유지할 수 있도록 만드는 과정
  • ex) 자동차 - 운전자가 자동차를 운전하기 위해서는 운전자를 위한 정보만 알면된다.
  • 컴퓨터에서는 개발자가 자기가 관심있는 개념에만 집중할 수 있도록 하는 것, 층 구조로 구현
  • fs도 층 구조

  • ls -l을 치면 위의 사진과 같은 단계로 통한다.

디스크

  • 플래터 : 원판

  • 실린더 : 원판 모음

  • 섹터 - 512B

  • 스핀들 : 축

  • arm 앞에 head로 데이터 센싱

  • 디스크 접근 : 섹터 어드레싱 : 어떤 헤드를 사용해서 섹터 위, 아래쪽에 데이터를 저장할 수 있기 때문에 각각 서피스마다 헤드가 필요. 어느 헤드로 가서 어느 트랙으로 가서 섹터를 읽어달라. 요청을 하게됨.

    1. 헤드가 원하는 섹터로 움직여야함
    1. 디스크가 회전을 해서 원하는 섹터가 헤드 아래로 가야함
    1. 데이터 센싱 : read , write the sector

디스크의 계층 구조

  • 디스크 디바이스 드라이버: 복잡한 물리디스크를 논리적인 디스크로 추상화

  • 논리적인 디스크는 원기둥 형태로 그려진다. 이걸 나눠서 디스크 블럭이라 한다.

    • 디스크 = 디스크 블럭의 집합
    • 이런 복잡한 하드디스크를 디스크블럭으로 추상화 시켜주는것이 디바이스 드라이버
  • 디스크블럭 : 보통 4KB or 8KB

  • 섹터 512B => 0.5KB => 8x0.5 = 4KB

  • 하나의 디스크블럭은 섹터가 8개 있어야한다.

  • 디스크 블럭이 어느 섹터에있는지 매핑하는게 디스크 디바이스 드라이버

  • 디스크 초기화 , 에러핸들링, 스케줄링 => 디스크 디바이스 드라이버

  • 그 위에 파일시스템이 존재

  • 파일시스템은 디스크 블럭들을 파일이라는 개념으로 추상화

  • offset : 읽거나 쓰려는 위치

  • 파일의 크기가 10000바이트라 가정. 10000바이트를 집어넣으려면 디스크블럭이 3개필요

  • 0번은 다른 파일이 사용하고 있다.

  • 1번은 free상태다.

  • 1,5,6에 할당을 하게 될 걸로 예상됨 (불연속 할당)

    • 이것에 대한 관리를 inode나 FAT으로 한다.
    • 파일시스템이 관리하고 있는 메타데이터
  • 만약 13,14,15로 할당을 하면? (연속 할당)

  • 원본 파일에서 append 할 경우 연속적으로 할당이 불가능해진다!

  • 그래서 불연속 할당을 사용한다. => inode , fat으로

  • 파일 시스템 위에 시스템 콜 (추상화)
    • open , read, write ,close를 인터페이스를 통해서 접근할 수 있도록 해줌.
    • 유저레벨과 시스템콜 사이에 라이브러리와 같은 요소가 존재.
  • 이 층 구조를 통하여 사용자가 스토리지에 접근하도록 해 준다.

유저의 입장

  1. 파일 name에 접근
  2. file name을 통해 시스템콜로 내려간다.
  3. file name을 파일디스크립터(fd)로 바꾼다.
  4. fd를 파일시스템으로 내려가면 file structure , inode structure 등의 메타데이터를 사용해서 논리디스크 블럭을 가리키게 된다.
  5. 이것을 드라이버로 가져다주면 섹터로 바꿔준다.

실습

1. Everything is a file in Linux (also in UNIX)

2. 나만의 Cat 만들기

int main(int argc, char *argv[])
{
        int fd, read_size, write_size;
        char buf[MAX_BUF];

        if (argc !=2){
                printf("USAGE: %s file_name\n", argv[0]);
                exit(-1);
        }
        fd = open(argv[1], O_RDONLY);
        if(fd < 0){
                printf("Open Error\n");
                exit(-1);
        }
        while(1) {
        read_size = read(fd,buf,MAX_BUF);
        if(read_size == 0){
                break;
        }
        write_size = write(STDOUT_FILENO, buf, read_size);
        }
        close(fd);
}

3. Cat Redirection

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define MAX_BUF 512

int main(int argc, char *argv[])
{
    int fd, read_size, write_size;
    int fd1; // for redirection
    char buf[MAX_BUF];

    if (argc != 3) {
        printf("USAGE: %s input_file_name output_file_name\n", argv[0]);
        exit(-1);
    }
    fd = open(argv[1], O_RDONLY);
    if(fd < 0){
        perror("Open Error");
        exit(-1);
    }
    fd1 = open(argv[2], O_WRONLY | O_CREAT | O_APPEND, 0641); // 원본파일 보존+ 내용추가
    if (fd1 < 0) {
        perror("Open Error");
        close(fd);
        exit(-1);
    }
    dup2(fd1, STDOUT_FILENO);

    while(1) {
        read_size = read(fd,buf,MAX_BUF);
        if(read_size == 0){
            break;
        }
        write_size = write(fd1, buf, read_size);
        if(write_size == -1){
            perror("Write Error");
            close(fd);
            close(fd1);
            exit(-1);
        }
    }
    close(fd);
    close(fd1);
    return 0;
}

0개의 댓글