본문 바로가기

Linux(Centos or RHEL)/RHEL 기초

프로세스?

1.1 멀티태스크

리눅스 커널은 멀티태스킹을 지원한다. 이를 이용하여 동시에 여러 프로세스를 동시에 실행하고, 교대로 시스템의 자원을 사용할 수 있게 합니다. 동시에 라고는 하지만, 일정 시점에 시스템에 탑재되어있는 CPU의 수 이상으로 프로세스를 실행하는 것은 불가능합니다.

 

1.2 프로세스란?

프로세스는 컴퓨터 내에서 실행중인 프로그램의 인스턴스입니다. 하지만  프로세스가 실행 중인 프로그램 코드만을 뜻하는 것은 아닙니다. 조금 더 구체적으로 설명하면 사용 중인 파일, 대기 중인 시그널, 커널 내부 데이터, 프로세서 상태, 하나 이상의 물리적 메모리 영역이 할당된 메모리 주소 공간, 실행중인 하나 이상의 스레드 정보, 전역 데이터가 저장된 데이터 부분 등 모든 자원을 포함 하는 개념입니다. 따라서 다시 간단히 설명하면 프로그램 코드를 실행하면서 생기는 모든 결과물이라 할 수 있습니다. (리눅스 커널 심층 분석 개정 3판 - 로버트 러브 -)

프로세스는 몇몇 운영체계에서 사용되는 태스크라는 용어와 의미상 가깝습니다. 리눅스의 ps명령어로 프로세스들의 리스트를 확인하는 것이 가능합니다.

 

[root@localhost ~]# ps

PID TTY TIME CMD

18870 pts/1 00:00:00 bash

18890 pts/1 00:00:00 ps

[root@localhost ~]#

 

그림1.1 task_struct  구조체의  sibling  필드로 연결된 프로세스 리스트

http://egloos.zum.com/rousalome/v/9990377

 

 

각각의 프로세스는 고유의 컨텍스트를 가집니다. 컨텍스트는 그 프로세스가 동작하기 위해 필수로 필요한 메모리영역, 레지스터의 값(CS, EIP 등등)의 리소스들을 총칭하는 것입니다. 이러한 정보는 프로세스의 task_struct 구조체 (task_t 타입)로 관리됩니다. 리눅스 커널이 프로세스를 조작할 때는 이 구조체를 조작하는 것이 됩니다.

 

 

그림1.2 task_struct 구조체

https://myaut.github.io/dtrace-stap-book/kernel/proc.html

 

또한, 리눅스커널에서는 스레드도 일종의 프로세스로써 관리됩니다. 스레드들이 같은 프로세스공간을 공유하고 있는 것을 제외하면, 보통의 프로세스와 같습니다. 각 스레드에도 task_struct 구조체가 할당됩니다. 프로세스 스케줄링을 할 때에도 스레드와 프로세스를 똑같이 취급합니다.

task_struct구조체의 정의는 “include/linux/sched.h”에 정의되어 있습니다.

구조체 소스코드 : [https://elixir.bootlin.com/linux/v2.6.39.4/source/include/linux/sched.h#L1193]

task_struct 구조체 설명 : [http://blog.naver.com/PostView.nhn?blogId=ryutuna&logNo=100176137806]

 

 

1.3 프로세스의 상태

프로세스를 효율적으로 관리하기 위해서 커널은 프로세스에게 프로세스 상태를 부여합니다.

커널에서 정의한 프로세스 상태는 다음과 같습니다.

 

프로세스 상태 정의 : [https://elixir.bootlin.com/linux/v2.6.39.4/source/include/linux/sched.h#L172]

/*

* Task state bitmask. NOTE! These bits are also

* encoded in fs/proc/array.c: get_task_state().

*

* We have two separate sets of flags: task->state

* is about runnability, while task->exit_state are

* about the task exiting. Confusing, but this way

* modifying one set can't modify the other one by

* mistake.

*/

#define TASK_RUNNING 0

#define TASK_INTERRUPTIBLE 1

#define TASK_UNINTERRUPTIBLE 2

#define __TASK_STOPPED 4

#define __TASK_TRACED 8

/* in tsk->exit_state */

#define EXIT_ZOMBIE 16

#define EXIT_DEAD 32

/* in tsk->state again */

#define TASK_DEAD 64

#define TASK_WAKEKILL 128

#define TASK_WAKING 256

#define TASK_STATE_MAX 512



#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW“

 

위와같이 여러 상태가 있지만 크게 분류를 하자면 3가지 상태가 있습니다. unrunnable, runnable, stoped3가지입니다. 커널은 프로세스의 상태를 task_struct 구조체의 state 변수에 저장합니다.

 

 

task_struct내의 state변수 : [https://elixir.bootlin.com/linux/v2.6.39.4/source/include/linux/sched.h#L1193]

struct task_struct {

volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */

void *stack;

 

그중에서 프로세스의 스케줄링에 관련되는 0, 1, 2의 상태에 대해서 알아보겠습니다.

 

 

프로세스의 상태는 다음 프로세스 상태 다이어그램으로 표현이 가능합니다.

 

그림1.3 프로세스 상태 그림(http://egloos.zum.com/rousalome/v/9990651)

 

 

 

다음 테이블에서 위 프로세스 상태를 확인할 수 있습니다.

 

(http://egloos.zum.com/rousalome/v/9990651)

자세한 것은 아래 링크를 보시기 바랍니다... 정말 정리를 잘 해 놓은 블로그입니다.

http://egloos.zum.com/rousalome/v/9990651