저번 시간에 "데드락"에 대해서 배워봤었죠??
그리고 "IPC"에 대한 존재가 있다고 했지만 그전에 배워야할 것들이 있다고 했어요~
흐름에 따라 포스팅을 하는 것이 자연스럽고 깔끔하다고 느끼지만, 글을 쓰다가 아직 포스팅하지 않은 내용의 용어를 써야할 때는 조금 막막하더라구요. 그래서 고민하다가 데드락이 끝난 직후 바로 정리를 하는게 나을거 같더라구요~
그래서 저번시간에 언급했던 IPC를 배우기전에 한번 거쳐서 가야할 부분이 있습니다.
유저모드와 커널모드 ,시스템 콜, 인터럽트 정도? 알고 가시는게 흐름 상 좋을거 같다는 생각입니다!
자 그렇다면 오늘은 무엇을 배울거냐???! "유저모드" 그리고 "커널모드"에 대해서 배워볼려고 합니다.
그게 뭐야..? 하실수 있을거에요 ㅎㅎ 저도 그랬거든요. 일단 한줄~ 한줄~ 차근히 읽어보면서 이해해보죠.
자! 바탕화면에 있는 프로그램들을 실행시키면 여러 프로세스가 생성되어 메모리에 상주하게 되잖아요???????
(이거 기억 못하시면 벽 보고 서있으세요 ㅡ.ㅡ )
근데 실행된 프로그램이 다른 프로그램의 실행을 방해하거나 프로그램 간에 충돌을 일으키면 어떻게 할까요?
예를 들어 프로그램 A를 실행 시켰는데 그 프로그램에서 갑자기
"크킄킄.. 너 컴퓨터에 깔려있는 파일들을 몽땅 다 지울거야!!" 라고 명령을 내렸을 때 다른 프로그램의 메모리 영역이나 파일 영역을 침범하는 경우가 발생하겠죠?
이러한 문제를 막기 위해 하드웨어에 대한 보안 기법이 필요하답니다.
쉽게 생각하시면 돼요!
어떠한 프로그램에서 나쁜짓을 못하게 애초에 중요자원에는 접근할 수 없도록 막아놓으면 끝인거죠.
즉, 분리 시켜놓는겁니다~
그림을 보시면 유저영역과 커널 영역으로 나뉜거 보이시죠?
응용프로그램이나 사용자가 수행할 수 있는 영역과 운영체제가 수행할 수 있는 영역을 따로 분리시켜놓은거에요.
즉, 메모리(램) 공간에는 영역을 두개로 분리시키고 어떤 영역에서 수행중이냐에 따라 유저 모드와 커널모드로 나뉘는 겁니다.
유저영역에서의 수행되는 것을 유저모드! 커널 영역에서 수행되는 것을 커널 모드!
유저모드
일반적으로 프로그램을 실행시켰을 때 메모리에 상주하게 되는 공간이 유저영역이에요. 즉, 저희가 사용하고 있는 모든 사용자 애플리케이션들이 해당 메모리 공간에서 수행되는 거죠.
예를 들어, 웹 브라우저를 키거나 워드를 키거나 인텔리제이를 키거나 등등 프로그램을 실행 시켰을 때 데이터들이 메모리에 올라가잖아요? 이때 위치하는 곳이 유저영역이라는 거죠!
그리고 유저영역에서 명령어를 수행하고 있다면 그게 유저모드인 거죠
int x = 1;
int y = 2;
int result = x+y;
개발 툴에서 위의 코드를 작성했다고 가정해봐요!
디스크에 접근하는 명령어가 있나요?? 없죠! 그냥 메모리에 값을 연산하고 저장하는 부분밖에 없어요!
그래서 그냥 유저영역에서 수행될 수 있는 명령어들인거죠.
ifs.open("a.txt")
근데 지금 이 코드는 디스크에 보관되어있는 a.txt 라는 파일의 데이터를 오픈하라는 거네요??
(코드를 모르셔도 a.txt를 열라는거네? 라고만 생각하시면 됩니다)
이렇게 되면 유저모드에서 수행할 수가 없는거죠. 왜냐, 저렇게 디스크에 접근하는 명령어를 사용자 프로그램한테 쉽게 허락하면 악의적으로 데이터를 망가뜨릴 수 있는거죠. 저처럼 착한 개발자만 세상에 존재하는 건 아니니깐요ㅎㅎ
즉, 유저모드에서는 제한적인 명령만 수행할 수 있고 이렇게 유저모드에서 수행하는 명령어를 "일반 명령"이라고 말합니다!
다시 말해서, 일반 명령은 메모리에서 자료를 읽어와서 CPU에게 계산하고 결과를 메모리에 쓰는 등의 명령이고, 응용 프로그램에서 수행할 수 있는 명령인거죠.
커널 모드
운영체제가 실제로 사용하는 공간이 커널영역이에요. 그리고 커널 영역에서 명령어를 수행하고 있다면 그게 커널모드인거겠죠?
커널 모드는 운영체제가 CPU의 제어권을 가지면서 중요한 정보에 접근해서 위험한 상황을 초래할 수 있는 연산을 할 수 있는 모드에요
이렇게 커널모드에서만 수행하는 명령어를 "특권 명령"이라고 하는데 프로세스 제어, 파일 조작, 통신 뭐 등등 운영체제에서만 수행할 수 잇는 명령이에요~
아까 디스크에 접근하는 명령은 응용 프로그램이 할 수 없으니까 커널모드로 전환을 해서 운영체제가 해당 명령을 할 수 있게 해야죠! 즉, 디스크의 어떠한 자원에 손을 댈거면 커널모드로 전환해서 특권 명령을 사용할 수 있게 해야한다는 거죠.
그래서 아까 위에서 "open("a.txt")" 이 명령어는 커널모드로 전환을 해서 운영체제가 처리할 수 있는거죠.
아래의 표가 커널의 핵심 기능이라고 보시면 됩니다!!
핵심 기능 | 설명 |
프로세스 관리 | 프로세스에 CPU를 배분하고 작업에 필요한 제반 환경을 제공한다. |
메모리 관리 | 프로세스에 작업 공간을 배치하고 실제 메모리보다 큰 가상공간을 제공한다. |
파일 시스템 관리 | 데이터를 저장하고 접근할 수 있는 인터페이스를 제공한다. |
입출력 관리 | 필요한 입력과 출력 서비스를 제공한다. |
프로세스 간 통신 관리 | 공동 작업을 위한 각 프로세스 간 통신 환경을 지원한다. |
근데 조금 궁금한게 생겼어요~ 예를 잠깐 들어볼게요!
A 프로세스가 명령어를 잘 수행하고 있는데 갑자기! "ifs.open("a.txt")" 라는 명령어를 딱 만난 거에요~
그러면 A 프로세스는 당황하면서 운영체제한테 말해요~
"어?? 이거 뭐지..? 디스크에서 값을 빼와야하는데 나 못하는데?? 운영체제야! 너가 이거 수행할 수 있지않아? 너가 해"
했는데 지금 CPU가 A 프로세스를 처리하고 있는 유저모드잖아요~ 커널모드로 전환해야하는데 모드를 바꿨다는 어떠한 표시를 해야하지 않을까요?!
그래서 똑똑한 조상들이 컴퓨터 시스템 CPU 내부에 "모드 비트"라는 것을 두었답니다~
위의 그림을 보세요 ~
모드비트가 0이면 커널모드로서 모든 명령을 수행할 수 있고, 모드 비트가 1로 세팅되어 있으면 사용자 모드로서 제한된 명령만을 수행할 수 잇는거죠. 즉, 운영체제가 CPU를 점유해서 코드를 수행하다가 작업이 끝나면 모드비트를 1로 세팅해서 CPU의 제어권을 넘기는 겁니다~
(저기 위에서 trap이라는 용어는 인터럽트의 일종인데 곧 배우게 되실겁니다! )
근데 위의 그림에서 "calls system call" 이라고 쓰여진거 보이시나요??
"시스템 콜"이라는건데 운영 체제의 커널이 제공하는 서비스에 대해, 응용 프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스에요!
조금 더 간단하게 이해시켜드리자면!
여러분들 커피 좋아하시죠??
여러분이 커피를 마시고 싶어서 스타벅스에 들어갔다고 가정해봅시다.
그리고 스타벅스 바를 폴짝 뛰어 넘어서 직접 원두넣고 원두갈아서 쿵짝쿵짝해서 투샷으로 뽑으시나요??
아니죠! 손님은 바에 들어갈 수도 없고 들어갈 필요도 없는거죠. 그냥 직원에게 "커피 주세요" 하고 요청하면 되는거에요.
여기서 여러분들은 유저모드이고 직원이 커널모드이고 "커피 주세요" 는 시스템 콜인거죠 ㅎㅎ
즉, 누군가에게 요청해서 작업의 결과만 받을 수 있게 모드의 전환이 필요할 때 쓰는 것이 시스템 콜인거에요!
자! 만약 A 프로세스가 디스크에 데이터를 넣고 싶대요. 그래서 A 프로세스가 커널이 제공하는 write() 함수를 사용해서 데이터를 넣어달라고 요청해요. 그러면 시스템콜이 돼서 유저모드에서 커널모드로 전환이 되고 운영체제가 CPU 제어권을 가지면서 데어터를 넣는 작업을 수행하는 거죠.
응용 프로그램은 데이터가 디스크에 어떤 방식으로 저장되는지 알 수 없어요. 아까 위에서 예로 들었던 커피를 만들 때 손님은 직원이 어떤 방식으로 커피를 만드는지 알 수 없는것처럼요.
시스템 콜을 이용하면 커널이 데이터를 가져오거나 저장하는 것을 전적으로 책임지기 때문에 컴퓨터 자원을 관리하기 수월합니다!!
[아래 표는 시스템 콜의 종류들이에요. 이것보다 훨씬 많아요~ 암튼! 이런게 있다~ ]
1 | exit( ) | 현재 프로세스의 종료 | kernel/exit.c |
2 | fork( ) | 자식 프로세스의 생성 | arch/i385/kernel/process.c |
3 | read( ) | 파일 지정자로 부터 읽기 | fs/read_write.c |
4 | write( ) | 파일 지정자로 쓰기 | fs/read_write.c |
5 | open( ) | 파일이나 장치열기 | fs/open |
6 | close( ) | 파일 지정자 닫기 | fs/open.c |
7 | waitpid( ) | 프로세스의 종료를 기다린다 | kernel/exit.c |
8 | creat( ) | 파일이나 장치의 생성 | fs/open.c |
9 | link( ) | 파일을 위한 새로운 이름 만들기 | fs/namei.c |
10 | unlink( ) | 파일 혹은 참조된 이름을 삭제한다 | fs/namei.c |
11 | execv( ) | 프로그램의 실행 | arch/i386/kernel/process.c |
12 | chdir( ) | 작업디렉토리의 변경 | fs/open.c |
13 | time( ) | 초단위의 시간 얻기 | kernel/time.h |
14 | mknod( ) | 일반 혹은 특수파일의 생성 | fs/namei.c |
15 | chmod( ) | 파일의 권한 바구기 | fs/open.c |
16 | chown( ) | 파일의 소유자 변경 | fs/open.c |
자 이번 시간에는 커널 모드, 유저 모드 그리고 시스템 콜 까지 배워봤어요!
그리고 아까 서두에서 "인터럽트"까지 알고 가야한다고 말씀드렸어요 ㅎㅎ 그럼 다음주에 무엇을 포스팅할 지 느낌오시죠??
다음 시간에는 "인터럽트"에 대해서 한번 알아봅시다! 감사합니다:)
'남이 읽는 CS > 운영체제' 카테고리의 다른 글
[운영체제 8편] IPC란 무엇인가 (4) | 2022.04.13 |
---|---|
[운영체제 7편] 인터럽트가 무엇인가 (5) | 2022.04.04 |
[운영체제 5편] 데드락이 무엇인가 (4) | 2022.03.22 |
[운영체제 4편] 세마포어가 무엇인가 (5) | 2022.03.15 |
[운영체제 3편] 뮤텍스가 무엇인가 (3) | 2022.03.08 |
댓글