Files and Directories
OS는 파일시스템 안에서 물리적인 디스크를 관리한다.
File system : 파일과 attribute의 집합체로 파일을 효율적으로 관리하기 위해서 파일의 위치나 이름을 관리함. 실제 하드디스크상의 위치는 모르더라도 파일이름과 offset으로 파일의 위치를 찾는다
Directory : 다른 파일이나 서브디렉터리들을 포함할 수 있는 기능을 가지고 있는 것. 아이노드 번호와 파일명을 하나의 디렉터리 엔트리라고 하고 이정보를 가지고 있는 것을 디렉터리라고 한다. 대부분의 디렉터리는 트리구조이다.(계층구조)
Root directory : ' / '라고 표현함. 절대경로(루트부터 시작되는 경로)를 의미함.
Parent directory : " .. " 현재 작업 중 인디렉토리를 기준으로 부모디렉터리를 표현함.
Current working directory : " . " 현재 작업 중인 디렉터리를 나타냄.
Home directory : " ~ "로그인하고 처음에 보이는 디렉토리가 홈 디렉터리임 ex) cd ~
Sub-directory : 다른디렉토리안에 속해있는 디렉터리
pathname
루트부터 시작하는 절대경로(absolute path) or 현재 작업디렉터리를 기준으로 경로를 나타내는 상대경로(relative path)라는 두 가지 path로 이름 지을 수 있음
absolute path는 또 다른 말로 fully qualified path
절대경로는 루트부터 시작하기에 /부터 시작한다,
상대경로는 현재 작업 디렉터리를 기준으로 파일의 위치를 나타내므로 현재 디렉터리가 어디냐에 따라 최종 경로가 달라질 수 있음.
만약에 dirA에서 my3.dat의 경로를 상대경로로 나타낸다면?../dirC/my3.dat
만약에 dirA에서 my3.dat의 경로를 절대경로로 나타낸다면? /dirC/my3.dat
만약에 dirB에서 dirA에 있는 my1.dat의 경로를 상대경로로 나타난 대면?../my1.dat or./../my1.dat
이처럼 상대경로로 나타내는 방법은 다양하나 short path로 보통 표현한다.
만약에 dirB에서 dirA에 있는 my1.dat의 경로를 절대경로로 나타난 대면? /dirA/my1.dat
Change directory
cd 명령어처럼 사용이 되는 함수가 있다. chdir
getcwd함수를 사용하러면 버퍼를 준비해야 하는데, 그럼 버퍼의 크기를 얼마로 해야 할까? 시스템에서 반환할 수 있는 최대 경로를 알아야 버퍼의 크기를 설정할 수 있는데 알아내기 쉽지 않고 임의로 설정하는 것도 어려움.
그럼 시스템 별로 PATH_MAX가 정해져 있는데 이것을 활용을 하자. 그래서 char buf [PATH_MAX];로 선언하자. PATH_MAX가 없는 시스템인 경우엔 임의의 값으로 사용하자.
search path
만약 실행파일의 이름만 주게 되면 OS 프로세스는 사용자가 준 실행파일의 위치를 시스템의 환경변수 중에서 PATH에 정의된 디렉터리를 순서대로 뒤져서 찾아낸다.
which 명령어를 써서 실행파일의 위치를 바로 알아낼 수 있다. ex) which ls
현재 작업디렉터리를 PATH환경변수에 추가할때 맨 처음에 둔다면 보안상 위험할 수 있음. 왜? 해커가 home디렉토리에 ls라는 이름의 실행파일을 넣어두고 심어두고 나간다고 가정하자. 사용자가 ls를 입력하고 엔터를 치면 시스템이 ls라는 파일을 찾기 위해서 PATH환경 변수를 쭉 뒤진다, 근데 . 이라는 현재디렉토리가 맨처음에 뒤져진다면 현재 디렉토리에 해커가 심어둔 ls파일이 실행이 된다. 그렇게 때문에 현재 디렉토리를 맨 마지막에 둔다면 이런 위험성을 줄일 수 있다.
Directory access
디렉터리안에있는 내용들을 access하고 싶을때 opendir, closedir, readdir함수가 있다.
성공적으로 오픈을 했다면 DIR스트림을 가지고 디렉토리 엔트리를 access 할 수 있다.
File status information
lstat과 stat함수를 이용해서 파일의 여러 정보들을 얻어낼 수 있다.
Inode : 파일에 대한 정보를 담고 있는 객체, 아이노드의 크기는 파일의 크기와 상관없이 고정되어 있다.
Directory implementation
디렉터리안에 디렉토리 엔트리 정보가 들어가 있다. 디렉토리도 하나의 파일이다. 그래서 파일의 타입중에서 디렉토리 타입인 파일이 있다. 그럼 디렉토리파일은 어떤기능을 가지고 있나면 디렉토리 엔트리정보를 가지고 있는 파일이 디렉토리이다. 하나의 디렉토리 엔트리란 파일명과 파일위치 정보를 담고 있는 정보이다. 파일위치는 inode번호를 가지고 표현을 한다.
디렉터리 안에는디렉토리 엔트리 정보가 들어가있다. 그래서 디렉토리 엔트리란 inode번호와 파일명의 페어로 구성이 된다.
어떤 파일의 inode로 access 하기 위해선 사용자는 inode를 직접 지정하는 것이 아니고 사용자가 표현하기 쉽도록 경로명을 통해서 access 하고 싶은 파일을 지정을 하면 os가 사용자가 지정한 경로를 따라서 부모디렉터리부터 말단 디렉토리까지 쭉 내려가 파일명을 찾게되면 그 파일의 디렉토리 엔트리를 찾아갈 수 있게되는 것이고 디렉토리엔트리를 찾았으면 inode번호를 알게된다. 그래서 innode객체를 찾아갈수있게된다. inode객체를 찾아가면 그 파일의 상태정보와 파일의 내용을 access할 수 있게 된다.
advantages of inode+filename
실제파일과 디렉토리 구조를 분리하면 어떤 장점이 있을까?
1. 파일명이 디렉토리 엔트리 안에 들어있기 때문에 파일명을 변경할 때 간단한다.(디렉터리 엔트리만 찾아가면 엔트리에 파일명 필드가 있어서 그 필드만 수정하면 된다. 실제 파일의 inode객체를 access 해서 수정할 필요가 없어짐)
2. 만약에 파일이 속한 디렉터리를 변경할때 실제 파일의 inode객체와 블럭들을 실제로 옮길 필요가 없고 디렉토리 엔트리만 옮기면 된다.
3. 디스크상에 실제 파일은 하나만 존재하더라도 그 파일을 나타내는 파일이 름은 여러 개가 있을수 있다. 같은 inode를 가리키는 디렉터리 엔트리만 추가하면 되기떄문. 즉, 같은 파일을 가리키는 이름을 여러개 만들어서 사용할 수 있다. 그래서 서로다른 디렉토리에 같은 이름의 파일로 같은 파일을 가리킬 수 있다. 혹은 같은 디렉토리안에 서로 다른 이름을 가지고 있지만 그 다른이름이 같은 파일을 가리키게 만들수도 있다.
4. 디렉토리 엔트리 구조의 크기는 크지 않다. 왜냐하면 실제 파일정보는 inode라는 객체에 따로 저장이 되어있기 때문에
Hard links and Symbolic Links
링크란 파일이름과 inode사이의 연관관계를 표현한 것이다.
hard link : 파일이름과 inode사이의 연관관계가 강한 것(직접적인 연결)
symbolic link : 파일이름과 inode사이의 연관관계가 약한 것(간접적인 연결)
hand link 한 디렉터리 레퍼런스를 나타내는 것이고 하드디스크 상의 파일을 찾아갈 수 있는, 즉 inode를 찾아갈수있는 직접적인 포인터 정보를 가지고있는것이다. 파일과 연관된 파일명 이라는 것은 간단하게 디렉토리구조안에 포함된 레이블이라고 한다. 그냥 파일이름이라고 생각하면됨. 그리고 같은 파일을 가리키는 하드링크의 이름이 하나만 있는것이 아니라 여러개가 있을 수가 있다. 그 하드링크의 이름은 같은 디렉토리안에 다른이름으로 존재할 수 있고 다른 디렉토리에서 원본 파일 이름과 같은 이름으로 위치할 수 도있다. ex) 파일을 하나 만들면 inode가 만들어지고 디렉토리 엔트리도 생성된다. 그래서 inode 번호를 통해서 엑세스 할 수 있게된다. 근데 하드링크는 같은 inode를 가리키는 디렉토리를 또 만들 수 있다는 뜻이다. 즉, 같은 inode를 가리키는 하드링크의 이름이 여러개가 있을 수 있다. 같은이름일수도, 다른 이름일 수도 있고 이처럼 하드링크를 여러개 만들 수 있다. 심볼릭 링크도 마찬가지이다. 어떤 특정 디렉토리 엔트리를 통해서 파일을 변경을 한다고 가정하고 test`에 ABC라는 내용을 추가했다고 하자. 그 변경된 사항이 test라는 이름으로 access 하더라도 변경된 사항이 test`을 access 하지 않더라도 똑같이 적용이 된다. 왜냐하면 test나 test`이 같은 파일을 가리키고 있기 때문에. 이것은 씸볼릭도 마찬가지이다. 그러나 하드링크는 같은 파일시스템 내의 파일에 대해서만 참조할 수 있다는 제약사항이 있다.
새로운 하드링크를 추가로 생성하게 되면 새로운 디렉터리 엔트리만 추가가 된다.새로운 디렉토리 엔트리는 같은 inode를 가리키기 때문에 inode번호가 동일하다. ln 명령어로 원본파일의 하드링크를 추가할 수 있다. 하드링크를 추가하면 링크 카운트값이 하나 증가된다(감소되면 하나삭제). 삭제하려면 rm 명령어를 사용하면 된다. ln 명령어와 똑같은 역할을 하는 system call 함수가 있는데 link함수이다. 반대로 삭제하려는 함수는 unlink함수이다. 하드링크를 삭제하다가 카운터 값이 0 이 되면 inode자체가 삭제된다.
링크 카운터는 같은 파일을 가리키는 하드링크가 몇 개가 있는지에 대한 카운터값을 노드에 유지를 한다. 링크카운터는 정수형 숫자이고 int 값은 링크의 총개수를 알려주고 새로운 하드링크가 생성될떄마다 카운터 값이 하나씩 증가가 되고 링크가 삭제돼서 카운터값이 0이 되면 디렉터리 엔트리만 지우는 것이 아니라 inode자체도 지운다.
symbolic link는 특별한 타입의 파일이다. 씸볼릭링크를 추가를 하면 하드링크처럼 inode는 가만히 있고 디렉토리엔트리가 추가되는것이 아니라 심볼릭 링크를 하나 만들게되면 심볼릭 링크라는 원본파일의 경로명이 포함된 특별한 형태의 파일이하나 만들어진다.
내가 access 하려고 하는 파일을 씸볼릭 링크의 경로로 주게 되면 OS가 심볼릭 링크에 inode를 보고 탐색을한다. 탐색을 해서 심볼릭 링크까지 가고 inode를 찾아간 다음에 이 파일이 일반파일이아니고 심볼릭 링크라는것을 파악하게 되면 디렉토리 탐색을 멈추는 것이 아니라 심볼릭 링크안에 포함되어 있는 원본파일을 보고 그 원본 파일의 inode로 탐색을 계속한다. OS가 심볼릭링크안에 원본파일의 경로가 있다는것을 보고 계속탐색을한다. 그래서 원본파일의 inode를 찾아간다. 그래서 심볼릭 링크를 통해서 간접적으로 연결된 원본파일을 찾아간다. 심볼릭링크를 만들기위해선 ln -s 명령어를 사용한다. 또한 심볼릭 링크는 하드링크처럼 원본파일의 링크 카운터값을 유지하지 않는다. 하드링크는 좀더 강한 직접적인 연관관계를 맺고 있는 링크이기때문에 inode에서 별도로 링크 카운터 값을 관리하는 반면에 심볼릭 링크는 카운트 값을 따로 관리하지 않는다.
씸볼릭과 하드의 차이점은 삭제할떄 생긴다. temp.c라는 원본파일을 삭제를 한다면 심볼릭 링크인 경우에 심볼릭링크가 가리키는 원본파일이 삭제가 된다. temp-sym.c안에는 원본파일의 경로명이 들어가 있었는데 그 파일이 삭제가 되어서 색이 바뀌고 댐블링 포인트가 되어버렸다. 그러나 하드링크였던 temp2.c는 여전히 원본이였던 temp.c inode를가리키고 있다. temp.c는 삭제가 됐지만 temp.c의 inode는 삭제가 되지 않고 카운트 값만 하나 감소되었다. 즉 temp2.c를 이용해서 원본파일을 access할 수 있다. 그러나 심볼릭 파일을 열면 아무런 내용도 안 뜬다.
재밌는 사실로 여기서 아까 삭제한 원본파일과 같은 이름의 파일을 다시 만든다면 이제 temp.c와 temp.2는 아예 다른 파일이 된다. 하지만 temp.c와 temp-sym.c는 다시 연결이 되었다. 그래서 temp-sym.c는 새로 만든 temp.c를 가리키는 씸볼릭 링크가 된 것이고 temp2.c는 예전파일을 가리키는 파일로 남아있게 된 것이다.
'Computer Science > 시스템 프로그래밍' 카테고리의 다른 글
[시스템 프로그래밍] Chapter 8 (0) | 2024.05.09 |
---|---|
[시스템 프로그래밍] Chapter 6 (0) | 2024.05.09 |
[시스템 프로그래밍] Chapter 4 (0) | 2024.04.12 |
[시스템 프로그래밍] Chapter 3 (0) | 2024.04.10 |
[시스템 프로그래밍] Chapter 2 (0) | 2024.04.06 |