Linux 파일 구조

mohadang·2023년 3월 11일
0

Linux System Programming

목록 보기
3/9
post-thumbnail

파일 구조

파일 생성시

프로세스마다 개별적인 fd array와 file table을 가진다.
fd array에는 정수형 값이 있는데 파일 생성시 순차적으로 번호가 할당 된다.
fd array는 정수형 번호는 파일 디스크립터라고 하며 file table의 특정 파일 구조체(파일 노드)를 핸들링 할 수 있도록 가리킨다.
fd array의 0, 1, 2는 고정이며 순서대로 표준 입력/출력/에러를 나타낸다. 그리고 이건 다른 프로세스도 마찬가지다.
0, 1, 2 파일 디스크립터는 프로세스 실행시 기본적으로 할당된다.

파일 Read/Write 발생시

dup/dup2

dup에 파일 디스크립터를 넣어주면 복사된 파일 디스크립터를 반환 해준다.
여기서는 dup(3)을 호출하여 4번을 반환 받았고 fd array에 3과 4번 모두 같은 파일 노드를 가리킨다.

0, 1, 2 기본 파일 디스크립터는 제거도 가능한데 이걸로 재미있는 동작도 가능하다.
stdout에 대한 리다이렉션 예제

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
  int fd, fid1;
  fd = open("tmp.aaaa", O_CREAT | O_WRONLY | O_TRUNC, 0644);
  if (fd == -1) {
    perror("Create file error");
    exit(1);
  }
  close(1); // stdout(표준 출력) 닫음, fd array에 1번이 비어 있음
  fd1 = dup(fd); // 복사, 순차적으로 비어 있는곳 검색하여 1번 할당
  printf("DUP FD=%d\n", fd1);
  printf("Hello World!\n");
  close(fd);
  return 0;
}
$ redirect.out  <-- Hello World! 출력 안된다.
$ cat tmp.aaa  <-- 대신 파일 안에 들어있다.
DUP FD=1
Hello World!
  • 파일 끊기전
  • close(1)하고 dup(fd) 호출

inode

파일 구성

파일은 크게 3가지로 구성된다

  • File name
  • inode
  • Data block

파일을 open 하였을때는 내부적인 구조는 다음과 같다.

  1. fd array에 파일 기술자 추가
  2. 파일 기술자는 file table에서 특정 파일 구조체를 지칭한다.
  3. 파일 구조체에는 inode에 접근할 수 있는 속성이 있다.
  4. inode에는 파일과 관련된 정보가 있다.
  5. inode를 통해서 disk에 데이터를 쓰거나 읽기가 가능하다.

stat

stat api를 이용하여 inode에 저장된 파일 정보를 읽어 올 수 있다. 단 파일이 있는 폴더에 대한 읽기 권한이 있어야 한다.

int stat(const char* pathname, struct stat* buf);
int stat(int fd, struct stat* buf);

디렉터리

디렉터리 역시 파일이다.
디렉터리는 자신이 가지고 있는 다른 파일들의 File name, File name이 가리키는 inode 번호들을 저장하고 있다.

링크

복사는 물리적으로 데이터를 복사하여 각각 개별적으로 데이터 관리가 이루어지고
링크는 물리적인 데이터 복사가 아닌 접근할 수 있는 파일만 추가되고 같은 데이터에 접근하여 관리한다.

하드 링크

디렉터리는 기본적으로 파일 하나에 대한 하드 링크를 가지고 있다.
위 예에서는 Filename.txt|36 이라는 하드 링크가 기존에 있었지만 추가적으로 Filename.txt에 대해 하드 링크를 생성하여 가리킬 수 있다.
생성된 하드 링크 파일은 기존 파일과 같은 inode를 가리키며 이때는 inode에 링크 수도 증가하게 된다.
파일이 제거되면 inode 링크 수도 감소하고 결국 0이 되면 파일이 제거된다.

다른 file system에 있는 inode에 대한 hard link가 불가능하다는 의미는 linux 파일 시스템(ext4)에서 windows 파일 시스템(ntfs)으로 하드 링크가 불가능 하다는 뜻이다. 또한 C 드라이브에서 D 드라이브에 대한 하드 링크 역시 불가능 하다.

하드 링크는 C++의 shared_ptr과 비슷한 개념이다.

심볼릭(소프트) 링크

심볼릭 링크는 새로운 파일이 생성 되는 것이다. 윈도우의 바로 가기 파일이랑 같은 개념이다.
심볼릭 링크 파일(Slink.txt)를 생성하면 새로운 inode(i-node 2)가 생성된다.
심볼릭 링크 파일(Slink.txt)에는 타겟이 되는 파일(File.txt)에 대한 경로 정보(/c/file.txt)가 있으며 이 경로를 사용하여 타겟 파일(File.txt)에 접근 할 수 있다.

심볼링 링크는 하드 링크와 타겟 파일과 같은 inode를 가리키지 않아서 링크 수는 증가하지 않는다.

이렇게 간단한 기능을 하기에 심볼릭 링크는 다른 file systemn의 파일/폴더 연결이 가능하다.

Ex) 하드 링크

  • 링크 갯수가 증가 하는것 확인 가능하다.

Ex) 심볼릭 링크

  • 링크 갯수가 증가하지 않는다.

Ex) 윈도우와 공유 폴더 링크

유용해 보이는 API

fcntl

Low-Level File IO에서 지원하는 기능으로 fd에 명령을 수행하여 파일 상태를 변경할 수 있다.

#include <unistd.h>
#include <fcntl.h>
// fd : 대상 파일
// cmd : 수행할 명령, F_GETFL(상태 flag 읽기), F_SETFL(상태 flag 설정), 파일 오프셋 변경등...
// arg : cmd에 필요한 인자들
int fcntl(int fd, int cmd, /*arg*/);

tmpnam, tempnam, tmpfile

  • tmpnam, tempnam : 중복 되지 않도록 임파일명 생성
  • tmpfile : 임시 파일 포인터 생성. 파일명을 알 필요 없이 w+ 모드로 열린 파일 생성
FILE* tmpfile();

access

현재 process가 가진 접근 권한 확인

#include <unistd.h>
int access(const char* pathname, int mode);

mode(확인 할 권한) : R_OK, W_OK, X_OK, F_OK(파일 존재 확인)

int per;
if (access("li.bak", F_OK) == -1 && errno == ENOENT)
  printf("file not exist.\n");
per = access("li.txt", R_OK);
if (per == 0)
  printf("lt.txt : read permission is permitted. \n");
else
  printf("lt.txt : read permission is not permitted. \n");
profile
mohadang

0개의 댓글