[리눅스 시스템 프로그래밍] 4.7 물리적 파일에 접근하기 위한 경로, 하드 링크(link)와 심볼릭 링크(symlink)

리눅스(유닉스) 시스템에서는 물리적 파일에 접근하기 위해 경로(디렉토리 및 파일명)명을 사용합니다. 그런데 리눅스에서는 하나의 물리적 파일에 접근하기 위한 경로를 여러 개를 설정할 수 있습니다. 리눅스(유닉스) 시스템에서 하나의 물리적 파일에 접근하기 위한 경로는 하드 링크와 심볼릭 링크로 구분할 수 있습니다.

하드 링크는 물리적 파일과 대응하는 inode 항목에 연결 계수(link count)를 두어 관리하는 방법입니다. 이러한 하드 링크는 같은 파일 시스템 내에 존재하는 파일에 관해서만 생성할 수 있습니다. 특히 디렉토리는 슈퍼유저만 하드링크를 허용하여 잘못 연결하였을 때 무한루프의 피해를 최소화하였습니다. 시스템에서는 특정 경로를 삭제 요청하면 inode의 연결 계수를 감소한 후에 그 값이 0이 아니면 다른 경로명으로도 접근할 수 있어서 삭제하지 않습니다. 만약 연결 계수를 감소한 후에 그 값이 0이면 프로세스 중에 해당 파일에 접근하여 작업하는지 확인하여 없을 때에 삭제합니다. 만약 프로세스 중에 해당 파일에 접근하는 작업이 있다면 해당 작업을 완료한 후에 물리적인 파일을 삭제합니다. 이처럼 특정 경로를 삭제하는 작업을 링크를 해제한다는 의미로 unlink라고 부릅니다.

심볼릭 링크는 파일의 데이터로 연결할 파일의 경로명을 기억하게 하여 심볼릭 링크 파일을 접근하였을 때데이터로 기억하는 연결할 파일을 사용하게 하는 것을 말합니다. 이러한 이유로 심볼릭 링크는 다른 파일 시스템 혹은 존재하지 않는 파일에 관한 심볼릭 링크로 만들 수 있습니다.

[그림 4.9] 하드링크와 심볼릭 링크
[그림 4.9] 하드링크와 심볼릭 링크

[그림 4.9]는 명령어 ln을 이용하여 하드 링크와 심볼릭 링크를 만들어 확인한 화면입니다. 먼저 dummy 파일을 생성한 후에 vi 편집기로 abc라는 내용을 입력하였습니다. 그리고 cat 명령으로 dummy 파일 내용을 확인했어요. 그리고 ln 명령으로 dummy 경로에 관한 하드 링크 dummy2를 만들었습니다. 물론 dummy2는 dummy 경로명으로 접근하는 물리적 파일에 접근할 수 있는 또 다른 경로명이므로 파일 내용을 확인하면 똑같다는 것을 알 수 있습니다. 그리고 ln 명령어에 -s 옵션을 사용하여 sdum이라는 심볼릭 링크를 만들었습니다. 이 때도 cat 명령으로 sdum을 확인하면 dummy 파일의 내용을 확인할 수 있습니다. 그런데 ls -al로 확인을 해 보면 dummy와 dummy2는 파일 크기를 비롯하여 파일 속성이 같지만 심볼릭 링크인 sdum은 파일 크기가 원본 경로명인 dummy의 개수인 것을 알 수 있고 파일 속성에도 차이가 있음을 알 수 있습니다.

[그림 4.10] 하드링크와 심볼릭링크2
[그림 4.10] 하드링크와 심볼릭링크2

그리고 [그림 4.10]은 존재하지 않는 경로명에 하드 링크와 심볼릭 링크를 만드는 화면입니다. 하드 링크는 보시는 것처럼 존재하지 않는 경로에 설정할 수 없지만 심볼릭 링크는 가능한 것을 볼 수 있습니다.

다음은 하드 링크와 심볼릭 링크를 만드는 시스템 호출입니다.

#include <unistd.h >

int link(char *path, char *newpath);

int symlink(char *path, char *sympath);

반환 값: 실패 시 -1, 성공 시 0

다음은 link 시스템 호출을 이용하여 하드 링크를 생성하는 예제 코드입니다.

/***********************************************************************
* ex_link.c                                                            *
* example source - make hard link                                      *
***********************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    if(argc !=3)
    {
        fprintf(stderr,"usage:%s <path> <newpath>\n",argv[0]);
        return 0;
    }
    
    if(access(argv[1], F_OK)!=0)
    {
        fprintf(stderr,"%s is not existed\n",argv[1]);
        return 0;
    }
    
    if(link(argv[1],argv[2])<0)
    {
        fprintf(stderr,"link error\n");
        return 0;
    }  

    int fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC);
    write(fd,"Hello\n",6);
    close(fd);

    return 0;    
}
[그림 4.11] link 시스템 호출 예제 코드 실행 및 내용 확인
[그림 4.11] link 시스템 호출 예제 코드 실행 및 내용 확인

[그림 4.11]은 link 시스템 호출 예제 코드를 실행한 후에 파일 내용을 확인하고 ls -al 명령으로 파일 속성을 확인한 예제입니다. 앞에서 보았던 하드 링크 명령을 수행한 결과와 같음을 알 수 있습니다.

다음은 symlink 시스템 호출을 이용하여 심볼릭 링크를 생성하는 예제 코드입니다.

/***********************************************************************
* ex_symlink.c                                                                   *
* example source - make symbolic link                                   *
***********************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int main(int argc,char **argv)
{
    if(argc !=3)
    {
        fprintf(stderr,"usage:%s <path> <newpath>\n",argv[0]);
        return 0;
    }    
    
    if(symlink(argv[1],argv[2])<0)
    {
        fprintf(stderr,"symlink error\n");
        return 0;
    }  

    int fd = open(argv[1],O_WRONLY);
    write(fd,"Hello\n",6);
    close(fd);

    return 0;    
}
[그림 4.12] symlink 시스템 호출 사용 예제 실행 및 내용 확인
[그림 4.12] symlink 시스템 호출 사용 예제 실행 및 내용 확인

[그림 4.12]는 symlink 시스템 호출 사용 예제를 실행한 후에 파일 내용을 확인 및 ls -al 명령을 실행하였을 때의 결과입니다. ccb 파일은 cca에 관한 심볼릭 링크라는 것을 알 수 있습니다.