CS/Linux / / 2020. 12. 30. 01:05

Linux Kernel - Introduction

 

kernel, shell, utility를 구분할 수 있냐?
리눅스 OS를 맨 처음 부팅을 하면 kernel a.out이 메모리에 올라간다. (kernel은 항상
메모리에 올라가 있다) 그리고 유저가 터미널을 키면 메모리에 shell a.out이 올라간다. 그런 shell은 키보드에서
command가 입력되기를 기다리고, command가 입력되면 shell은 해당 명령에
대응되는 utility app(disk resident program)을 disk로부터 가져와서 execute. utility는 필요할 때만 메모리에
올라가고 run하고 내려간다. 그리고 utility가 메모리에 언제 올라가고 내려가는지를
서비스하는 게 shell의 roll이다.

 

Linux: Multi_User <--> Windows: Single_User
Multi_User System은 자원을 최대한 효율적으로 아껴서 사용해야 하는 반면,
Single_User System은 사용자가 한 명밖에 없다고 가정한 시스템이므로 상대적으로
그런 고려를 덜하게 된다.
그래서 Linux는 CUI(Character_User_Interface)인 반면, Windows는 GUI로 그 역사를
시작한다.

 

Linux에서 자원을 어떻게 관리할 것인가?

Linux는 Multi_User System이라서 다른 User가 내 정보에 접근할 가능성이 있다
사후 예방은 절대 있을 수 없고 무조건 '사전에 prevent' 해야한다.
쉽게 말하면 하나의 Application이 자신에게 허용된 메모리 공간이 아닌 곳을
read/write 하는 상황을 사전에 어떻게 방지할 것인가? CPU의 자원은 하나이므로
특정 시점에는 분명히 하나의 Application에 CPU의 자원을 줄 터인데, 그 시점에
그 Application Process가 다른 메모리 공간에 write나 read를 하면 어떡하지?
이런 상황을 방지하기 위해 Process가 IO를 할일이 생기면 Process에게 IO 권한을
주지 말고, IO Instruction이 할 일이 생기면 Kernel이 가지고 있는 Function을
Call해서 IO를 의뢰하자. 이 행위를 System Call이라고 한다.

이런 System Call을 도와주기 위해서, Windows같은 Personel Computer에는 없는 개념인
1비트짜리 MODE_BIT<KERNEL_MODE VS USER_MODE>를 CPU에 도입한다. MODE_BIT가
KERNEL_MODE이면 CPU는 어떠한 메모리 영역도 Access할 수 있지만 MODE_BIT가 USER_MODE로
Set이 되어있으면 My Address Space만 Access할 수 있게 하는 게 기본 아이디어이다. 또한,
Instruction의 경우에도 KERNEL_MODE의 경우에는 어떠한 Instruction도 수행가능 하지만,
USER_MODE의 경우에는 IO Instruction같은 특수 Instruction은 수행 불가능하게 한다.
CPU의 기본 동작 방식은 다음과 같다

1) CPU의 Program Couter라는 특수 레지스터가 메모리에게 이번에 수행되어야 할 Instruction의
주소를 메모리에게 보낸다.
2) 그럼 메모리에서는 해당 주소의 명령을 다시 CPU의 Instruction Register라는 레지스터에게
그 명령을 전달한다.
3) 그럼 그 Instruction에는 operation-code(연산 종류)와 operands(피연산자)를 해석해서
CPU의 ALU(Arithmetic Logic Unit: 제어 장치의 지시에 따라 산술, 논리, 비트 연산등의 실제 연산을 수행하는 장치)에서
Instruction을 실행한다.

CPU MODE Memory Operand Code
KERNEL_MODE Access Any(all) Execute Any(all)
USER_MODE Mine Only(local) Restricted*

Preveliged OP-Code: NO I/O Instruction, No special register access(Stack pointer나 Program Couter의 값을 읽거나 쓰는 행위 못함), 다른 시스템에 해를 끼치는 행위 그 어떠한 것도 허용되지 않는다.

**CPU Instruction 수행 과정

1) PC(Program Counter) to Memory: PC가 메모리에게 해당 주소의 Instruction 요청

2) Instruction Fetch: 명령어를 가져온다

3) Decode

4) Execute: ALU에게 OP를 보낸다.

5) 해당 명령 실행

1)에서 MODE_BIT가 USER_MODE이면 cpu로부터 메모리로 가는 Meomory Bus에서 Address를 검사해서, 해당 메모리 주소가 그 프로세스의 합당한
주소이면 계속 진행하지만 USER_MODE인데도 불구하고 접근하려는 메모리 주소가 범위를 벗어나면 CPU를 강탈해버린다. 반면, KERNEL_MODE이
면 보안검색을 당하지 않는다.
2), 3)에서도 USER_MODE인 경우, Instruction을 가져와, op-code를 확인해서 I/O같이 적절하지 않은 Instruction을 Execute를 할 일이 생기면 CPU를 사전에 강탈한다. 한 가지 추가하자면, OS Kernel이 실행중일 때는 MODE_BIT가 KERNEL_MODE인 반면 USER의 Program이 실행될 때는 MODE_BIT가 USER_MODE가 된다.

 

의문
하지만 여기서 의문이 들 수 있는 게, C로 프로그램 작성하면 당장에 printf나 scanf 같은 라이브러리 함수들 전부 I/O 함수인데 이런 건 USER Program 아니냐라고 생각할 수 있다. 이건 내가 작성한 source 내에서만 I/O처럼 보이는 것뿐 실제로 컴파일을 하면 I/O가 아니다. 만약 컴파일을 하고 나서도 User Progrma에 I/O가 있으면 CPU를 빼았겨 버린다. 즉, I/O를 하고 싶으면 Kernel이 가지고 있는 Function인 System Call을 Call해라. I/O Statement가 나올 때마다 Compiler가 해당 명령을 chmodk(Change MODE_BIT Kernel)로 바꾼다. 자, 좋다. user program에서 등장하는 I/O 명령을 compiler가 chmodk로 바꾸었다고 가정하자. 그런데 User Program에서 I/O 명령을 할 수 있게 여지를 두는 것 자체가 잘못된 거 아닌가? 맞다. I/O 명령을 compiler가 chmodk로 바꾸었다 하더라도 실행되면 권한이 없으므로 CPU를 빼았긴다. 그래서 더이상 CPU가 run할 수 없으므로 Trap(Interuppt)이 걸린다. 이 Trap Handler는 Kernel 안으로 들어간다. 하지만 Kernel도 어떤 명령 때문에 Trap이 걸린 건지 알아야 하므로 파라미터로 무엇을 I/O 하는지 같은 정보를 받는다. 이 행위를 System Call이라고 한다. Kernel로 왔다고 바로 I/O를 하는 게 아니라 Kernel은 해당 프로그램이 요청한 영역에 Read OR Write할 권한이 있는지 check하고 Read/Write를 진행한다. Read/Write가 끝나면 Trap으로 돌아가고 그리고 다시 해당 프로그램 내의 다음 명령으로 이동한다.  이런 방식으로 모든 프로그램은 USER_MODE로 실행되다가 KERNEL_MODE로 실행되다가 다시 USER_MODE로 실행되는 걸 반복한다.

 

 

'CS > Linux' 카테고리의 다른 글

Linux - Process Management  (0) 2021.01.30
Linux Kernel: System Call  (0) 2021.01.01
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유