스레드(Thread)와 프로세스(Process)
이번 포스팅은 스레드와 프로세스에 대해 하겠습니다. 스레드는 영어로 Thread로 해석하면 실이나 가닥이라고 해석할 수 있습니다. 컴퓨터에서 동작하는 모습이 실과 같이 움직이기 때문에 붙여진 이름인 것 같습니다.
프로세스는 영어로 Process로 해석하면 과정이라고 해석이 됩니다. 대부분 프로세스라는 말은 현재 실행하고 있는 프로그램이라는 의미로 해석하면 될 것 같습니다. 태스크(task)와 같은 뜻으로 사용되며 여러 프로그램을 병행하여 실행하는 다중 프로그래밍을 할 때 기본적인 프로그램의 단위입니다.
컴퓨터 프로그램 수행 시 프로세스 내부에 존재하는 수행 경로, 즉 일련의 실행 코드. 프로세스는 단순한 껍데기일 뿐, 실제 작업은 스레드가 담당합니다. 프로세스 생성 시 하나의 주 스레드가 생성되어 대부분의 작업을 처리하고 주 스레드가 종료되면 프로세스도 종료됩니다. 하나의 운영 체계에서 여러 개의 프로세스가 동시에 실행되는 환경이 멀티태스킹이고, 하나의 프로세스 내에서 다수의 스레드가 동시에 수행되는 것이 멀티스레딩 입니다. 나무 데이터 구조(tree data structure)에서 상위 노드의 식별과 나무 내의 정보 탐색을 촉진하는 포인터입니다.
프로세스(Process)
과정, 프로세스라고 설명할 수 있습니다. 프로그램이라고 설명하면 잘 맞아 떨어집니다. 여러 분야에서 과정 또는 처리라는 뜻으로 사용되는 용어입니다. 또한 컴퓨터 분야에서는 ‘실행중인 프로그램’이라는 뜻으로 쓰입니다. 1960년대 중반 멀틱스 시스템을 설계한 벨전화연구소의 연구원들이 처음 사용했다고 알려져 있습니다. 프로그램 또는 그 일부를 뜻하기도 하고, 데이터의 입력이나 출력 등을 조작하거나 처리하는 것을 말하기도 합니다.
부모프로세스(parent process)라는 상위계층과 자식프로세스(child process)라는 하위계층이 존재합니다. 부모프로세스는 프로그램이나 명령어에 의해 시작되며, 자식프로세스는 부모프로세스에 의해 만들어지는 것을 말합니다. 하나의 부모프로세스는 여러 개의 자식프로세스를 관리하는데, 여러 개의 자식프로세스가 하나의 CPU에서 동시에 처리되는 것처럼 보이는 것을 멀티태스킹(multitasking)이라고 합니다.
리엔지니어링에서는 과업이 아닌 연속적 업무의 묶음을 말합니다. 예를 들어 주문프로세스는 소비자의 주문이 접수되는 단계에서 주문 품목이 소비자에게 전달되기까지의 모든 과정을 의미합니다. ISO9000시리즈 개정2000판에서는 ‘입력을 출력으로 변환시키는, 상호관련 되거나 상호작용하는 활동의 집합’이라고 정의하였습니다.
스레드의 기본개념
스레드 개념을 소개하기 전에 프로세스의 개념에 대해 알아야 합니다. 윈도우 운영체제를 제외한 대부분의 운영체제에서 프로세스 CPU 시간을 할당 받아 실행 중인 프로그램을 말합니다. 프로그램이 저장장치에 파일로 존재하는 정적인 개념인 데 반해, 프로세스는 코드(CPU 명령), 데이터, 리소스를 파일에서 읽어들여 작업을 수행하는 동적인 개념입니다.
반면, 윈도우 운영체제에서는 일반적인 의미의 프로세스 개념을 프로세스와 스레드 두 개로 구분하고 있습니다. 프로세스(Process)는 코드, 데이터, 리소스를 파일에서 읽어들여 윈도우 운영체제가 할당해놓은 메모리 영역에 담고 있는 일종의 컨테이너로, 정적인 개념입니다.
스레드는 CPU 시간을 할당받아 프로세스 메모리 영역에 있는 코드를 수행하고 데이터를 사용하는 동적인 개념이다. 요약하면, 일반 운영체제의 프로세스 = 윈도우 운영체제의 프로세스 + 스레드라고 보면 됩니다.
윈도우 응용 프로그램이 CPU 시간을 할당 받아 실행하려면 스레드가 최소 하나 이상 필요합니다. 응용프로그램 실행 시 최초로 생성되는 스레드를 주스레드(Primary thread)또는 메인 스레드(main thread)라고 하며 Winmain()또는 main()에서 실행을 시작합니다.
만약 응용프로그램에서 주 스레드와 별도로 동시에 수행하고자 하는 작업이 있다면, 스레드를 추가로 생성해 이 스레드가 해당 작업을 수행하게 하면 됩니다. 많은 윈도우 응용 프로그램이 이렇게 구현되어 있는데, 이를 멀티스레드 응용프로그램(multithreaded application)이라고 합니다. 대부분의 응용프로그램은 멀티스레드 응용프로그램이라고 보면 됩니다.
멀티스레드를 활용하면 사용자는 프로그램 하나가 동시에 여러 작업을 수행하는 것처럼 느끼게 됩니다. 이것은 CPU 동작과도 관련이 있습니다. 물리적인 CPU 개수는 한정되어 있는데 운영체제는 어떤 원리로 수많은 스레드가 동시에 실행되는 것과 같은 효과를 만들어 낼까? CPU가 하나 뿐이고 스레드는 두 개라고 생각해보고 알려드리겠습니다.
CPU는 하나이기 때문에 동시에 2개의 스레드를 실행할 수 없습니다. 하지만 한 개씩 번갈아가면서 실행하는 것은 가능합니다. 동시에 하는 것이 아니기 때문입니다. 또한 이렇게 교대로 실행하는 시간의 간격이 짧다면 사용자는 두 스레드가 동시에 실행되는 것처럼 느낄 것입니다.
하지만 이렇게 하기 위해서는 컴퓨터 안에서도 많은 작업이 필요합니다. 두 개의 스레드를 동시에 돌리기 위해서 하나의 스레드의 작업을 저장하고 다음 스레드로 넘어갔다가 다시 스레드의 작업을 저장하고 불러오는 작업을 반복해야 합니다.
이러한 스레드의 작업 상태는 CPU와 메모리 상태를 말하며, 구체적으로는 CPU 레지스터 값과 메모리의 스택을 말합니다. 하드웨어와 소프트웨어의 협동으로 이루어지는 스레드 실행상태의 저장과 복원 작업을 컨텍스트 전환(Context Switching)이라고 이야기합니다. 이러한 컨텍스트 전환을 통해 스레드들은 다른 스레드에 관계없이 상태를 유지하며 CPU를 나눠 쓸 수 있습니다.
응용프로그램 스레드 확인
Windows 작업 관리자에서 응용프로그램의 스레드 개수를 확인할 수 있습니다. ctrl + alt + del키를 이용하거나 시작메뉴에서 오른쪽 마우스를 눌러서 윈도우 작업관리자를 실행할 수 있습니다. 윈도우 작업 관리자를 실행하면 프로세스 탭에서 보기 → 열선택 메뉴를 선택합니다. 열 선택 대화상자에서 스레드를 선택하고 확인을 누르면 프로세스 목록에 이제 스레드 개수가 표시되는 것을 볼 수 있습니다. 대부분의 응용프로그램들이 하나 이상의 스레드를 사용하고 있는 것을 볼 수 있습니다.
스레드의 생성과 종료
스레드의 개념을 실제 응용프로그램에 활용하기 위해서 윈도우 운영체제가 제공하는 함수를 통해 스레드를 만들 수 있습니다. 윈도우에서 제공하는 함수는 윈도우 API입니다. 윈도우 자체에서 제공하는 함수로 스레드 생성 API도 따로 있습니다.
윈도우에서 스레드를 생성할 때는 CreateThread() API 함수를 사용합니다. CreateThread() 함수는 스레드를 생성한 후 스레드 핸들(Thread Handle)을 리턴합니다. 스레드 핸들은 파일 디스크립터나 소켓 디스크립터와 비슷한 개념입니다. 운영체제의 스레드 관련 데이터 구조체를 간접적으로 참조하는 매개체 역할을 합니다. 응용프로그램은 스레드 핸들을 윈도우 API함수에 전달함으로 다양한 방식으로 스레드를 제어할 수 있습니다.
CreateThread 함수
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
CreateThread() 함수는 다음과 같은 파라미터를 가지고 있습니다. lpThreadAttributes에는 SECURITY_ATTRIBUTES 구조체를 통해 핸들 상속과 보안 디스크립터 정보를 전달합니다. NULL값을 사용하면 됩니다.
dwStackSize는 스레드에 할당되는 스택 크기입니다. 0을 사용하면 실행 파일의 헤더에 들어 있는 기본 크기를 사용하는데 비주얼 C++로 만드는 응용프로그램의 기본크기는 1MB입니다.
lpStartAddress는 스레드 함수의 시작주소입니다.
lpParameter는 스레드 함수에 전달할 인자입니다. void형 포인터이므로 포인터 크기보다 작거나 같은 데이터 값 또는 주소 형태로 전달하면 됩니다. 전달할 인자가 없으면 NULL값을 사용하면 됩니다.
dwCreationFlags는 스레드 생성을 제어하는 값입니다. 0또는 CREATE_SUSPENDED를 사용합니다. 0을 사용하면 스레드는 생성 후 곧바로 실행되고 CREATE_SUSPENDED를 사용하면 스레드가 생성되지만 정지되어 있는 상태로 만들어지며 ResumeThread()함수를 호출해야 다시 실행됩니다.
lpThreadid는 DWORD형 변수를 전달하면 여기에 스레드 ID가 저장됩니다. 스레드 ID가 필요없으면 NULL값을 사용해도 됩니다.
'IT' 카테고리의 다른 글
기계명령어의 특성 (0) | 2017.09.03 |
---|---|
컴퓨터의 역사에 대해 (0) | 2017.08.30 |
인공지능 스피커 및 종류에 대해 (2) | 2017.08.28 |
소켓과 윈도우 소켓에 대해 (0) | 2017.08.27 |
VR과 AR의 개념과 적용사례 (0) | 2017.08.25 |
댓글