[UNIX] Inode, 디렉터리

Taegang Yun·2023년 9월 18일
1

Unix 프로그래밍

목록 보기
3/19

리눅스와 디렉터리

  • 리눅스의 파일 구분
    • 리눅스에서는 파일을 일반 파일과 특수 파일, 디렉터리로 구분
    • 디렉터리는 해당 디렉터리에 속한 파일을 관리하는 특별한 파일
  • 리눅스의 파일 구성
    • 파일명 : 사용자가 파일에 접근할 때 사용
    • Inode : 파일의 소유자나 크기 등의 정보와 실제 데이터를 저장하고 있는 데이터 블록의 위치를 나타내는 주소들이 저장
    • 데이터 블록 : 실제로 데이터가 저장되는 하드디스크의 공간
  • Indirect block : 훨씬 많은 양의 데이터를 담을 수 있는 데이터 블록.

Inode 구조

리눅스의 함수

파일의 종류

크게 일반 파일, 특수 파일, 디렉터리로 구분된다.

/etc

: "etc"는 "et cetera"의 약자로, 주로 시스템 구성 파일을 포함하는 디렉토리입니다. 이 디렉토리에는 시스템 설정, 네트워크 구성, 서비스 설정 등과 관련된 설정 파일들이 저장됩니다.

/mnt

: "mnt"는 "mount"의 약자로, 외부 파일 시스템을 임시로 마운트(mount)하기 위한 디렉토리입니다. 다른 디스크 또는 네트워크 리소스를 마운트할 때 사용됩니다.

/dev

: "dev"는 "devices"의 약자로, 시스템에 연결된 하드웨어 장치를 나타내는 파일들이 저장되는 디렉토리입니다. 리눅스에서는 하드웨어 장치를 파일처럼 다루는데, 이 디렉토리에는 이러한 가상 파일들이 있습니다.

/boot

: "boot"는 부팅과 관련된 파일들이 있는 디렉토리입니다. 주로 커널 이미지와 부트 로더 관련 파일이 여기에 저장됩니다.

/var

: "var"는 "variable"의 약자로, 시스템 동작 중에 자주 변경되는 데이터가 저장되는 디렉토리입니다. 이곳에는 로그 파일, 데이터베이스 파일, 임시 파일 등이 저장됩니다.

/tmp

: "tmp"는 "temporary"의 약자로, 일시적인 파일이나 디렉토리를 저장하는 곳입니다. 이 디렉토리는 시스템 재부팅 시에도 데이터가 유지되지 않습니다.

/home

: "home"은 사용자 홈 디렉토리가 있는 곳입니다. 각 사용자는 이 디렉토리 아래에 자신만의 디렉토리를 가지며, 개인 파일과 설정 파일을 저장합니다.

일반 파일

  • 텍스트 파일, 실행 파일, 라이브러리, 이미지 등 리눅스에서 사용하는 대부분의 파일이 일반 파일에 해당된다.

  • 데이터 블록에 텍스트나 바이너리 형태의 데이터를 저장하고 있다.

  • vi 같은 편집기를 사용해 만들기도 하고 다른 응용 프로그램에서 생성할 수도 있다.

특수 파일

  • 데이터 블록을 사용하지 않으며, 블록 장치 파일과 문자 장치 파일이 있음.
  • 블록 장치 파일은 블록 단위로 데이터를 읽고 씀
  • 문자 장치 파일은 하드 디스크인 경우 섹터 단위로 읽고 씀

숙제 파일들은 tmp에 복사해서 하는 게 좋음. 누구나 접근 가능.

디렉터리

  • 리눅스에서는 디렉터리도 파일로 취급
  • 디렉터리와 연관된 데이터 블록은 해당 디렉터리에 속한 파일의 목록과 inode를 저장
  • 디렉터리를 생성하려면 mkdir, 삭제하려면 rmdir 또는 rm -r, 복사하려면 cp -r 명령을 사용

파일의 종류 구분

  • ls -l 명령을 사용하면 파일의 종류를 알 수 있다.
$ ls -l /usr/bin/cp
-rwxr-xr-x 1 root root 153976 9월 5 2019 /usr/bin/cp
  • 명령의 결과 중 파일의 권한을 표시하는 부분에서 맨 앞의 하이픈(-)이 파일의 종류를 나타냄.

  • ls -ai , ls -lai 과 같이 i옵션 사용시 inode 번호를 볼 수 있다.

파일의 구성 요소

파일명

  • 사용자가 파일에 접근할 때 사용하며 파일명과 관련된 inode가 반드시 있어야 함

  • 유닉스에서는 예전에는 시스템 파일명으로 최대 14자까지 사용할 수 있었지만, 현재는 255 바이트까지 사용할 수 있음

  • 리눅스에서는 255바이트보다 긴 파일명도 사용할 수 있음

  • 파일명이나 디렉터리명은 /와 null 문자를 제외하고 아무 문자나 사용할 수 있음

  • 그러나 출력이 가능한 문자를 사용하고 혼동을 줄 수 있는 특수문자는 사용을 자제하는 것이 관례

  • 파일명 지정 주의사항

    • 파일명과 디렉터리명에 사용하는 알파벳은 대소문자를 구분
    • 파일명과 디렉터리명이 '.' 으로 시작하면 숨김 파일로 간주

✨inode

  • 파일에 대한 정보를 저장하고 있는 객체로, 실제로 디스크에 저장되어 있음
  • 리눅스 커널의 입장에서는 파일의 정보를 관리하는 자료구조로 사용
  • inode는 외부적으로 번호로 표현하며, 내부적으로는 두 부분으로 나누어 정보를 저장

  • inode의 첫 번째 부분에는 파일에 관한 정보가 저장
    • (파일 종류, 파일 접근 권한, 파일 크기, 소유자, 소유 그룹, 파일 변경 시각, 하드 링크 수, 데이터 블록 수 등)
  • ls -l 명령은 inode의 정보를 읽어서 출력
  • 두 번째 부분에는 파일의 실제 데이터가 저장되어 있는 데이터 블록의 위치를 나타내는 주소들이 저장
  • 파일의 inode 번호는 ls -i 명령으로 알 수 있음

데이터 블록

  • 실제로 데이터가 저장되는 하드 디스크의 공간
  • 일반 파일이나 디렉터리, 심벌릭 링크는 데이터 블록에 관련 내용을 직접 저장
  • 장치 파일은 데이터 블록을 사용하지 않고 장치에 관한 정보를 inode에 저장

디렉터리 생성과 삭제

디렉터리 생성 : mkdir(2)

#include <sys/stat.h>
#include <sys/types.h>

int mkdir(const char *pathname, mode_t mode);

  • pathname : 디렉터리가 포함된 경로
  • mode : 접근 권한
  • mkdir()의 특징
    • mkdir() 함수는 생성하려는 디렉터리명을 포함한 경로를 받고, 생성하는 디렉터리의 기본 접근 권한을 지정
    • mkdir() 함수는 수행에 성공하면 0을, 실패하면 -1을 리턴
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
	if (mkdir("han", 0755) == -1){
    	perror("han");
        exit(1);
    }
}

디렉터리 삭제 : rmdir()

int rmdir(const char *pathname);

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
	if(rmdir("han") == -1){
    	perror("han");
        exit(1);
    }
}

디렉터리 위치 검색 : getcwd()

char getcwd(char buf, size_t size);

  • buf : 현재 디렉터리의 절대 경로를 저장할 버퍼 주소

  • size : 버퍼의 크기

  • getcwd() 의 특징

    • getcwd() 함수는 경로를 저장할 버퍼의 주소와 버퍼의 크기를 인자로 받음
    • 인자를 지정하는 방법
      1. buf에 경로를 저장할 만큼 충분한 메모리를 할당하고 그 크기를 size에 지정
      2. buf에 NULL을 지정하고 할당이 필요한 메모리 크기를 size에 지정
      3. buf에 NULL을 지정하고 size는 0으로 지정
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
	char *cwd;
    char wd1[BUFSIZ];
    char wd2[10];
    
    getcwd(wd1, BUFSIZ);
    printf"wd1 = %s\n, wd1);
    
    cwd = gwtcwd(NULL, BUFSIZ);
    printf("cwd1 = %s\n, cwd);
    free(cwd);
    
    cwd = getcwd(NULL, 0);
    printf("cwd2 = %s\n, cwd);
    free(cwd);
    
    if(getcwd(wd2, 10) == NULL){
    	perror("getcwd");
        exit(1);
    }
}

/*
$ ch2_3.out

wd1 = /home/jw/src/ch2
cwd1 = /home/jw/src/ch2
cwd2 = /home/jw/src/ch2
getcwd: Numerical result out of range
*/

디렉터리 위치 검색2 : get_current_dir_name()

char *get_current_dir_name();

  • 현재 디렉터리의 절대 경로를 리턴
  • 시스템이 메모리를 자동으로 할당해 경로를 저장하고 리턴
#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
	char *cwd;
    
    cwd = get_current_dir_name();
    printf("cwd = %s\n", cwd);
    free(cwd);
}

/*
$ ch2_4.out

cwd = /home/jw/src/ch2
*/

디렉터리 명 변경 : rename()

int rename(const char oldpath, const char newpath);

  • oldpath : 변경할 파일 / 디렉터리명

  • newpath : 새 파일 / 디렉터리 명

  • rename() 의 특징

    • 만약 두 번째 인자로 지정한 이름이 이미 있으면 해당 디렉터리를 삭제
    • 실행 도중 요류가 발생하면 원본과 새로운 디렉터리명이 모두 남음
    • rename() 함수는 수행에 성공하면 0, 실패하면 -1 리턴
    • rename() 함수는 파일명을 변경하는데도 사용할 수 있음
int main(){
	if(rename("han", "bit") == -1){
    	perror("rename");
    }
}

디렉터리 이동 1 : chdir()

int chdir(const char *path);

  • path : 이동하려는 디렉터리 경로
  • chdir()의 특징
    • 수행 성공 시 0, 실패 시 -1을 리턴

디렉터리 이동은 프로그램 내부에서만 진행 -> pwd 명령으로 확인하면 현재 디렉터리는 바뀌지 않았음.

디렉터리 이동 2 : fchdir()

int fchdir(int fd);

  • fd : 이동하려는 디렉터리의 파일 디스크립터
  • chdir()의 특징
    • 파일 디스크립터를 인자로 받음
    • 파일 디스크립터 : open() 함수로 디렉터리를 열고 돌려받는 것
    • fchdir() 함수를 사용하려면 open() 함수로 해당 디렉터리를 먼저 열어야함
    • 성공하면 0, 실패하면 -1을 리턴
profile
언젠간 전문가가 되겠지

2개의 댓글

comment-user-thumbnail
2023년 9월 18일

대단해요!!! ㅎㅎ

1개의 답글