반응형

프로세스는 실행 중인 프로그램 ( 특정 매체에 저장된 오브젝트 코드) 입니다.

또한 프로세스는 사용중인 파일, 대기 중인 스그널, 커널 내부 데이터, 프로세서 상태, 하나 이상의 물리적 메모리 영역이 할 당 된 메모리 주소공간, 실행 중인 하나 이상의 스레드 정보등 ... 모든 자원을 포함 하는 개념입니다.

다시말해... 프로세스는 프로그램 코드를 실행하면서 생기는 무든 결과물이라고 할 수 있습니다.

 

스레드는 프로세스 내부에서 동작하는 객체입니다. 스레드는 프로그램 카운터와 프로세스 스택, 프로세스 레지스터를 갖고 있으며 커널은 프로세스가 아니라 각각의 스레드를 스케줄링합니다. 전통적인 유닉스 시스템에서는 프로세스가 하나의 스레드로 구성되지만 현대 시스템에서는 여러개의 스레드로 구성된 다중 스레드 프로그램을 볼수 있습니다. 또한 리눅스는 프로세스와 스레드를 구분하지 않으며 리눅스에 있어서는 스레드는 조금 특별한 형태의 프로세스입니다.

 

운영체제에서 프로세스는 가상 프로세서와 가상 메모리 라는 두가지의 가상환경을 제공합니다.

 

가상 프로세스는 실제로는 수백개의 프로세스가 프로세서(CPU)를 공유하는 상황일지라도 프로세스가 혼자 시스템을 사용하는 듯한 가상환경을 제공해줍니다.

가상 메모리는 프로세스가 시스템의 전체메모리를 혼자 차지하고 있는 것 처럼 메모리를 할당하고 관리할 수 있게 해준다.

 

스레드는 가상 프로세서를 할당 받지만, 가상 메모리는 공유합니다.

 

 

커널은  프로세스 목록을 테스크 리스트라고 부르는 환형 양방향 연결 리스트 형태로 저장한다. 각 항목은 <linux/sched.h>에 정의된 struct task_struct 형식으로 저장되어 있으며 프로세스 서술자라고 부르고 프로세스 서술자는 해당 프로세스와 관련된 모든 정보를 포함하고 있다.

 

 

task_struct 구조체는 객체 재용 및 캐시 컬러링 기능을 지원하는 슬랩 할당자(Slab Allocator)를 사용해 할당한다. 슬랩 할당자를 이용해 동적으로 프로세스 서술자를 만들기 때문에 thread_info라는 새로운 구조체를 스택 밑바닥이나 꼭대기에 두고 있다.

x86 시스템의 thread_info 구조체는 <asm/thread_info.h>에 다음과 같이 정의됩니다. 각 태스크의 thread_info 구조체는 프로세스 스택의 제일 끝부분에 할당이 되며 구조체의 task 포인터가 태스크의 실제 task_struct 구조체를 가르킵니다.

 

 

시스템은 고유한 프로세스 인식번호(PID)를 이용해 프로세스를 구별한다. PID는 보통 int형을 사용하고 PID의 최대 값은 32,768이며 4백만으로 상향 조정가능합니다.

 

프로세스 서술자의 state 항목은 현재 프로세스의 환경을 알려주고 시스템의 프로세스는 다섯가지 상태중에 하나에 있으며 각 상태값은 다음 다섯가지 플래그를 통해 표현 된다

 

1. TASK_RUNNING

프로세스가 실행 가능한 상태, 현재 실행 중이거나 실행되기 위해 실행되기 위해 실행 대기열에 있는 상태. 사용자 공간에서 실행된 프로세스는 이 상태만 가질수 있으며 커널 공간에서 실행 중인 프로세스도 이 상태에 속합니다.

2. TASK_INTERRUPTIBLE

프로세스가 특정 조건이 발생하기를 기다리며 쉬는 중이다(중단된 상태) 기다리는 조건이 발생하기를 기다리며 쉬는 중이고 기다리는 조건이 발생하면 커널의 프로세스의 상태를 TASK_RUNNING 상태로 바꾼다 프로세스가 시그널을 받은 경우 조건에 상관없이 실행 가능한 상태로 바꿉니다.

3. TASK_UNINTERRUPTIBLE

시그널을 받아도 실행가능상태로 바뀌지 않는 점을 빼면 TASK_INTERRUPTIBLE 상태와 같다. 이 상태는 기 다리는 조건이 금방 발생하는 경우에 사용되며 자주 사용되지는 않습니다.

4. __TASK_TRACED

디버거 등의 다른 프로세스가 ptrace를 통해 해당 프로세스를 추적하는 상태이다.

5. __TASK_STOPPED

프로세스 실행이 정지된 상태다 해당 테스크는 실행 중이지도 않고 실행가능한 상태도 아니다. 작업이 SIGSTOP, SGTSTP, SIGTTIN, SIGTTOU같은 시그널을 받은 경우 디버그 중에 시그널을 받은 경우에도 이상태가 된다.

 

 

 

커널 코드에서 프로세스의 상태를 바꿀 필요가 생기는 경우가 많이 발생한다. 이경우에는 다음의 함수를 사용하게 됩니다.

 

set_task_state(task, state); // 태스크 'task'의 상태를 'state' 상태로 설정

 

이 함수는 특정 태스크의 상태를 지정한 상태로 변경하며 필요한 경우, 메모리 보호 기능을 이용해 다른 프로세서와 작업 순서가 겹치는 것을 방해 한다.

 

이 함수의 동작은 아래와 같다.

task->state=state;

 

프로세스의 중요한 부분 중 하나는 실행 중인 프로그램 코드다. 프로그램이  시스템 호출을 하거나 예외 처리가 발생한 경우 프로그램은 커널 공간으로 진입하게되고 이런 상황을 커널은 '프로세스를 대신해 실행 중' 이거나 '커널이 프로세스 컨텍스트에 있다'라고 말한다. 커널이 작업을 끝내면 프로세스는 사용자 공간에서 실행르 계속한다.

 

시스템호출과 예외 처리기는 잘 정의된 커널 진입 인터페이스이며 프로 세스는 이 두가지 인터페이시를 통해 커널 공간으로 들어갈 수 있다.

 

 

반응형
반응형

리눅스 커널과 관련하여 본격적인 글을 쓰기 전에 커널에 관하여 간략하게 소개하는 시간을 갖고자 합니다. 사람들은 흔히 운영체제와 커널을 같은 개념으로 말하고는 하는데 어떤의미에서는 같기도 하고 틀리기도 합니다.

 

운영체제를 한 문장으로 정의하기는 매우 어렵지만 기술적인 관점에서 이야기 하자면 기본적인 사용과 관리를 담당하는 시스템의 일부분이라고 볼 수 있습니다. 여기에 커널, 디바이스 드라이버, 부트로더, 쉘 등이 포함이 되고 웹 브라우저 같은 어플리케이션은 포함이 되지 않습니다.

 

운영체제라는 큰 카테고리안에 커널이 포함이 되지만, 실제로 커널 소스코드를 다운 받게 되면 커널 소스코드안에 커널, 디바이스 드라이버, 파일시스템, 부트코드 등 대부분의 코드를 포함하고 있습니다. 다시 말해 커널을 운영체제라고도 볼 수 있는 셈입니다.

 

어찌보면 운영체제와 커널을 꼭 구분해야 되는게 의미없는 논쟁일 수 도 있겠습니다.

 

운영체제에서 가장 핵심적인 역활을 하는 부분은 커널입니다. 커널은 운영체제의 가장 안쪽에 위치해서 모든 핵심적인 역활을 수행하고 시스템의 다른 모든 부분의 기본적인 서비스를 제공하며 하드웨어를 관리하고 시스템의 자원을 분배하게 됩니다.

 

커널의 주된 구성요소로는

 

1. 인터럽트 서비스 요청을 처리하는 인터럽트 핸들러

2. 프로세서(CPU) 실행 시간을 여러 프로세스에 분배하는 스케줄러

3. 프로세스 주소공간을 관리하는 메모리 관리 시스템

4. 네트워크나 프로세스간 통신을 처리하는 시스템 서비스 등등등 을 말할 수 있습니다.

 

또한 보호 메모리 관리장치가 있는 최근 시스템에서 커널은 일반적인 사용자 애플리케이션과 다른 시스템 상태를 갖고 있습니다. 다른 상태란, 보호메모리 공간사용, 제약없는 하드웨어 접근이 가능하다는 의미로 이같은 시스템 상태와 메모리 공간을 커널 공간 (Kernel Space)라고 부릅니다. 이와 반대되는 사용자 어플리케이션은 사용자 공간(User Space)에서 실행이 됩니다. 사용자 공간은 특정 시스템 함수와 제한된 장비의 가용 자원만이 사용가능합니다.

반응형

+ Recent posts