[전산학] 프로세스/시스템콜/인터럽트

Hyo Kyun Lee·2021년 6월 13일
1

전산학

목록 보기
1/16

1. 프로세스

프로세스의 정의

프로세스는 실행작업의 단위적 요소로 정의할 수 있습니다. 어떤 응용프로그램이 실행될때 여러 프로세스가 실행되는 경우나 우리가 하나의 코드를 작성하고 실행할 때까지 모든 실행경우가 포함이 가능합니다.

프로세스의 구조적 이해

하나의 코드를 작성하여 실행을 한다고 가정해보겠습니다. 코드는 컴파일되어 실행파일이 생성되고 사용자는 shell을 통해 운영체제에게 생성된 실행파일을 실행하도록 요청하게 됩니다. 이때 실행파일이 동작하면서 컴퓨터내 위와 같은 stack/heap/data/text(code) 구조가 생성되며, 실제 할당되는 주소(0~max)는 물리적인 메모리주소가 아닌, 가상메모리 주소입니다. 프로세스 상태표시를 위한 stack pointer / program counter에 사용됩니다.

(1) TEXT (CODE) Segment
사용자가 작성한 코드가 text(code)에 저장되는 영역입니다. 가상메모리주소가 코드 한줄한줄마다 할당이 되어 PCB의 SP(Stack Pointer, Stack에 할당되어 실행중인 최상위 코드의 다음 메모리가 할당되어 저장, 쉽게 말하면 코드의 함수 및 기능적 구분을 저장하기위한 공간) 및 PC(Program Counter, 현재 실행중인 코드의 가상메모리 주소를 저장하는 공간) 레지스터와 함께 코드 실행시 사용되는 중요한 공간이 됩니다.

(2) DATA Segment
코드내 함수외 영역에 선언된 전역변수나 상수 등 정적변수가 저장되는 영역입니다. 이미 정해진 크기의 메모리가 존재하여, 그 정해진 크기만큼의 변수가 저장되는 공간입니다. 초기화된 상태가 아닐 경우엔 BSS, 초기화된 상태라면 DATA영역에 저장됩니다.

(3) HEAP Segment
코드내 동적할당이 필요할 경우 사용되는 동적메모리 공간입니다. 예를 들어 C언어 malloc() 함수의 경우 int data로 포인터가 선언이 되어 이 포인터가 주소값을 가리키게 됩니다(포인터는 stack 공간에 있습니다). 이때 다음 로직에서 data = (int) malloc(sizeof(int))와 같이 정적변수가 선언되지 않은 상태에서, 이후 선언된 변수만큼의 메모리가 할당되는 동적인 경우가 생겼을때 HEAP공간에 이 data가 저장되어 동적할당을 기다리게 됩니다. 이후 변수가 선언될때 HEAP공간에 값이 저장되고, data는 포인터로 해당 HEAP주소값을 가리키고 있어 이에 대한 값할당이 가능해집니다.

(4) STACK Segment
TEXT영역내 코드 및 코드내 함수가 한줄한줄 실행이 될때 로직들이 할당되어 임시로 저장되는 영역입니다. main 함수에 대한 return address를 시작으로 함수가 실행될 경우엔 함수인자 및 내부적인 지역변수가 Stack에 할당되어 저장이 됩니다. 함수실행이 완료되었을 때 저장되었던 return address 및 인자들은 모두 삭제되는 공간입니다.

프로세스 상태

(1) new 실행될 프로세스가 신규 생성된 상태
(2) ready TEXT(CODE)구조에 실행코드 및 로직이 할당되어 프로세스의 실행준비가 완료된 상태
(3) run PCB의 PC/SP 레지스터에 프로세스 상태변수가 할당되면서 프로세스가 실행중인 상태
(4) wait(block) 시스템 콜 등 커널모드 전환 및 세마포어의 busy waiting 등 프로세스내 함수 및 다음 로직 실행이 보류된 상태, 혹은 현재 로직상태에서 다른 주요 동작처리를 위한 대기상태
(5) terminated 한 프로세스의 실행이 완전히 종료되어 stack의 모든 변수나 할당이 제거된 상태

2. 시스템콜

시스템 콜의 정의

운영체제는 사용자가 원하는 동작을 해주는 전반을 관리하여, 말 그대로 컴퓨터의 운영을 위한 관리자의 역할을 하고 있습니다. 이 관리의 역할 중 하나는 응용프로그램이나 여러 프로세스의 실행시 필요로 하는 자원들을 빌려주고 통제하는 것입니다. 이때 응용프로그램이나 프로세스들이 시스템 자원을 필요로 하여 접근하고자 할때, 운영체제에 요청하는 과정, 혹은 그 요청을 시스템 콜이라 합니다.

시스템콜의 역할

위 시스템콜의 정의처럼 시스템 자원의 접근이 필요할때 이루어지는 요청입니다.
위 요청에 대한 전반적인 관리를 하여 적재적소에 메모리 허가 및 분배, 이를 통한 시스템 자원이 사용될 수 있도록 합니다.
여러 응용프로그램이 동시적으로 시스템자원을 함부로 사용하지 못하도록 관리합니다.
시스템콜 요청시 CPU는 커널모드로 전환되며, 이는 사용자가 일반적인 프로세스 실행을 요청하는 경우와는 다른 형태에서 진행을 합니다. 하나의 프로세스 진행을 block하고 진행이 될 만큼 운영체제의 관리와 집중을 더 필요로 하는 모드이며, 이는 시스템콜이 시스템 자원 관리를 넘어 사용자 관리 측면에서도 이루어진다는 것을 의미합니다.'

시스템콜의 형태

사용자가 시스템콜을 사용하기 위해 시스템 콜이 포함된 코드를 작성한다고 해보겠습니다.

먼저 사용자는 운영체제가 제공하는 shell을 통해 각 언어별 API로 1차적인 요청서를 작성하게 됩니다. 이때 요청서는 API, 혹은 언어별 헤더파일이나 라이브러리에 저장되어 이용하는 형태가 되겠습니다. 이후 컴파일링 하여 코드 실행간 해당 요청을 운영체제가 받아오는데, 1차적인 요청서를 기계어로 번역하여 운영체제와 CPU가 시스템콜 요청을 수행하는 단계가 진행됩니다.

코드예시

C언어에서 사용자가 저장매체에 접근하여 파일을 읽어야 하는데, 이는 시스템콜을 통해 이루어지는 단계이므로 시스템콜 라이브러리 및 해당 코드를 작성합니다.
1. #include(unstd.h) > open함수(시스템콜)을 작성하기 위한 C언어 라이브러리 사용
2. int fd;
3. fd = open(“data.txt”.O_RDONLY); > 파일을 읽기위한 시스템콜 요청

시스템콜 호출시 이용되는 eax/ebx/요청주소

사용자는 보통 시스템콜 번호(eax)/시스템콜 인자(ebx)/ 인터럽트 시스템콜 요청주소(0x80) 의 형태로 요청을 하게 됩니다. 이때 CPU는 해당 요청주소로 가서 eax에 매핑되는 시스템콜을 불러오게 됩니다. 시스템콜 요청시 별도의 interrupt를 발생을 해줘야 하며, 이는 CPU OPcode를 통해 구현합니다.

3. 인터럽트

인터럽트 개요


우리가 여러 응용프로그램을 실행하거나 문서작업을 하면서 컴퓨터내 다른 장치에서 이상이 발생할 경우, 혹은 코드내 시스템콜 요청으로 block 상태가 된 프로세스가 다시 ready 및 run state가 되어야 하는 경우 등이 있습니다. 중요한 것은 CPU는 현재 할당된 코드를 실행하는데만 집중한다는 점으로, 위와 같은 상황이 발생하였을때 CPU에게 인지를 시켜줘야 합니다. 이때 인터럽트를 통해 인지를 시켜주게 됩니다.

인터럽트의 정의

입출력 장치 및 키보드 등 하드웨어 장치에서 예외상황이 발생하거나, block state된 프로세스가 ready state로 전환하면서 이벤트를 발생할 때 CPU에게 알려주어 이를 처리하도록 하는 기술을 일컫습니다.

인터럽트의 종류(내부/외부 인터럽트)

소프트웨어 인터럽트(내부 인터럽트) : 말 그대로 프로그램 내부에서 발생하는 인터럽트로, 일반적으로 잘못된 명령 및 데이터 사용시 발생하는 경우를 일컫습니다.
-C언어 포인터가 잘못된 데이터 주소를 접근하거나, 사용자 모드에서 포인터가 커널 모드의 주소를 가리킬 때
-비허용 명령을 사용하거나 참조되지 않은 명령을 참조할때
-계산결과가 overflow를 발생하여 해당 결과를 표현할 공간이 부족할 때

하드웨어 인터럽트(외부 인터럽트) : 외부적인, 주로 하드웨어 부분에서 이상점이 나타났을때 발생하는 경우를 일컫습니다.
-전원이상, Timer 이벤트, 입출력 장치 이상, 저장매체 이상 등

인터럽트의 메커니즘

[처리주체]
기본적으로 CPU는 코드를 실행하기만 할 뿐 이에 대한 예외사항이나 오류 발생시 처리할 수 있는 능력이 없습니다. 따라서 운영체제가 이를 인지하고 프로세스를 종료하거나 중단하는 등의 조치가 필요한데, 다시 말해 인터럽트를 처리하는 주체는 운영체제입니다.
[IDT]
인터럽트가 발생할 경우 해당 인터럽트 및 이벤트에 맞게 운영체제가 처리하게 됩니다. 따라서 운영체제는 인터럽트마다 어떤 종류가 있고, 어떤 방식으로 처리해야하는지를 기록한 영역이 있는데, 이를 IDT(Interrupt Descriptor Table)이라 합니다.
보통 이벤트 번호와 실행코드 주소로 이루어져 있으며, 부팅시 운영체제가 이를 생성합니다. 사용자가 인터럽트를 발생시킬 경우엔 CPU OPcode를 통해 interrupt를 발생하며 이를 통해 처리하고자 하는 시스템콜 및 커널모드 함수 등 해당 주소를 입력하여 처리할 수 있도록 합니다.
[처리 메커니즘(이해를 위해 시스템콜이 처리될 때까지의 경우를 기재하였습니다)]
인터럽트 발생시 운영체제는 IDT를 확인합니다.
예를 들어 시스템콜 인터럽트 발생시 int 0x80 의 명령어를 참조하여, 인터럽트를 발생하고 해당 주소로 이동하여 시스템콜 함수를 참조합니다.
0x80 시스템콜 함수 주소를 찾아가, 시스템 콜 번호(eax)와 매핑된 시스템 콜 함수를 찾아 실행합니다.
시스템콜 처리후 인터럽트를 발생하여 해당 프로세스 block 처리 등, 운영체제는 CPU를 사용자모드로 전환하여 인터럽트 및 커널모드 처리를 완료합니다.
[인터럽트 번호]
리눅스의 경우 0~3이 예외사항, 32~47이 HW인터럽트, 128이 시스템콜로 정의되어 있습니다.

4. 참조링크

https://m.blog.naver.com/dilector/221786020526

5. remind

Not sugar syntax but sugar logic!

0개의 댓글