유닉스의 파일을 어떻게 접근하는가 - 2

sp.arc·2022년 11월 2일

Linux

목록 보기
4/6
post-thumbnail

📒 학교 강의를 바탕으로 개인적인 공부를 위해 정리한 글입니다.


멀티 유저 환경에서의 파일

유저와 소유권

✔ 소유권(Ownership)

유닉스는 멀티 유저 시스템.
유닉스 시스템을 사용하는 유저는 여러명.


어떤 유저가 파일을 만들면 그 파일의 소유자가 됨.
어떤 파일에는 소유자가 반드시 존재함.
유닉스 시스템에서의 모든 파일은 반드시 소유자가 있음.
→ 시스템의 유저 중 한 명.

보통은 파일을 만든 사람이 소유자가 됨
→ 반드시 그렇지 않을 수 있음.


/etc/passwd에 유저가 아래와 같이 등록됨.

💡유저 아이디(uid)

소유자의 identity
uid는 숫자 값.

유저가 로그인하면 그 사람에 대응되는 uid가 있음.
유저가 프로세스를 생성하면 그 프로세스에 uid가 대응됨.
→ 이 프로세스를 누가 실행시켰는가(일종의 프로세스 소유자)

어떤 유저가 실행시킨 프로세스가 파일을 만들 때, 프로세스의 uid가 파일의 소유자가 됨.
따라서 이 프로세스를 실행시킨 유저의 uid가 파일의 소유자가 됨.
→ 반드시 이렇게 되는 것은 아님.

💡password

초창기 유닉스 버전에서는 비밀번호가 저장되었음.
보안 문제가 생기면서 비밀번호를 다른 파일로 옮김.

💡그룹 아이디(gid)

유닉스의 모든 유저는 어떤 그룹에 속함.

💡홈 디렉토리(home-dir)

시스템마다 디폴트로 설정해주는 홈 디렉토리가 다름.


✔ 파일의 생성과 소유권

쉘 프로세스는 로그인한 유저의 uid를 가짐.
쉘 프롬프트에 명령어를 입력받아 자식 프로세스를 생성하면 부모의 uid를 상속받음.
→ 로그인한 유저가 해당 프로세스를 만든 것으로 인식함.

파일을 생성하는 touch 명령어.


✔ 파일의 소유권 변경

파일의 소유권은 슈퍼 유저 또는 파일의 소유자가 변경할 수 있음.

파일의 소유자가 한 번 소유권을 양도하면, 이전 소유자의 의지로 파일의 소유권을 되돌려 받을 수 없음.
새로운 소유자가 다시 이전 소유자에게 양도해야 가능함.

💡슈퍼 유저(super user)

username = root
uid = 0

슈퍼 유저는 못하는 것이 없음
심지어 파일도 마음대로 삭제 가능.
→ 루트로 로그인해서 작업하는 것은 삼가하라. 시스템이 망가질 수 있음.


✔ 그룹(Group)

유닉스에는 많은 유저가 있음.
유저들이 모여서 그룹을 형성함.
그룹은 여러개가 있을 수 있음.
한 유저는 여러개의 그룹에 속할 수 있음. 적어도 하나의 그룹에는 속해야 함.

usermod 명령의 -G 옵션을 통해 그룹을 변경할 수 있음.
→ usermod = user modify

id 명령을 통해 로그인한 유저의 정보를 조회할 수 있음.
= whoami


그룹에 대한 정보는 /etc/group에 들어있음.
그룹의 identity : group-id(gid)

gid와 uid는 유저가 프로세스를 만들면 상속됨.
쉘도 프로세스임.
→ 쉘 프로세스는 로그인한 사람의 uid와 gid를 갖고 있음.
쉘 프로세스에서 자식 프로세스가 생성되면 uid와 gid가 생성됨.


✔ ruid와 euid

프로세스의 uid에는 두 가지 종류가 있음

💡ruid(real user-id)

프로세스를 실행시킨 유저의 id.

💡euid(effective user-id)

대부분의 경우 ruid와 euid는 같음.
하지만 가끔 다를 수 있음.

ruid와 euid가 다를 때, 프로세스가 만든 파일의 소유자는 누가 되어야 하는가?
→ euid가 생성된 파일의 소유자가 됨.

어떤 프로세스가 파일을 만들거나 접근할 때, 생성되는 파일은 전부 euid와 관련 있음.
→ ruid와는 관련 없음

euid와 gid가 파일의 접근 권한을 결정함.


💡ruid와 euid가 다른 특별한 경우

쉘에서 passwd라는 파일을 실행하는 경우.

passwd는 유저의 비밀번호를 바꾸는 파일임.
비밀번호는 아무나 변경할 수 있으면 안됨.
비밀번호는 /etc/shadow에 저장되어 있음.
/etc/shadow 파일의 소유자는 루트.
접근 권한은 루트에게만 있음.
root의 그룹은 root.
어떤 유저도 root와 같은 그룹에 속하지 않음.

ruid와 euid가 둘 다 100이라면 shadow 파일을 수정할 수 없음.
따라서 passwd를 실행하면 euid가 0(루트)으로 바뀜.



권한(permissions)

user : 소유자.
group : 소유자가 속한 그룹의 다른 유저들.
others : 소유자가 속한 그룹이 아닌 모든 다른 유저들.

vi의 소유자는 루트.
모든 다른 유저들은 vi를 읽고 실행할 수 있으나, vi에 대한 write 권한은 없음.
→ vi의 내용을 바꿀 수 없음.


슈퍼 유저는 permission에 관계 없이 뭐든 다 할 수 있음.



open 시스템 콜과 file permission

open 시스템 콜을 호출하면 파일이 있으면 열리고, 없으면 실패함.
그런데 파일이 있다고 하더라도 permission을 체크함.
이때, 권한을 체크하는 기준은 euid와 egid임.

시스템은 프로세스가 요청한 접근 모드가 권한이 있는지를 체크함.
파일이 있어도 권한이 없으면 open 호출에 실패함.
프로세스가 open을 호출했을 때, 파일에 접근 권한이 없으면 -1을 리턴함.


✔ 예제

위의 이미지에 file1 ~ file5의 각각의 파일의 permission과 유저, 그룹이 주어짐.
a.out이라는 프로그램의 permission과 유저, 그룹이 주어짐.

user의 쉘에서 a.out을 실행시켜 프로세스를 만들면 a.out의 uid와 gid는
ruid = usr1
euid = usr1
rgid = grp1
egid = grp1


a.out 프로세스에 위와 같이 5개의 open이 있을 때, 각각의 open의 성공 여부는?

file1 : 성공 → 유저가 같음, 유저에 r 권한이 있음.
file2 : 성공 → 유저가 다름, 그룹이 같음, 그룹에 r 권한이 있음.
file3 : 실패 → 유저가 같음, 유저에 r 권한이 없음.
file4 : 성공 → 유저가 같음, 유저에 r 권한이 있음.
file5 : 실패 → 유저가 다름, 그룹이 다름, others에 r 권한이 없음.


✔ 커널에서 파일의 접근 권한을 테스트하는 과정

if(프로세스의 euid가 0이면(슈퍼유저이면)) 접근은 무조건 허용됨.
else {
	if(프로세스의 euid가 파일의 owner id와 같으면){
    	if(유저 접근 권한이 있으면) 접근이 허용됨.
        else 접근이 거부됨.
    }
    else{
    	if(프로세스의 egid가 파일의 owner gid와 같으면){
        	if(그룹 접근 권한이 있으면) 접근이 허용됨.
            else 접근이 거부됨.
        }
        else{
        	if(others 접근 권한이 있으면) 접근이 허용됨.
            else 접근이 거부됨.
        }
    }
}

✔ S_ISUID와 S_ISGID

읽기, 쓰기, 실행 권한 외에도 permission에는 세 가지가 더 있음.

sticky bit는 별로 중요하지 않음. 나머지는 중요.
sticky bit는 디렉토리에 접근할 때만 의미가 있음.

이 세 가지는 기존의 유저 그룹 others 앞에 세 비트로 표현됨.
000 유저 그룹 others


💡S_ISUID

실행 파일에만 의미가 있는 permission.
실행 파일을 실행 시작할 때, 시스템(커널)이 생성되는 프로세스의 ruid를 쉘의 ruid로, euid는 파일 소유자의 uid로 설정함.
즉, S_ISUID가 세팅되어 있으면 프로세스의 ruid와 euid가 달라짐.
이 S_ISUID가 세팅되지 않으면 프로세스의 ruid와 euid가 모두 쉘의 것으로 세팅되어 같음.

로그인한 유저는 유저1(uid = 100), 그룹1(gid = 500)

a.out 파일의 소유자는 user1이 아니라 user2임.

a.out을 실행하면 a.out 프로세스의 ruid, euid는 user1이 됨.
user2의 파일인 a.out을 실행해도 그 프로세스의 ruid, euid는 실행한 user1이 됨.

chmod : 권한을 바꿔주는 명령.
u + s : 유저 permission 위의 S_ISUID를 1로 세팅함.

유저 부분의 x자리에 x대신 s가 들어감.
이 s는 x가 없으면 의미가 없음.
따라서 s가 있으면 x도 있는 것.

a.out을 실행하면 ruid는 그대로 user1이 되지만, euid는 user1이 아니라 파일의 소유자인 user2가 됨.
egid에 대해서도 같음.

이 예시에서는 chmod u + s로 유저의 권한에 s를 줬음.
그룹에 대해 s를 주면 egid도 group2로 바뀜.

프로세스가 실행될 때, euid와 ruid가 다른 값을 갖는 경우가 바로 S_ISUID가 1로 세팅되어 있는 경우.

파일을 실행할 때, 권한은 euid를 기준으로 체크함.
euid가 다른 사람으로 설정되어 있음 → 다른 사람의 권한으로 permission을 획득함.
파일을 만든 user2의 권한으로 a.out에 접근할 수 있음.


S_ISUID를 통해 다른 사람의 권한으로 프로그램을 실행하는 예시
→ 비밀번호를 변경해보자

passwd의 소유자는 루트.

passwd 파일의 유저 권한이 s로 설정되어 있음.
모든 사람이 이 파일을 실행할 수 있음.

passwd를 실행하면 비밀번호가 저장되어 있는 /etc/shadow 파일이 업데이트 됨.

shadow의 소유자는 루트.
루트만이 읽을 수 있음.
유저도 쓰기 권한이 없는데 어떻게 업데이트 하지?

user1이 자신의 비밀번호를 변경하려고 passwd 명령을 실행함.

S_ISUID가 세팅되어 있기 때문에, passwd의 euid가 루트가 됨.
/etc/shadow는 루트만이 읽을 수 있음.
user1에게는 write 권한이 없지만, 루트의 권한으로 shadow를 업데이트 함.



file creation mask

✔ file creation mask란?

생성된 프로세스에 attribute 값 처럼 붙어 다니는 것.
안전장치(safeguarding) 역할을 함.

특정 권한은 중요할 수 있음.
생성한 사람은 반드시 read, write 권한을 갖고 있어야 함.
실행파일이라면 execution 권한도 갖고 있어야 함.

내가 아닌 다른 사람들에게 가능하면 write 권한을 주지 않는 것이 좋음.
→ 다른 유저가 내가 만든 파일을 마음대로 수정할 수 있기 때문.
따라서 특별한 경우가 아니면 write 권한을 주면 안됨.

read 권한은 대부분 줌.
→ 비밀인 경우에는 주지 않음.

실행 파일이라면 다른 유저들도 실행할 수 있게 execution 권한은 줌.


따라서 r과 x는 주는 경우가 많지만 w는 주지 않는 것이 대부분임.

그런데 파일을 생성할 때 실수로 다른 사람들에게 write 권한을 잘못 부여할 수 있음.
file creation mask는 특별하게 지정된 권한이 잘못 주어지지 않도록 자동적으로 꺼버리는 역할을 함.
방지하는 역할.

이를 위해 mask라는 것을 설정함.
mask는 특별한 비트에만 1이 있는 값.
프로세스가 실행되기 전에 미리 세팅됨.

open이 첫 줄과 같이 실행되어도, 자동으로 두 번째 줄로 실행됨.
file creation mask는 프로세스가 실행되면 디폴트로 정해진 mask 값이 mode와 bitwise and 해서 값을 필터링해줌.

대부분 group과 others의 write에 해당하는 비트를 처리하기 위한 mask.
group과 others에게 write 권한을 주고 싶다면?
→ mask에서 해당되는 비트의 1 값을 지워야 함.


✔ umask(1) : umask 커맨드.

$ umask -s
// 값을 보여줌.
$ umask 22
// mask 값을 22로 바꿔줌.

✔ umask(2) : umask 시스템 콜

새로 설정하고 싶은 new mask 값이 시스템 콜 호출 인자로 들어감.
시스템 콜을 호출하면 바꾸기 전의 old mask 값이 리턴됨.

💡사용법



access 시스템 콜

access 시스템 콜을 실행하는 프로세스의 ruid와 rgid를 기반으로 pathname 파일에 대한 amode 권한이 있는지를 체크.

💡amode

R_OK : read 권한이 있는가?
W_OK : write 권한이 있는가?
X_OK : execute 권한이 있는가?
F_OK : pathname 파일이 존재하는가?


💡사용 예시



chmod 시스템 콜

pathname의 권한을 newmode로 바꿈.
이 시스템 콜을 수행하는 프로세스가 pathname 파일에 대해 권한이 있어야 함.
→ 이 프로세스를 실행하는 euid가 pathname 파일의 소유자와 같으면 됨.
다르면 바꾸지 못함.

파일의 소유자 또는 슈퍼 유저만 바꿀 수 있음.

💡사용 예시



chown 시스템 콜

파일의 소유자를 바꿔줌.
파일의 uid와 gid를 바꿀 수 있음.
내 파일만 바꿀 수 있음.
남의 파일의 소유자 변경 불가.
→ 남이 소유한 파일의 소유자를 변경하려하면 EPERM 에러 발생.


uid_t owner_id : 새로운 소유자
gid_t group_id : 새로운 그룹
만약 uid와 gid 중 하나만 바꾸고 싶으면 바꾸지 않을 것에다가 -1을 대신 넣기.


파일의 소유권이 바뀔 때 uid와 gid를 세팅하는 권한이 자동적으로 꺼짐.


예를 들어, 삼성이 돈을 아주 많이 들여서 반도체 설계 도면을 만듦.
설계 도면이 들어있는 TopSecret이라는 파일을 생성함.
이 파일의 소유자는 삼성 직원(suser)
이 파일의 권한은 rw-------
→ 소유자만 read, write 권한을 가짐. 나머지는 없음.

suser가 설계 도면을 수정하는 프로그램(a.out)을 만듦
이 프로그램의 소유자는 suser, 이 파일의 권한은 rwx---------
→ 자신만이 실행할 수 있고, 읽고 쓸 수 있음.
이 a.out이 TopSecret 파일을 read, write 할 수 있음.

TopSecret 파일에 제한된 접근만 허용하는 프로그램(b.out)을 만듦.
b.out을 만든 suser가 b.out의 소유자가 됨.
이 b.out의 권한은 rwsr-xr-x.
→ 협업을 위해 다른 사람이 프로그램을 실행할 수 있게함.
→ 그리고 여기에 S_ISUID를 세팅해줌.

삼성의 기술을 호시탐탐 노리는 스파이(uid = 200)가 있다고 하자.
스파이가 b.out을 통해 TopSecret에 접근하더라도 별 문제 없음.
스파이가 b.out을 실행하면 ruid = 200, euid = 100이 됨.
→ 스파이가 b.out을 통해 TopSecret에 접근할 수 있음.
그런데 이런 것까지 다 고려해서 b.out 프로그램을 만들었기 때문에 별 문제 없음.

문제는 스파이가 직접 c.out이라는 프로그램을 만드는 것.
만든 스파이가 파일의 소유자가 됨.
이 c.out의 권한은 rwsr-xr-x.
이때, 스파이가 자신이 만든 c.out의 소유자를 suser로 바꿔버림.
그리고 스파이가 c.out을 실행함.
이 c.out의 ruid = 200 → 스파이, euid = 100 → suser.
따라서 c.out을 통하면 TopSecret을 read write 할 수 있음.
스파이가 만든 프로그램으로 suser의 권한을 이용해 TopSecret 파일에 마음대로 접근하는 것.

이를 막기 위해 chown을 할 때, rws의 s를 자동적으로 클리어 시켜줌.



File with multiple names

파일 시스템

하드디스크 같은 저장 장치에 파일을 저장하기 위해 논리적인 구조를 가진 소프트웨어.
유닉스 파일 시스템은 계층 구조(hierarchical structure)를 가짐.
→ 맨 위에 루트가 있음.


💡Mount-on

유닉스 파일 시스템에서는 여러개의 파일 시스템을 하나로 통합할 수 있음.
위 그림의 /dev/sd0g 파일 시스템을 그 위의 루트 파일 시스템으로 통합시키는 것을

"(아래) 파일 시스템을 (위의) 파일 시스템으로 마운트시킨다."라고 함.

루트는 하나만 있어야 함.
마운트 후에 루트가 여러개가 되면 안됨.
다른 디렉토리에 마운트 되는 파일 시스템의 루트를 붙임.
이때, 다른 파일 시스템의 루트가 붙게 되는 디렉토리를 "마운트 포인트"라고 함.



유닉스 파일 시스템

유닉스의 파일 시스템의 종류는 한 가지가 아님. 다양함.

유닉스 파일 시스템은 크게 4개의 블록으로 구성됨.

💡Boot block

파일 시스템을 작동시키는데 사용되는 Boot code가 있는 부분.

💡Super block

파일 시스템의 정보를 담고 있음.

  • 파일 시스템에 블록이 몇개가 있는가
  • 비어있는 i-node의 개수가 몇개인가
  • 비어있는 블록이 어디에 있는가(a bit map)
    → 비트 맵을 보면 어디가 비어있고 채워져있는지 알 수 있음.
  • 블록의 사이즈가 얼마나 되는가?(보통 4k)
  • 비어있는 블록이 몇개인가
  • 채워져있는 블록이 몇개인가

등의 정보들이 담겨있음.

💡Data block

블록 단위로 데이터가 들어있음.
사용되는 블록도 있고, 비어있는 블록도 있음.

💡i-node block

어떤 파일에 일대일로 대응되는 것이 i-node.
→ 파일 하나에 i-node는 단 하나.

일대일로 대응되기 때문에 i-node는 파일을 유니크하게 identify함.

i-node block에는 i-node들이 들어가 있음.
i-node는 파일에 관한 정보들을 갖고 있음.



i-node

✔ i-node란?

디스크의 데이터 블록에 있는 어떤 파일에 딱 하나만 일대일로 대응되는 것.
어떤 종류의 파일이든지 각각의 파일은 딱 하나의 i-node가 반드시 대응됨.
i-node의 일련번호로 파일을 지정할 수 있음.

i-node에는 파일 이름이 없음.
파일 이름은 디렉토리에 등록되어 있음.
디렉토리에 있는 파일 이름이 디스크의 어떤 파일을 가리키는지에 대한 i-node의 포인터를 가짐.
따라서 디렉토리에는 파일명과 i-node 넘버만 들어있음.
그리고 이 i-node 넘버에 의해 파일 시스템에 있는 하나의 파일이 대응됨.


💡특수목적 i-node

0번과 1번은 i-node 번호로 사용되지 않음.
0번은 i-node가 없다는 의미로 사용됨.
→ 실제로 0번 i-node가 가리키는 파일은 없음.

1번은 디스크에 에러가 있어 데이터를 쓸 수 없는 bad block들의 정보를 갖고 있는 파일을 가리킴.

따라서 실제로 파일에 대응되는 i-node는 2번부터.
이 2번 i-node는 루트 디렉토리에 대응됨.



✔ Hard link

하드 링크는 파일에 대한 다이렉트 포인터.

특정한 파일에 대해 i-node 넘버는 딱 하나만 대응됨.
But 프로그램에서 파일에 접근할 때는 i-node 넘버가 아니라 파일 이름으로 접근함.
파일 이름은 디렉토리 안에 있음.
디렉토리 안에 파일 이름과 i-node 넘버가 있고, 이 i-node 넘버가 파일을 가리킴.
이런 것을 하드 링크라고 함.

그래서 유닉스 프로그램에서 파일을 접근하려면 반드시 i-node 번호에 대응되는 파일명이 적어도 하나가 있어야 함.
→ 하나 이상이 있을 수 있음.

다른 디렉토리에 i-node 넘버가 97인 다른 이름을 갖는 것이 있을 수 있음.
같은 97번 i-node를 가리키는 파일 이름이 2개가 존재하는 것.

i-node에 연결된 파일 이름의 개수를 link count(hard link의 개수)라고 함.
i-node를 가리키는 디렉토리 엔트리의 개수.

이 link count가 0이 될 때만 파일이 삭제됨.

프로그램에서 파일에 접근하려면 파일 이름이 반드시 있어야 함.
→ hard link가 적어도 하나는 있어야 함.
link count가 0이라는 것은 hard link가 하나도 없음을 의미.
hard link가 하나도 없음 == 그 i-node에 대응되는 파일 이름이 하나도 없음.
파일 이름이 없으면 프로그램에서 그 파일에 접근을 못함.
그러면 그 파일은 존재의 의미가 없음.

따라서 link count가 0이면 그 파일은 파일 시스템에서 삭제된 것으로 간주함.


유닉스 시스템 안에는 파일 시스템이 여러개 존재할 수 있음.
2개의 파일 시스템을 마운트할 때, 실제로는 파일 시스템이 2개 있으면서 하나의 계층을 구성하는 것.
hard link는 파일 시스템을 cross 할 수 없음.
→ 다른 파일 시스템에 있는 디렉토리에서 i-node를 hard link 할 수 없음.
→ 같은 파일 시스템 내에서만 hard link 할 수 있음.


어떤 유저든 디렉토리를 만들 수 있음.
오직 슈퍼 유저만이 디렉토리에 대해 hard link를 만들 수 있음.
다른 이름으로 hard link를 추가하는 것은 슈퍼 유저만 할 수 있음.


위의 그림을 보면 다른 디렉토리에서 같은 i-node를 가리킴
→ hard link를 추가하는 것.

두 개의 i-node 번호가 단순히 같은가?
같으면 name1과 name2가 서로 다른 이름이면서 같은 파일을 가리키는 두 개의 hard link가 됨.
→ 12345 i-node를 가리키는 link count는 2가 됨.



✔ Symbol link

윈도우의 바로가기 파일.
→ pathname을 통해 파일에 링크시키는 것.

유닉스에서는 윈도우의 바로가기 파일을 Symbol link라고 함.
파일에 대한 indirect 포인터.
pathname을 가지고 있는 파일을 통해서 간접적으로 가리킴.

hard link는 디렉토리에서 i-node로 넘어가서 직접 가리킴.
symbol link는 바로가기 파일처럼 또 다른 파일이 있어, 그 파일 안에 실제로 가리킬 파일의 pathname이 있음.
symbol link의 실제 내용은 링크되어 있는 파일의 pathname.


hard link는 다른 파일 시스템에 있는 것을 링크하지 못함.
하지만 symbol link는 파일 시스템의 제한이 없음.

symbol link를 만들 때는 link 명령은 쓰지 못하고 ln 명령만 쓸 수 있음.

ln -s (오리지널 파일) (symbol link 파일)


symbol link는 같은 파일이 아니고 다른 파일임.
name2 파일이 name1 파일을 가리킴.

ls 명령을 통해 조회하면 name2 → dirA/name1과 같은 형태로 symbol link를 확인할 수 있음.
또한, symbol link 파일은 맨 앞의 파일 타입이 l로 표기됨.



hard link와 symbol link를 만드는 시스템 콜.

original_path : 오리지널 경로명
new_path : 새로운 경로명

성공하면 0, 실패하면 -1을 리턴.

새로 링크되는 이름이 디렉토리 엔트리에 추가됨.
i-node의 link count가 1 증가함.

디렉토리에 대한 hard link를 추가하는 것은 슈퍼 유저만 할 수 있음.


💡사용 예시



링크를 삭제하는 명령.
삭제하고자 하는 pathname을 넣으면 됨.
→ 그 pathname이 디렉토리 엔트리에서 제거됨.
→ 링크된 이름을 삭제함.
→ i-node의 link count가 1 감소함.


unlink를 수행하다가 link count가 0이 되는 순간
그 i-node는 free i-node가 되고,
그 i-node가 가리키던 데이터 블록이 클리어됨.
→ free block 리스트에 들어감.

unlink는 write 권한이 있어야 함.
디렉토리에 대해 read, write 권한이 있어야 함.

파일 명을 바꾸는 rename 프로그램.
새로운 것을 연결하고 원래 있던 것을 unlink 함.



remove 시스템 콜

파일에 대해 remove는 unlink와 같음.



rename 시스템 콜

파일의 이름을 바꿔주는 시스템 콜.



symbol link는 윈도우의 바로가기 파일.

hard link는 이름만 추가되는 것.
symbol link는 또 다른 파일이 추가됨.
realname 파일의 절대 경로명이 symname이 가리키는 파일 안에 들어있음.

symname 파일에서 절대 경로명을 찾아 realname 파일에 접근함.


fd = open("file",)

어떤 파일을 open하면 파일을 가리키는 file descriptor가 리턴됨.
그런데 symbol link 파일을 open하면 file descriptor는 realname 파일을 open해서 가리킴.
링크 파일이 아니라, 링크 파일 안에 있는 절대 경로 파일의 descriptor를 리턴함.

symbol link 파일 자체의 내용을 보려면 open하면 안되고 readlink라는 시스템 콜을 이용해야 함.
readlink 시스템 콜을 이용해서 symbol link를 열면 그 안에 있는 내용을 볼 수 있음.



symbol link 파일을 open하면 그 파일 자체를 open하는 것이 아님.
symbol link가 간접적으로 가리키고 있는 파일을 open함.
symbol link 파일 자체를 open할 때 사용하는 것이 readlink 시스템 콜.

readlink에는 일반적인 파일이 들어가면 안됨.
symbol link만 들어가야 함.

sympath를 open해서 그 안의 내용을 buffer에 읽어주고 sympath를 닫음.
리턴 값은 실제로 읽은 문자의 개수.


💡danggled reference

symbol link 바로가기 파일이 간접적으로 가리키고 있던 오리지널 파일이 삭제되면?
→ symbol link 파일을 readlink로 열어보는 것은 가능함.
→ 그런데 symbol link를 open하면 오리지널 파일이 없어서 EEXIST 에러가 발생.



stat과 fstat을 이용해 파일의 정보 얻기

stat 시스템 콜과 fstat

stat은 어떤 파일의 i-node에 들어있는 자세한 정보를 가져와서 보는 시스템 콜.

stat에는 파일 이름이 들어감.
fstat에는 파일 이름 대신 파일을 미리 open 해놓고 그 file descriptor를 인자로 넣음.

lstat의 l은 symbol link를 의미함.
lstat의 pathname에는 symbol link만 들어갈 수 있음.


💡그냥 stat에 symbollic link 파일을 넣으면?

symbol link 파일의 i-node 정보가 아닌, symbol link 파일이 가리키고 있는 파일의 i-node 정보를 읽어옴.
symbol link 자체에 대한 i-node 정보를 보려면 lstat을 써야 함.


💡정리 : 인자로 넘어가는 것

stat : 파일명
fstat : open된 파일의 descriptor
lstat : symbolic link 파일의 파일명


위의 변수들이 i-node에 들어있는 정보들을 변수로 표현한 것.

💡st_ino

i-node 넘버.

💡st_mode

파일의 타입과 모드(권한:permission)
→ 파일 타입 : 4 비트, 모드 : 12 비트.

💡st_dev

디바이스 넘버가 있음.
파일이 디스크가 아니라 usb에 있을 수도 있음.
→ 어떤 장치에 이 파일이 저장되어 있는가에 대한 정보.

💡st_nlink

link count.
link의 수.

💡st_uid

소유자(owner)

💡st_gid

소유자의 gid

💡st_size

레귤러 파일의 사이즈 정보.
몇 바이트 인지.

💡st_atime

가장 최근에, 가장 마지막에 접근한 시간.
last access.

💡st_mtime

가장 최근에, 가장 마지막에 컨텐츠를 수정한 시간
last modification

💡st_ctime

가장 최근에, 가장 마지막에 파일의 status가 수정된 시간.
last file status change.
→ i-node에 있는 정보가 변경된 마지막 시간

💡st_blksize

I/O에 가장 좋은 블록 사이즈

💡st_blocks

할당된 디스크 블록의 개수


위와 같은 정보들이 i-node에 저장되어 있음.


✔ 예제




profile
나의 기록

0개의 댓글