전공과목 정리/리눅스시스템 + 시스템프로그래밍

[리눅스시스템🐧] 12장 파일 시스템과 파일 입출력

최연재 2024. 1. 7. 00:51

교재 : 리눅스 시스템 원리와 실제 (창병모, 생능출판)

 

12.1 파일 시스템

1) 파일 시스템 보기

- 명령어 : 파일 시스템에 대한 디스크 사용 정보를 보여준다.

$ df 파일시스템*

 

2) 디스크 사용량 보기

- 사용법 : 파일 혹은 디렉터리의 사용량을 보여준다. 파일을 명시하지 않으면 현재 디렉터리 내의 모든 파일들의 사용 공간을 보여준다.

$ du [-s] 파일명*

- -s 옵션 : sun

 

3) 파일 시스템 구조

(1) 부트 블록(Boot block)

  • 파일 시스템 시작부에 위치하고 보통 첫 번째 섹터를 차지
  • 부트스트랩 코드가 저장되는 블록

(2) 슈퍼 블록(Super block)

  • 전체 파일 시스템에 대한 * 정보를 저장
  • *정보 : 총 블록 수, 사용 가능한 i-노드 수, 사용 가능한 블록 비트 맵, 블록의 크기, 사용 중인 블록 수, 사용 가능한 블록 수 등

(3) i-리스트

  • 각 파일을 나타내는 모든 i-노드들의 리스트
  • 한 블록은 약 40개 정도의 i-노드를 포함

(4) 데이터 블록(Data block) : 파일의 내용(데이터)을 저장하기 위한 블록들

 

12.2 파일 상태 정보와 i-노드

1) 파일 상태

- 파일 상태

  • 파일에 대한 모든 정보
  • 블록 수, 파일 타입, 접근권한, 링크 수, 파일 소유자의 사용자ID, 그룹ID, 파일 크기, 최종 수정 시간
$ ls -l test.txt
4 -rw-rw-r-- 1 yeonjae yeonjae 2088 12월 21일 23:23 test.txt

4(블록 수) -(파일타입)rw-rw-r--(접근권한) 1(링크 수) yeonjae(사용자ID) yeonjae(그룹ID) 2088(파일 크기) 12월 21일 23:23(최종 수정 시간) test.txt(파일 이름)

 

- stat 명령어 : 파일에 대해 자세한 상태 정보를 출력한다.

$ stat [옵션] 파일

 

2) i-노드

- 하나의 파일은 하나의 i-노드를 갖는다.

- 파일에 대한 모든 정보를 가지고 있다.

파일 상태 정보 의미
블록 수 파일을 구성하는 블록의 개수 (K 바이트 단위)
파일 종류 파일 종류
접근권한 파일에 대한 소유자, 그룹, 기타 사용자의 읽기,쓰기, 실행 권한
하드 링크 수  파일에 대한 하드 링크 수
소유자 및 그룹 파일의 소유자 ID 및 소유자가 속한 그룹 ID
파일 크기 파일의 크기
최종 접근 시간 파일을 최후로 접근한 시간
최종 수정 시간 파일을 생성 혹은 최후로 수정한 시간
데이터 블록 주소 실제 데이터가 저장된 데이터 블록의 주소

 

3) i-노드와 블록 포인터

- 블록 포인터

  • 데이터 블록에 대한 포인터 : 파일의 내용을 저장하기 위해 할당된 데이터 블록의 주소
  • 하나의 i-노드 내의 블록 포인터
    • 직접 블록 포인터 : 12개
    • 간접 블록 포인터 : 12개
    • 이중 간접 블록 포인터 : 1개

 

12.3 디렉터리의 구현

- 디렉터리 엔트리

#icnlude <direct.h>

struct direct {
	ino_t d_ino; // i-노드 번호
    char d_name[NAME_MAX+1]; // 파일 이름 
}

- 디렉터리를 위한 별도의 구조는 없음. -> 디렉터리는 일종의 파일

- 파일처럼 하나의 i-노드로 표현

- 디렉터리의 내용 : 디렉터리 엔트리(파일 이름, i-노드)

 

12.4 링크의 구현

1) 링크

- 기존 파일에 대한 또 하나의 새로운 이름

- 사용법

$ ln [-s] 파일1 파일2

: 파일1에 대한 새로운 이름(링크)으로 파일2를 만든다. (-s 옵션 : 심볼릭 링크)

$ ln [-s] 파일1 디렉터리

: 파일1에 대한 링크를 지정된 디렉터리에 같은 이름으로 만들어준다.

 

2) 하드링크

- 기존 파일에 대한 새로운 이름이라고 생각할 수 있다.

- 실제로 기존 파일을 대표하는 i-노드를 가리켜 구현

3) 심볼릭 링크

- 다른 파일을 가리키고 있는 별도의 파일

- 실제 파일의 경로명을 저장하고 있는 일종의 특수 파일 -> 이 경로명이 다른 파일에 대한 간접적인 포인터 역할을 함.

 

12.5 C 파일 입출력

1) 시스템 호출 (system call)

- 시스템 호출은 유닉스 커널에 서비스를 요청하기 위한 프로그래밍 인터페이스

- 응용 프로그램은 시스템 호출을 통해서 유닉스 커널에 서비스를 요청한다.

 

2) 파일

- c 프로그램에서 파일의 필요성

  • 변수에 저장된 정보들은 실행이 끝나면 전부 사라짐
  • 정보를 영속적으로 저장하기 위해서는 파일에 저장해야 한다.

- 유닉스 파일 : 모든 데이터를 연속된 바이트 형태로 저장한다.

 

3) C언어의 파일 종류

- 텍스트 파일 (text file)

  • 사람들이 읽을 수 있는 문자들을 저장하고 있는 파일
  • 텍스트 파일에서 "한 줄의 끝"을 나타내는 표현은 파일이 읽어들여질 때, C 내부의 방식으로 변환된다.

- 이진 파일 (binary file)

  • 모든 데이터는 있는 그대로 바이트의 연속으로 저장
  • 이진 파일을 이용하여 메모리에 저장된 변수 값 형태 그대로 파일에 저장할 수 있다.

 

4) 파일 입출력

- C언어의 파일 입출력 과정

  1. 파일 열기 : fopen() 함수 이용
  2. 파일 입출력 : 다양한 파일 입출력 함수 ㅏ용
  3. 파일 닫기 : fclose() 함수 사용

(1) 파일 열기

- 파일을 사용하기 위해서는 반드시 먼저 파일 열기(fopen) 필요

- 파일 열기를 하면 FILE 구조체에 대한 포인터가 리턴된다.

- FILE 포인터는 열린 파일을 지정한다.

- 함수 fopen() : 파일 열기를 한다. 열린 파일을 나타내는 FILE 포인터를 반환하며 오류가 발생하면 NULL을 반환한다.

FILE *fopen(const char *filename, const char *mode);

- 모드

모드 의미 파일이 없으면 파일이 있으면
"r" 읽기 전용 (read) NULL 반환 정상 동작
"w" 쓰기 전용 (write) 새로 생성 기존 내용 삭제
"a" 추가 쓰기 (append) 새로 생성 기존 내용 뒤에 추가
"r+" 읽기와 쓰기 NULL 반환 정상 동작
"w+" 읽기와 쓰기 새로 생성 기존 내용 삭제
"a+" 추가를 위한 읽기와 쓰기 새로 생성 기존 내용 뒤에 추가

 

(2) 스트림과 파일 구조체

- 스트림(stream) : 파일이 열리면 스트림이라 한다.

- FILE 구조체 

  • stdio.h에 정의되어 있음.
  • 열린 파일의 현재 상태를 나타내는 필드 변수들
  • 특히 파일 입출력에 사용되는 버퍼 관련 변수들
typedf struct {
    int cnt; // 버퍼에 남은 문자 수
    unsigned char *base; // 버퍼 시작
    unsigned char *ptr; // 버퍼의 현재 포인터
    unsigned flag ; // 파일 접근 모드
    int fd; // 열린 파일 디스크립터
} FILE; // FILE 구조체

 

(3) 표준 입출력 스트림 : stdin(표준 입력), stdout (표준 출력) , stderr (표준 오류)

- C 프로그램이 실행되면 자동으로 열리고 프로그램이 종료될 때는 자동으로 닫힘.

표준 입출력 스트림 설명 가리키는 장치
stdin 표준입력에 대한 FILE 포인터 키보드
stdout 표준출력에 대한 FILE 포인터 모니터
stderr 표준오류에 대한 FILE 포인터 모니터

 

(4) 파일 닫기

- 파일을 열어서 사용한 후에는 파일을 닫아야 한다.

- 함수 fcolse() : fp가 가리키는 파일을 닫는다. 성공하면 0, 오류일 때는 -1을 반환한다.

 

12.6 파일 입출력 함수

1) 파일 입출력 함수

표준 입출력 함수 파일 입출력 함수 기능
getchar() fgetc(), getc() 문자 단위로 입력하는 함수
putchar() fputc(), putc() 문자 단위로 출력하는 함수
gets() fgets() 문자열을 입력하는 함수
puts() fputs() 문자열을 출력하는 함수
scanf() fscanf() 자료형에 따라 자료를 입력하는 함수
printf() fprintf() 자료형에 따라 자료를 출력하는 함수

 

2) 문자 단위 입출력

- fgetc(), fputsc() : 파일에 문자 단위 입출력 가능

- int fgetc(FILE *fp)

  • getc 함수는 fp가 지정한 파일에서 한 문자를 읽어서 리턴한다.
  • 파일 끝에 도달했을 경우에는 EOF(-1) 리턴

- int fputc(int c, FILE *fp)

  • putc 함수는 파일에 한 문자씩 출력
  • 리턴값으로 출력되는 문자 리턴
  • 출력 시 오류가 발생하면 EOF(-1) 리턴 

 

12.7 명령어 구현

1) cat.c

#include <stdio.h>
/* 텍스트 파일 내용을 표준출력에 프린트 */

int main(int argc, char *argv[])
{
    FILE *fp;
    int c;
    
    if (argc < 2) fp = stdin;  // 명령줄 인수가 없으면 표준입력 사용
    else fp = fopen(argv[1], "r"); // 읽기 전용으로 파일 열기
    
    c = getc(fp); // 파일로부터 문자 읽기
    while (c != EOF) { // 파일의 끝이 아니면
    	putc(c, stdout); // 읽은 문자를 표준출력에 출력
        c = getc(fp); // 파일로부터 문자 읽기
    }
    
    fclose(fp);
    return 0;
}

 

2) copy.c

#include <stdio.h>
/* 파일 복사 프로그램 */

int main(int argc, char *argv[])
{
    char c;
    FILE *fp1, *fp2;
    
    if (argc!=3) {
    	fprintf(stderr, "사용법: %s 파일1 파일2\n", argv[0]);
        return 1;
    }
    
    fp1 = fopen(argv[1], "r");
    if (fp1 == NULL) {
    	fprintf(stderr, "파일 %s 열기 오류\n", argv[1]);
        return 2;
    }
    
    fp2 = fopen(argv[2], "w");
    while ((c = fgetc(fp1)) != EOF) fputc(c, fp2);
    
    fclose(fp1);
    fclose(fp2);
    return 0;
}

 

12.8 줄단위 입출력

1) 줄 단위 입출력

- 파일로 한 줄씩 읽기 : 파일로부터 한 줄을 읽어서 문자열 포인터 s에 저장하고 s를 리턴한다.

char* fgets(char *s, int n, FILE *fp);

- 파일에 한 줄씩 읽기 : 문자열 s를 fp가 나타내는 파일에 출력한다. 성공하면 출력한 바이트수를, 실패하면 EOF 값을 리턴한다.

int fputs(const char *s, FILE *fp);

 

2) line.c  // cat -n 구현

#include <stdio.h>
#define MAXLINE 80

int main(int argc, char *argv[]) // 텍스트 파일에 줄 번호를 붙여 프린트
{
	FILE *fp;
    int line = 0;
    char buffer[MAXLINE];
    
    if (argc < 2) exit(1);
    
    if ((fp = fopen(argv[1], "r")) == NULL) {
    	fprintf(stderr, "파일 열기 오류\n");
        exit(2);
    }
    
    while (fgets(buffer, MAXLINE, fp) != NULL) // 한 줄 읽기
    {
    	line++;
        printf("%3d %s", line, buffer); // 줄 번호와 함께 프린트
    }
    exit(0);
}