카테고리 없음

시스템 프로그래밍 - 파일

김 도경 2024. 10. 24. 09:47

[2024.10.22] 필수 온라인 강의 Part4 시스템 프로그래밍 CH02 파일 다루기

 

- 파일 다루기가 가장 중요함! 리눅스의 장치, 일반파일, ipc도 모두 파일처럼 간주하고 접근을 함.

파일 디스크립터와 파일 포인터
  • 파일 디스크립터(File Descripter)
     - 프로세스는 운영체제로부터 파일을 할당-> 구분 및 식별방법
     - 파일을 식별하기 위해 운영체제로부터 할당받은 정보
                    참고) 입출력장치, 파이프, 소켓도 파일 디스크립터로 식별..
     - 일반적으로 0 이상의 정수 형태
     - 프로세스가 파일을 열거나 생성할 때 운영체제는 해당 파일에 대한 파일 디스크립터 할당
     - 저수준에서 파일을 식별하는 정보

    - 고정된 파일 디스크립터 값 (표준 입출력)
            - 0번: 표준 입력
            - 1번: 표준 출력
            - 2번: 표준 에러
            - 3번부터 할당이 가능 : 0~2번은 정해져있음

  • 파일 디스크립터 반환받기: 파일 열기
            - Parameter
                 - pathname: 파일 경로, flag: 접근 플래그 (이 파일을 어떻게 열지에 대한 결정하는 값), mode: 파일 생성시 모드
                      - flag 
                           - O_RDONLY : 읽기 전용으로 열기
                           -  O_WRONLY: 쓰기 전용으로 열기
                           -  O_RDWR : 읽기 쓰기 전용으로 열기
                           -  O_CREAT : 파일이 없다면 생성하기 (mode_t mode 필수)
                           -  O_TRUNC: 기존 파일 내용 삭제
                           -  O_APPEND : 파일의 끝 지점부터 쓰기 시작 (추가하기)
                      - mode : 권한값이 들어감
                           - S_IRWXU : 소유자에 대한 읽기, 쓰기, 실행권한 모두 설정
                           - S_IRUSR : 소유자에 대한 읽기 권한
                           - S_IWUSR : 소유자에 대한 쓰기 권한
                           - S_IXUSR : 소유자에 대한 실행 권한
                           - S_IRWXG : 그룹에 대한 읽기, 쓰기, 실행권한 모두 설정
                           - S_IRGRP : 그룹에 대한 읽기 권한
                           - S_IWGRP : 그룹에 대한 쓰기 권한
                           - S_IXGRP : 그룹에 대한 실행 권한
                           - S_IRWXO : Other에 대한 읽기, 쓰기, 실행권한 모두 설정
                           - S_IROTH : Other에 대한 읽기 권한
                           - S_IWOTH : Other에 대한 쓰기 권한
                           - S_IXOTH : Other에 대한 실행 권한

                         - 리눅스에서 권한 : 소유주, 그룹, other  : 숫자료 표현 가능
                           - Owner, Group, Other 읽기 4, 쓰기 2, 실행 1
                                 0755
                                 = Owner 권한은 4 + 2 +1 (읽고 쓰고 실행) 7
                                 = Group 권한은 4 + 1 (읽고 실행) 5
                                 = Other 권한은 4 +1 (읽고 실행) 5

    Return
         - 성공시 파일 디스크립터
         - 실패시 -1

  • 파일 디스크립터 반환받기: 파일 닫기
    Parameter
      - fd: 닫고자 하는 파일 디스크립터

    Return
      - 성공시 0
      - 실패시 -1

  • 코드
    - import = include라고 생각하면 좋음 : 라이브러리 소환

  • 파일 포인터
       - (C 언어기준) FILE * 타입
      - 파일을 스트림처럼 읽고 쓰기 위한 자료형 -> 편리한 함수 기능 많음
      - 파일 디스크립터가 저수준에서 파일을 식별하는 정보(운영체제와 가까이 있는 식별하는 정보)라면
         파일 포인터는 고수준 파일 식별 정보

    - 파일 포인터
    - 파일 포인터로 파일 열기 - 파일 포인터로 파일 닫기
       - Parameter
            - pathname: 파일 경로
           - mode: 파일 열기 모드

       - Return
           - 성공시 파일 포인터
           - 실패시 NULL
       - Parameter
            - stream: 파일 포인터

       - Return
           - 성공시 0
           - 실패시 EOF

  • 파일 디스크립터에서 파일 포인터 반환받기
    - Parameter
            - fd: 파일 디스크립터
            -  mode: 권한

       - Return
           - 성공시 파일 포인터
          - 실패시 NULL
파일 입력
  • 파일 읽기 : read : 여러개의 read가 있음
파일 읽기
fscanf
파일에서 문자/문자열 읽기
fgetc
Parameter
- stream: 파일 포인터
- format: 입력 포맷

Return
- 성공시 입력받은 item 개수
- 실패시 EOF
Parameter
- stream: 파일 포인터

Return
- 성공시 읽은 문자
- 실패시 EOF
파일에서 문자/문자열 읽기
fgets
파일 읽기
fread
- 스트림 형태로 파일을 읽어드릴 수 잇음
Parameter
- s: 문자열 버퍼
- size: 버퍼 크기
- stream: 파일 포인터

Return
- 성공시 문자열을 가리키는 포인터
- 실패시 NULL
Parameter
- ptr: 저장 결과를 담을 주소 (저장 결과 포인터)
- size: 입력 item 크기
- nmemb: 입력할 item 개수
- stream: 파일 포인터

Return
- 입력된 아이템 개수

 

파일 출력
  • 파일 쓰기 write
  • 파일쓰기
파일 쓰기
fprintf
파일 쓰기 – 문자/문자열 읽기
fputc
Parameter
- stream: 파일 포인터
- format: 출력 형식

Return
- 성공시 쓰여진 바이트 값
- 실패시 음수 정수값
Parameter
- c: 출력할 문자
- stream: 파일 포인터

Return
- 성공시 쓰인 문자
- 실패시 EOF
파일 쓰기 – 문자/문자열 읽기
fputs
파일 쓰기
fwrite
Parameter
- s: 출력할 문자열
- stream: 파일 포인터

Return
- 성공시 0이상의 정수
- 실패시 EOF
Parameter
- ptr: 출력할 바이트 포인터
- size: 출력 item 크기
- nmemb: 출력 item 개수
- stream: 파일 포인터

Return
- 출력된 item 개수

 

  • 임의의 위치에서의 파일 입출력
임의의 위치에서의 파일 입출력- 파일 위치 확인하기
ftell
임의의 위치에서의 파일 입출력- 파일 위치 설정하기
fseek
Parameter
- stream: 파일 포인터

Return
- 성공시 파일 위치
- 실패시 -1
Parameter
- stream: 파일 포인터
- offset: whence값 기준 떨어져있는 위치
- whence: 기준점
(SEEK_SET: 파일의 시작 기준, SEEK_END: 파일의 끝 기준, SEEK_CUR: 현재 파일 위치 기준)

Return
- 성공시 파일의 위치(offset) - 실패시 -1

 

 

 

디렉터리 다루기
디렉터리 생성하기
mkdir
비어있는 디렉터리 삭제하기
rmdir
Parameter
- pathname: 생성하려는 디렉터리의 경로
- mode: 생성하려는 디렉터리의 초기 접근 권한
( Owner, Group, Other
읽기 4, 쓰기 2, 실행 1
0644
= Owner 권한은 4 + 2 (읽고 쓰기)
= Group 권한은 4 (읽기)
= Other 권한은 4 (읽기))

Return
- 성공시 0
- 실패시 -1
Parameter
- pathname: 삭제하려는 디렉터리의 경로명

Return
- 성공시 0
- 실패시 -1
디렉터리 열기
*opendir
열린 디렉터리 닫기
closedir
Parameter
- name: 개방하려는 디렉터리의 경로명

Return
- 성공시 DIR 형 포인터 반환
- 실패시 NULL 반환
Parameter
- dirp: 닫으려는 디렉터리에 대한 포인터

Return
- 성공시 0
- 실패시 -1
디렉터리 읽기
dirent *readdir
 
DIR *는 디렉터리를 다루기 위한 핸들러,
struct dirent: 그를 통해 접근 가능한 디렉터리 엔트리

디렉터리 엔트리 복습 & struct dirent
 
Parameter
- dirp: opendir로 개방한 디렉터리에 대한 포인터

Return
- 성공시 struct dirent 포인터 반환
- 실패시 혹은 더 이상 읽을 디렉터리 항이 없을 경우 NULL 반환

 

현재 작업 디렉터리 경로 얻어오기
*getcwd
현재 프로세스의 작업 디렉터리 변경
chdir
Parameter
- buf: 현재 작업 디렉터리의 경로를 저장할 버퍼
- size: 버퍼의 최대 크기

Return
- 성공시 buf의 포인터
- 실패시 NULL
Parameter
- path: 변경하려는 새로운 디렉터리 경로

Return
- 성공시 0
- 실패시 -1

 

하드 링크와 심볼릭(소프트) 링크

 

  • 아이노드 복습

      - 아이노드(i-node)라는 색인 블록을 활용한 파일 시스템
      - 아이노드는 사실상 파일의 모든 것(파일크기, 생성시간, 접근시간/수정시간, 소유자 등등)을 담고 있다
      - 파일마다 고유한 아이노드 번호가 있다. 
      - 아이노드를 사용량이 100%로 찼을 경우 : 저장장치 용량이 남아 있어도 파일 생성 불가

  • 하드 링크 파일
      - 하드 링크 생성시 같은 아이노드를 공유하는 하드 링크 파일이 생성됨
    - 같은 아이노드 공유!!! = 이름만 다르지 같은 파일이다.
    - 하드 링크 파일은 원본 파일과 같은 데이터 공유
    - 원본 파일이 삭제/이동해도 하드 링크 파일은 남아 있음
    - 사용 하는 이유 : 여러 이름으로 파일을 참조하고 싶을 때
    - 생성 : $ ln 원본파일이름 하드링크파일이름

  • 심볼릭 링크 파일 (= 소프트링크, 윈도우의 바로가기!)
      - 심볼릭 링크 생성시 원본 파일을 가리키는 새로운 아이노드를 만든다
    - 아이노드가 다름! 대신 가르키는 데이터는 원본파일이 어디에 있는지에 대한 내용임!- 원본 파일이 삭제/이동하면 심볼릭 링크 파일은 사용 불가
    - 사용하는 이유 : 하드 링크 파일에 비해 조작이 간편 , 복잡한 경로에 있는 파일을 참조하고자 할 때
    - 생성 : ln –s 원본파일이름 심볼릭링크파일이름
    - 원본 파일과 같은 데이터를 공유하지 않음 (원본 파일의 위치만 알 뿐)

 

  • 생성하기
하드링크 생성하기
link

$ ln 원본파일이름 하드링크파일이름
심볼릭링크 생성하기
symlink

ln –s 원본파일이름 심볼릭링크파일이름
Parameter
- oldpath: 생성하려는 디렉터리의 경로
- newpath: 생성할 하드 링크 파일 경로

Return
- 성공시 0
- 실패시 -1
Parameter
- target: 원본 파일 경로
- linkpath: 생성하려는 심볼릭링크 파일 경로

Return
- 성공시 0
- 실패시 -1

 

파일 속성 다루기

 

파일 : 보조기억장치의 의미있는 정보의 집합
   (구성 요소 : 이름, 실행하기 위한 정보, 부가 정보( 메타데이터 / 속성)

 

- 여기서 속성!!!

 : 유형 (확장자), 크기, 생성 날짜, 마지막 접근 날짜, 마지막 수정 날짜, 생성자, 소유자, 위치

  • stat
      - Parameter
           - filename: 파일 경로
           - buf: stat 정보를 저장할 버퍼

      - Return
           - 성공시 0
           - 실패시 -1

    - stat로 속성 자세히 보기 : https://pubs.opengroup.org/onlinepubs/007908775/xsh/sysstat.h.html

  • fstat
      - Parameter
           - filedes: 파일 디스크립터
           - buf: stat 정보를 저장할 정보

      - Return
           - 성공시 0
           - 실패시 -1
파일 메모리 매핑

- memory mapping, mmap이 중요함

  • 파일 메모리 매핑이란
     - 프로세스 메모리 영역에 파일의 내용 일부에 대응시키는 것
        - 프로세스별로 서로 다른 메모리 공간을 가지고 있음
     - 디스크에 있는 파일에 읽고 쓰는 것(파일 입출력)이 아니라 프로세스 메모리 영역에 읽고 쓰기
                       * lseek의 번거로움, 불필요한 시스템 콜 호출 횟수 감소
       - 두 개 이상의 프로세스가 같은 영역을 매핑할 경우 다른 프로세스와의 통신 가능 (***) 
       - 매핑은 페이지 단위(페이지의 배수 크기)로 이루어짐
            - 메모리 매핑은 파일에 있는 특정 내용을 맵핑하는 걸로 생각! 그럼 단위는 무조건 페이지!(페이징!!)

    * 파이썬 공식 문서에서 지원하는 mmap 기능 : https://docs.python.org/ko/3/library/mmap.html
    * golang 공식 문서에서 지원하는 mmap 기능 : https://pkg.go.dev/golang.org/x/exp/mmap
    * Rust 공식 문서에서 지원하는 mmap 기능 : https://docs.rs/memmap/latest/memmap/struct.Mmap.html
  • mmap : 메모리 맵핑을 위한 시스템 콜
    - 각각의 인자가 왜 필요한지 납득을 반드시 해야한다!

    Parameter
    - addr: 매핑할 메모리 주소에 대한 힌트 (NULL일 경우 임의의 위치에 매핑 : 대부분 NULL로 줌- 가용공간에 줘라는 의미)
          - 어디에 매핑하고자 하는지 메모리 주소
    - length: 매핑할 바이트 단위 길이 (offset에서 부터 length만큼 매팽, 페이지 크기의 배수!!)
          - 얼마나 떨어진곳부터 어디까지! 매핑할것인가!
    - prot: 메모리 보호 모드
          - PROT_READ: 읽기 모드로 접근
          - PROT_WRITE: 쓰기 모드로 접근
          - PROT_EXEC: 실행 모드로 접근
    - flags: 매핑 형태와 동작 방식
          - MAP_SHARED: 변경된 내용이 공유됨 (원본에 작업 - 원본에 매핑을 함, 원본에 대해서 작업함. 원본에 작업을 함)
                                       - 다른 프로세스에서도 원본이 바뀐 것을 확인이 가능함. 같이 매핑해도 서로관리가능
          - MAP_PRIVATE: 변경된 내용이 공유되지 않음 (복사본에 작업)
                                       - 원본에까지 영향X : 다른프로세스에서는 바뀐 걸 알 수X
          - MAP_FIXED: addr로 지정한 주소를 강제하기 (매핑할 주소 지정)
                     - 다른 매핑이 있다면 해제 후 매핑
          - MAP_ANONYMOUS: 어나니머스 매핑 : 실제로 존재하지 않는 가상의 파일에 매핑
    - fd: 파일 디스크립터 : 어떤 파일을 매핑할지에 대한 정보
    - offset: 매핑을 시작할 위치
          - 얼마나 떨어진 곳에서 시작하는 지에 따라

    Return
    - 성공시 매핑된 주소,실패시 MAP_FAILED

    * Anonymous Mapping
       - 특정 파일을 지정하지 않고 익명의(Anonymous) 파일을 매핑
         - mmap 인자
         - flags = MAP_SHARED | MAP_ANONYMOUS
         - fd = -1
         - offset 무시 (일반적으로 0)

  • munmap
    - 매모리를 mapping했다면 unmapping도 꼭 해야한다!!!
    Parameter
      - addr: 해제할 메모리 주소
      - length: 매핑된 길이

    Return
      - 성공시 0 - 실패시 -1