※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)
이 파일을 접근하는데 P1이 Abcd를 가나다라로 바꾸고 있다고 가정하자. 아직 파일은 저장되지 않은 상태이다. 이 때 P2가 이 파일을 읽으면 가나다라로 바뀌지 않고 Abcd로 나타나있을 것이다. 이는 Consistency에 어긋난다. 이것을 위해서 OS에서 제공하는 것이 Lock이다. 말 그대로 하나의 프로세스가 특정 파일을 건드리고 있을 때는 다른 프로세스는 그 파일에 접근할 수 없게 하는 것이다. Lock도 여러가지 방법으로 구현할 수 있다. 가장 대표적으로 쓰이는 두 가지가 바로 Unix semantics와 Session semantics이다.
Unix semantics는 하나의 프로세스가 열린 상태에서 Read 혹은 Write를 할 때마다 Lock과 Unlock을 되풀이 하는 것이다. 즉, 한번 open()를 통해 파일을 열고 난 후 read를 하면 read가 끝날 때까지 lock을 걸어서 다른 프로세스는 그 파일을 건들지 못 하게 하는 것이다.
Session semantics는 더욱 더 확실한 방법의 consistency를 보장한다. 프로세스가 파일을 접근하는 과정은 대략 open한 후 read 혹은 write를 원하는 만큼 실행한 후 close 하는 것이다. Session semantics는 프로세스가 파일을 open하고 close할 때까지 Lock을 한다는 것이다. Consistency가 확실하게 보장될 것으로 기대된다.
이제 본격적으로 File Protection에 대해서 이야기 해보자. File Protection은 기본적으로 Multi-user system에서 중요하게 다루어진다. 하나의 Unix 서버에 A라는 사용자와 B라는 사용자가 있다. A가 그 시스템에 자기의 일기를 써놨다고 하자. B가 그걸 읽어도 될까? 혹은 수정해도 될까? 더욱이 안된다. 이러한 이유에 때문에 Multi-user system에서는 File Protection이 구현되어야 한다.
그렇다면 어떠한 부분에 초점을 맞춰서 protection이 구현되는 것인가? 바로 실행하는 함수들에 초점을 맞추어서 Protection이 구현된다. Read, Write, Execute가 바로 그것이다. 허가되지 않는 사용자가 내 파일을 read, write, execute하지 못 하도록 해보자는 것이다.
이것을 구현하는 방법 중에 가장 많이 사용되는 방법이 Access Matrix이다. 하나의 테이블에 access 권한을 기록해두는 것이다.
위의 표에서 말하는 도메인은 사용자를 의미하고 Object는 각각의 파일들을 의미한다. 자 생각해보자. 뭔가 이상하지 않나? 하나의 시스템에 도대체 파일이 몇 개가 있는데 이런 식으로 관리하겠다는 것인가? 수천개 혹은 수만개 수억개까지도 가능한데 그 모든 파일에 대해서 저런 식으로 테이블을 가지고 있겠다는 것은 어찌보면 비현실적이다.
결론적으로 말하면, Unix 시스템에서는 그럼에도 불구하고 저런 식으로 사용을 하기는 한다. 그런데 진짜 저런 식으로 사용하는 것이 아니고, 위의 데이터에서 필요한 데이터들만 저장하여 갖고 있는다. 여기서 Sparse Matrix를 이야기하면 될 것 같다. 위의 테이블을 보면 내용이 있는 칸보다는 없는 칸이 더 많다. 아무 내용도 없는데 굳이 공간을 할당하고 있을 필요가 있을까? 아니다. 그래서 다음과 같이 기록하는 것이다.
도메인 단위로 다음과 같이 기록해둘 수 있다. 이렇게 도메인 기준으로 나타낸 것을 Access list 방식이라고 한다.
D1 : (F1, R), (F3, R)
D2 : (Printer, Print)
D3 : (F2, R), (F3, X)
D4 : (F1, RW), (F3, RW)
필요한 내용들만 뽑아서 쓴 것이라 훨씬 사이즈가 compact해질 수 있다. 그런데 Domain을 기준으로 하지 않고 Object를 기준으로 해도 될 것 같지? 그렇다. 해도 된다.
F1 : (D1, R), (D4, RW)
F2 : (D3, R)
F3 : (D1, R), (D2, X), (D3, RW)
Print : (D2, Print)
위와 같이 해도 좋다. 이와 같이 Object 기준으로 나열해둔 것을 Capability list 라고 한다. Unix system은 그렇다면 Access List 또는 Capability list 둘 중에 어떤 방법을 사용할까? 이번 포스팅이 끝날 때 쯤이면 이 답을 낼 수가 있다. 답을 찾아서 슝슝슝 가보자.
Unix에서 ls -l을 실행하면 어떤 결과를 얻는가? 파일의 inode 정보를 얻을 수 있다. 당연히 거기에는 rwxrwxrwx와 같이 실행권한을 의미하는 부분도 포함되어있다. (이 부분이 무엇인지 모르는 분은 따로 인터넷에 검색해보시길 바란다. 매우매우 쉽게 찾을 수 있을 것이다.) 말하고 싶은 것은 Unix 시스템에 존재하는 모든 파일은 inode에 실행권한 부분을 가지고 있다는 것이다.
또 다른 이야기를 해보자. 이전 포스팅에서도 다루었던 파일을 접근하는 방법에 대한 이야기 이다. 그런데 이번에는 권한에 초점을 맞추어서 이야기를 해볼 생각이다.
fd1 = open("/etc/passwd", "O_RDONLY");
fd2 = open("/anything/abc/test.txt", "O_RDWR");
fd3 = open("/etc/passwd", "O_WRONLY");
파일을 open할 때 어떤 과정으로 하는지 다시 한번 되세겨 보자.
1. 파일 이름을 얻는다.
2. 디렉토리 검색을 한다.
3. 파일이 검색될 경우 metadata를 메모리에 로딩한다.
4. metadata가 있는 주소의 위치를 가리키는 포인터를 system-wide open-file table에 저장한다.
5. system-wide open-file table index의 위치를 per-process open-file table에 저장한다.
6. per-process open-file table index의 주소를 return 한다.
여기서 3번과 4번을 보자. 3번에서는 metada를 로딩을 한다고 했는데, 추가적으로 한 가지 더 하는 것이 있다. 바로 여기서 권한을 검사한다. "너가 /etc/passwd에 접근할 권한을 갖고 있는 놈이냐?"하고 물어보는 것이다. 검사를 할 수 있냐고? 당연하다. 왜냐하면 metadata에 rwxrwxrwx와 같은 권한 정보가 있으니까. 그리고 4번에서는 metadata의 주소가 system-wide open-file table에 저장하는 일을 하는데 이 때 system-wide open-file table을 잘 보자. right이라는 field가 있다. 권한이다. 즉 이 테이블은 모든 열려있는 파일들에 대한 권한을 다 가지고 있다. 여기서 또 검사를 하는 것이다. 가령 위의 C코드를 봤을 때 fd1은 /etc/passwd 파일을 ReadOnly로 오픈했다. 만일 fd1 포인터를 통해 /etc/passwd 파일을 write하려고 한다면 어떻게 될까? 권한이 없어서 불가능하게 된다. 아래의 그림과 같다.
자, 이제 다시 위의 질문으로 돌아가보자. Unix 시스템에서는 Access List 방식을 사용하는가? Capability List 방식을 사용하는가? 정답은 "둘 다 사용한다" 이다. inode table에 저장되어 있는 rwxrwxrwx와 같은 정보들이 바로 access list를 구현해놓은 것이고, system-wide open-file table에 저장되어있는 각 파일 포인터에 대한 접근 권한이 바로 capability list를 구현해놓은 것이다.
OS에 대한 포스팅은 다음에 또 언제 하게 될지 모르겠다. 하지만 내가 공부하는데로 바로바로 올릴 것에 대해서 약속합니다.
'Operating Systems' 카테고리의 다른 글
[OS] Memory Management Scheme (8) | 2013.06.30 |
---|---|
[OS] File System (0) | 2013.05.18 |
[OS] File System (4) | 2013.05.17 |
[OS] Deadlock Detection (2) | 2013.02.03 |
[OS] Deadlock Avoidance (Banker's Algorithm) (5) | 2013.02.03 |