ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파일 - 인터페이스
    운영체제 2024. 5. 20. 15:21

    APIs

     

    시스템 콜

    - open (파일 디스크립터 리턴)

    - I/O(read, write)

    - attribute(stat, chown, chmod 등 속성 관련)

    - create (inode 할당)

    - name resolution (디렉토리 계층 트래버스)

    - 파일 시스템 관리

    - 디렉토리 관리

    ....

     

    OS 내부

    - 블록 할당, 반납

    - inode 할당, 반납

    - namei (name resolution을 하기 위한 내부 인터페이스)

    - 버퍼 관련


     

    // open with create flag
    int fd = open("foo", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
    
    // creat() ,, 잘 안씀
    int fd = creat("foo");

    open()

    인자

    - name

    - flags

    (* O_TRUNC: 파일 내용이 기존에 있었으면 다 자르고 깨끗한 파일에서 새로 만듦)

    - permissions

    (* 유저, 그룹 아더스.. 보통 O744 이런 식으로 줌. 7은 111이니 유저는 읽기 쓰기 실행하기 다 된다는 뜻)

     

    리턴

    파일 디스크립터

    이후 파일 디스크립터를 통해 read, write

     

     

    int read_size = read(fd, buf, req_size);
    int write_size = write(fd, buf, req_size);

    read() / write()

    인자: fd, 데이터 저장할 메모리 포인팅하는 버퍼, 리퀘스트 사이즈

    리턴: 읽기/쓰기 사이즈

     

    리드와 관련된 대표적인 명령: cat

    ** strace를 쓰면 어떤 시스템 콜을 쓰는지 볼 수 있음


    lseek(fd, 200, SEEK_SET);

    lseek()

    파일은 순차적으로 접근됨

    파일은 문자열이고 시작(스타트)과 끝(사이즈)이 있음

    그리고 현재 읽거나 쓰려는 위치: 오프셋

     

    파일은 세가지 어트리뷰트로 설명됨: 스타트, 사이즈, 오프셋

     

    그런데 순차적으로 읽기 싫을 수도 있음(점프) -> lseek() 사용

    인자

    1. 파일 디스크립터

    2. 오프셋    -- whence 기준으로 얼마나 더 갈 거냐

    3. whence --  SEEK_SET, SEEK_CUR, SEEK_END

     

    오프셋(offset)

    파일 테이블이라 불리는 자료구조에서 관리 (PCB, inode와 관련)

     

    PCB가 만들어지고 프로세스가 수행되며 PCB에 정보가 업데이트되는데,

    파일을 오픈할 경우 파일 디스크립터라는 자료구조가 파일 테이블을 가리킴

    파일 테이블 내부에서 inode를 가리키게 됨

    PCB => fd => file table => inode

     

    case1 - 어떤 파일을 처음부터 끝까지 쭉 읽는 경우

    파일 오픈 시 오프셋이 0으로 설정

    read 요청: 오프셋에서 사이즈만큼 읽고, 오프셋을 그만큼 올림

    읽을게 없으면 리턴값이 0 -> read의 리턴값이 0이면 파일 끝에 도착한 것

     

    case2 - lseek(fd, 200, SEEK_SET)

    이후 read시

    시작위치에서 200 떨어진 곳에서 읽기 시작

     

    case3 - 동일한 파일에 오픈 두 번

    동일한 파일에 대해 fd1, fd2가 만들어지고

    각 파일 디스크립터마다 각각의 파일테이블을 가리킴

    -> 결국 파일 테이블들이 같은 inode를 가리키는데, 오프셋은 따로 관리됨

     

     

    파일 테이블 쉐어링

    1. fork

    서로 다른 프로세스가 파일 테이블을 공유함

    포크 시 자식은 부모의 모든 내용을 복사하는데 파일 디스크립터도 복사함

    이때, 파일 테이블에서 레퍼런스 카운트가 2개가 됨

    -> 서로 다른 PCB에서 파일 테이블을 공유하게 됨

     

    2. dup

    서로 다른 fd가 같은 파일 테이블을 가리키도록 해줌

    결국 offset을 같이 사용하게 됨

     

     

    오픈 두 번 하는 건 애초에 다른 파일테이블을 가리키는데,

    fork나 dup는 같은 파일 테이블을 사용하게 됨


    fsync()

    지연쓰기

    디스크는 너무 느림

    write 시 일단 메모리에만 써두고 더티하다고 표시, 어느정도 시간이 지나면 씀

     

    버퍼, 페이지 캐시

    디램 중 일부를 캐시로 사용

    ** 계층 구조 상 위에 있는 건 아래 있는 걸 캐시로 사용 가능

    ** 디스크도 캐시로 사용 가능. 서버의 내용을 미리 당겨오는 용도

     

    Synchronous I/O

    동기적인 I/O - 내가 써달라고 요청하면 바로 씀

     

    Asynchronous I/O

    비동기적 I/O - 써달라고 해도 나중에 ..  예) 지연 쓰기

     

    지연쓰기는 성능은 좋으나 영속성을 보장하지 않음

    rc = fsync(fd);

    fsync()

    디램 상 더티한 데이터를 디스크에 써 줌

    혹은, 애초에 오픈 시 싱크 옵션을 주면 그 파일에 대해서는 바로바로 써짐


    int fd = open("foo.txt.tmp", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    write(fd, buffer, size);
    fsync(fd);
    close(fd);
    rename("foo.txt.tmp", "foo.txt");

    rename()

    편집기에서 많이 사용

    파일 수정 시 직접 수정하는게 아니라 tmp 파일을 만들어서 쓰고 작업이 끝나면 이름을 바꿔주는 방식

    원자적으로 작동함


    unlink("foo");

    unlink()

    삭제 api .. 링크를 제거하는 방식으로 작동


    파일 시스템의 내용

    - 유저 데이터

    - 메타 데이터 : 관리를 위해 시스템이 생성함 (inode, superblock)

    stat(file_name, struct stat)
    fstat(fd, struct stat)

    stat() / fstat()

    파일에 대한 정보를 알 수 있음

    stat() - 파일 이름을 인자로 줌

    fstat() - fd를 인자로 줌


    mkdir("foo", 0777); // name, permission

    mkdir()

    디렉토리 만들기

    ** ls -a 시 히든 파일까지 보기 가능

    ** .  이랑 .. 둘 다 파일 이름으로 있음


    rmdir(fime_name)

    디렉토리 삭제

    ** rm -rf -- recursive , force .. 재귀적으로 디렉토리와 하위 디렉토리를 강제로 제거, 중요한 파일을 삭제하지 않도록 주의 필요


    // ls
    int main(int argc, char *argv[]) {
        DIR *dp = opendir(".");
        assert(dp != NULL);
        struct dirent *d;
        
        while( (d = readdir(dp)) != NULL ) {
            printf("%d %s\n", (int)d->d_ino, d->d_name);
        }
        closedir(dp)
        return 0;
    }

    opendir()

    readdir()

    closedir()

    디렉토리는 파일 이름과 inode의 쌍으로 구성

    read_dir로 읽을 수 있음


    여러 디렉토리들

    /boot - 부팅에 관한 내용

    /etc - 시스템 구성

    /home - 일반 사용자용

    /mnt - 마운트 포인트

    /proc - 일종의 추상화된 파일 시스템, 커널 내부를 보여줌

    /sys - 하드웨어 구성

    /dev - 장치 파일

    /sbin - 시스템 바이너리, ifconfig 같은 것들이 저장됨

    /lib - 라이브러리

    /usr - 나중에 추가된 패키지들

    /usr/bin

    /usr/sbin

    /usr/lib


    링크

    파일 이름을 기존 inode에 연결

    명령어: ln

    api: link(old_name, new_name) -> 파일의 하드링크를 만들어줌

     

    서로 다른 파일이 같은 inode를 가리키게 됨

    unlink -> 데이터가 사라지는 건 아니고 링크를 끊음: 링크 카운트 감소

    inode의 링크 카운트가 0이 되면 해당 데이터는 삭제되는 것

     

    하드 링크

    실제 inode 공유

     

    심볼릭 링크

    다른 inode를 가지는데, 어느 파일로 가라고 표시가 됨

     

    하드 링크는 inode 21403764를 가리키고, file과 file2가 가리켜서 링크 카운트가 2인걸 확인 가능

    심볼릭 링크는 다른 inode를 가리킴

     

    16777221은 Mac OS에서 쓰는 파일 시스템 id

     

    하드 링크는 같은 파일 시스템에서만 사용 가능

    다른 파일 시스템의 파일을 링크하고 싶으면 심볼릭 링크(소프트 링크)를 해야 함

    ** 심볼릭 링크 Dangling reference 문제

    원본 파일이 지워지면 실제 데이터가 없는 문제가 있음


    파일 시스템

    mkfs 명령으로 만들어짐

    $ sudo mkfs.ext4 /dev/sda5

    보통 디스크를 조각내고 각각을 파티션이라 하고, 서로 다른 파일 시스템으로 관리됨

    한 파일 시스템이 고장나도(슈퍼블록 이상) 다른 파티션은 괜찮음

    파티션은 fdisk 명령으로 만들기 가능

     

    ext4: 파일 시스템 종류

     

    /dev/sda5

    * IDE 디스크 *
    /dev/hdXX
    
    *SCSI, 혹은 SATA 디스크*
    /dev.sdXX

    특정 디스크와 파티션을 의미함

    sda5 이면 SCSI나 SATA 디스크를 사용하고, 첫번째 디스크이며(a) 5번째 파티션이라는 의미


    마운트

    파일 시스템은 서로 분리됨

    윈도우는 c, d 드라이브..

    리눅스는 묶어줄 수 있음

     

    서로 다른 파일 시스템을 붙여주는 기능

    보통 /mnt가 마운트 포인트가 되고, 마운트되는 파일 시스템을 가리킴

    굳이 이름이 mnt일 필요는 없음

     

     

    '운영체제' 카테고리의 다른 글

    Fast File System  (0) 2024.05.28
    파일 시스템 - 레이아웃  (0) 2024.05.20
    파일과 디렉토리  (0) 2024.05.19
    Hard Disk Drive / Time io, Time rate / Disk Scheduling  (0) 2024.05.19
    I/O Device, Device Driver  (0) 2024.05.06
Designed by Tistory.