[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 05. 프로세스의 생성과 소멸

2023. 9. 17. 14:52·독서/[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ]

01. 프로세스(process)의 이해

오늘날의 운영체제를 가리켜 “멀티 프로세스(Multi-Process) 운영체제”라고 부른다. 이는 “프로세스라는 것이 여러 개 존재할 수 있는 운영체제”라는 뜻이다. 그럼 여기에서 프로세스란 무엇을 의미할까?

 

프로세스란 무엇인가?

프로세스란 실행 중에 있는 프로그램을 의미한다. 예를 들어, 인터넷 접속을 위해서 인터넷 익스플로러를 실행시키고, 익스플로러를 둘 이상 띄워서 두 군데 이상의 웹 페이지에 접속했다고 가정해 보자.이때 익스플로러의 실행파일(iexplorer.exe)은 프로그램이고, 익스플로러 창은 프로세스가 된다. 따라서, 위 상황에서는 둘 이상의 프로세스를 생성한 것이 된다.

 

프로세스를 구성하는 요소

프로그램이 실행될 때 다음과 같은 메모리 공간이 구성된다.

1.     전역변수나 static 변수의 할당을 위해 존재하는 Data 영역

2.     지역변수 할당과 함수 호출 시 전달되는 인자값들의 저장을 위해 존재하는 Stack 영역

3.     동적 할당(malloc, calloc 함수에 의한 할당)을 위해 존재하는 Heap 영역

4.     실행파일을 구성하는 명령어들이 올라가는 메모리 영역인 Code 영역

 

이와 같은 메모리 구조는 실행되고 있는 프로세스 개수만큼 생성된다.

 

Register Set

프로세스를 구성하는 요소로는 CPU 내에 존재하는 레지스터들이다. 프로그램을 실행시키기 위해서는 레지스터들이 필요하다. 이는 Chapter 04에서 확인하였다.

예를 들어, CPU가 현자 A.exe 파일을 실행 중에 있다면, 레지스터들은 A.exe의 정보들로 채워지게 된다. 즉, 현재 실행 중인 프로그램의 정보로 채워지는 것이다. 따라서, 레지스터들의 상태까지도 프로세스의 일부로 포함시킬 수 있다. 이는 이후에 언급될 컨텍스트 스위칭 (Context Switching)을 이해하기 위한 바탕이 된다.


02. 프로세스의 스케줄링과 상태 변화

“CPU는 하나인데 어떻게 여러 개의 프로그램이 동시에 실행 가능한 것인가?”에 대해 생각해 보자.

 

프로세스의 스케줄링(Scheduling)

논리적으로, CPU는 하나인데, 실행되어야 할 프로세스는 여러 개다. 때문에, 하나의 CPU가 여러 개의 프로세스를 번갈아 가면서 실행해야 한다. 이때, CPU는 매우 빠르기 때문에 여러 프로세스를 고속으로 번갈아 가며 실행시켜도, 사용자는 동시에 여러 개의 프로그램을 실행시킨다고 느낀다.

결론적으로, 우리가 사용하는 멀티 프로세스 운영체제는 여러 개의 프로세스들이 CPU 할당 시간을 나눈다.

 

스케줄링의 기본 원리

위의 결론에서 우리가 고려해야 할 것은 프로세스들에게 CPU를 할당하는 기준이다. 이렇게 프로세스의 CPU 할당 순서 및 방법을 결정짓는 일을 스케줄링(Scheduling)이라 하며, 이때 사용되는 알고리즘을 스케줄링 알고리즘(Scheduling Algorithm)이라고 한다. 또한, 스케줄링 알고리즘을 적용해서 실제로 프로세스를 관리하는 운영체제 요소(모듈)를 가리켜 스케줄러(Scheduler)라 한다. 특히, 스케줄러는 운영체제를 구성하는 요소 중 하나로, 소프트웨어적으로 구현되어 있다.

멀티 프로세스와 CPU

멀티 프로세스 운영체제에서 프로세스들이 실행되는 형태를 크게 두 가지로 나눠서 생각할 수 있다.

실행해야 할 일을 순차적으로 실행시키는 것

정해진 순서(우선순위)를 두어 CPU의 실행시간을 나눠서 할당받아 실행하는 것

 

일반적으로, 프로그램이 실행되는 과정에서 많은 시간을 I/O(입력 및 출력)에 할당한다. 이때 I/O라 함은 데이터의 입력 및 출력을 말하는 것이다. 여기에는 서버로부터 웹 페이지를 전송받는 등의 인터넷 간의 데이터 입출력도 포함된다. CPU는 이러한 입력 및 출력 상태에는 아무 일도 하지 않고 대기하게 된다.

따라서, 위에 제시한 첫 번째 방식에서는 A가 I/O 관련 일을 하고 있다면, CPU는 쉬는 상태인 것이다. 이러한 낭비를 해결하기 위해 A 프로세스가 I/O에 관련된 일을 할 경우, 운영체제는 스케줄러를 통해 다른 프로세스가 실행되도록 스케줄링한다.

 

프로세스의 상태 변화

멀티 프로세스 운영체제에서는 여러 개의 프로세스들이 돌아가면서 실행되기 때문에, 프로세스 각각의 상태는 시간 흐름에 따라 변화한다.

상황 1: S(Start)에서 Ready 상태로의 전이를 보여준다.

여기서 S는 프로세스가 생성되었음을 의미한다. 프로세스는 생성과 동시에 Ready 상태로 들어간다. Ready 상태에 있는 프로세스는 CPU에 의해 실행되기를 희망하는 상태이다.

 

상황 2: Ready 상태에서 Running 상태로의 전이를 보여준다.

Ready 상태에 있는 프로세스들은 스케줄러에 의해 관리되는 프로세스들이다. 스케줄러는 Ready 상태에 있는 프로세스 중 하나를 선택해서 CPU에 의해 실행될 수 있도록 한다. 결론적으로, Ready 상태에 있는 프로세스 중 스케줄러에 의해 선택된 프로세스는 Running 상태가 된다.

 

상황 3: Running 상태에서 Ready 상태로의 전이를 보여준다.

프로세스마다 중요도에 따라 실행 순서를 달리하기 위해 우선순위라는 개념이 존재한다. 예를 들어, A의 우선순위가 B의 우선순위보다 높게 설정되어 있다고 가정하자. 그리고 현재 B가 실행 중이다. 이때 우선순위가 B보다 높은 A가 생성되어서 Ready 상태가 되었다. 이때, 스케줄러는 B의 실행을 멈추고, 우선순위가 높은 A를 실행시키게 된다. 또한, B는 Ready 상태가 된다. 이러한 상황을 정리해 보면 다음과 같다.

 

우선순위가 높은 프로세스가 실행(Running) 중일 경우, 우선순위가 낮은 프로세스는 실행되지 않는다.

 

현재 우선순위가 낮은 프로세스가 실행 중일지라도, 우선순위가 높은 프로세스가 실행될 경우, 우선순위가 낮은 프로세스는 Ready 상태로 들어가고, 우선순위가 높은 프로세스가 실행된다.

 

 

상황 4: Running 상태에서 Blocked 상태로의 전이를 보여준다.

실행 중에 있는 프로세스가 실행을 멈추는 상태(Blocked 상태)로 들어가는 것이다. 일반적으로 데이터 입출력에 관련된 일을 하는 경우에 발생한다. 앞에서 언급했듯이, 이 시간에는 CPU에 의해서 프로세스가 더 이상 실행될 수 없다. 따라서, Blocked 상태가 되게 하고, Ready 상태에 있는 프로세스를 실행시키는 것이 효율적이다.

위 그림을 보면, 프로세스 A가 파일 입출력 상황이라 Blocked 상태에 들어갔고, 이와 동시에 Ready 상태에 있는 프로세스 중 하나는 Running 상태가 될 것이다.

 

상황 5: Blocked 상태에서 Ready 상태로의 전이를 보여준다.

Ready 상태와 Blocked 상태의 가장 큰 차이점은 스케줄러에 의해 선택될 수 있는가?이다.상태는 스케줄러에 의해 선택되어 실행 가능한 상태이고, Blocked 상태는 스케줄러에 의해 선택될 수 없는 상태이다. 따라서, 입출력이 완료된 Blocked 상태에 있는 프로세스는 다시 Ready 상태가 되어 스케줄러의 선택을 기다려야 한다.

 

더 자세한 예시는 책 p.137의 프로세스의 상태 변화, 시나리오로 다시 이해하기 부분을 참고하자.


03. 컨텍스트 스위칭(Context Switching)

앞에서는 멀티 프로세스 운영체제의 기본 원리에 대해 이야기하였고, 어떠한 방식으로 CPU를 효율적으로 사용할 수 있는지에 대해 알아보았다. 하지만, 이렇게 실행 중인 프로세스(Running 상태)의 변경은 시스템에 많은 부하를 가져다주기도 한다. 앞서 언급했듯이, CPU 내부의 레지스터는 현재 실행 중인 프로세스 관련 데이터로 채워진다. 즉, Running 상태에 있는 프로세스와 Ready 상태에 있는 프로세스가 변경될 때마다 데이터의 저장 및 로드가 이루어지는 것이다.

위와 같은 작업을 가리켜 컨텍스트 스위칭(Context Switching)이라 한다. 이는 레지스터 개수가 많은 시스템일수록, 프로세스별로 관리되는 데이터 종류가 많을수록 부담되며, 멀티 프로세스 운영체제의 단점이다.

 

이처럼 프로세스와 관련해서, 두 가지를 동시에 고려해야만 한다. I/O 시간에 상태 변화를 이용하여 CPU를 좀 더 효율적으로 사용할 수 있지만, 반대로 이것이 컨텍스트 스위칭을 거치며 오히려 성능에 저하를 가져올 수 있다.


04. 프로세스의 생성

프로세스를 프로그래밍을 통해서 생성 및 소멸시켜 보자.

가장 기본적인 프로세스 생성은 실행파일을 더블클릭해서 독립적으로 실행하는 것이다. 그러나 시스템 프로그래머는 프로그램 실행 중에 또 하나의 프로세스 생성이 가능하다.

 

 "프로그램 실행 중에 또 하나의 프로세스 생성"

 

CreateProcess 함수의 이해

Windows에서는 프로세스 생성을 돕기 위해 CreateProcess 함수를 제공하고 있다. 이때, CreateProcess 함수를 호출하는 프로세스를 가리켜 부모 프로세스(Parent Process)라 하고, 함수 호출에 의해 생성된 프로세스를 자식 프로세스(Child Process)라 한다.

 

다음은 CreateProcess 함수의 선언 형태를 보여준다.

BOOL CreateProcess(
    LPCSTR lpApplicationName,
    LPSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCSTR lpCurrentDirectory,
    LPSTARTUPINFOA lpStartupInfo,
    LPPROCESS_INFORMATION lpProcessInformation
);
    //if the function fails, the return value is zero.

각 인자들의 설명은 다음과 같다.

더보기

lpApplicationName

생성할 프로세스의 실행파일 이름을 인자로 전달한다. 경로명을 추가로 지정 가능하며, 지정하지 않을 경우 프로그램의 현재 디렉터리에서 실행파일을 찾는다.

 

lpCommandLine

프로그램을 실행하면서 main 함수에 인자를 전달하듯이, 새로 생성하는 프로세스에 인자를 전달할 때 이 두 번째 매개변수를 사용한다. 또한, 첫 번째 전달인자에 NULL을 전달하고 두 번째 전달인자에 실행파일의 이름을 더불어 전달할 수 있다. 이 경우, 실행파일의 이름은 표준 검색경로를 기준으로 찾는다.

 

lpProcessAttributes

프로세스의 보안 속성을 지정할 때 지정할 때 사용하는 인자로서 보통은 NULL을 전달한다. 이 경우 Default 보안 속성이 지정된다.

 

lpThreadAttributes

쓰레드의 보안 속성을 지정할 때 사용한다. 보통은 NULL을 전달하며, 이 경우 Default 보안 속성이 지정된다.

 

bInheritHandles

TRUE 일 경우 생성되는 자식 프로세스는 부모 프로세스가 소유하는 핸들 중 일부를 상속한다.

 

dwCreationFlag

생성하는 프로세스의 특성(특히 우선순위)을 결정할 때 사용되는 옵션이다. 특별이 설정할 필요가 없을 경우에는 0을 전달한다.

 

lpEnvironment

프로세스마다 Environment Block이라는 메모리 블록을 관리한다. 이 블록을 통해서 프로세스가 실행에 필요하는 문자열을 저장할 수 있다.

이 전달인자는 프로세스의 Environment Block을 지정한다. NULL이 전달되면, 자식 프로세스는 부모 프로세스의 환경 블록에 저장되어 있는 문자열을 복사하게 된다.

 

lpCurrentDirectory

생성하는 프로세스의 현재 디렉터리를 설정하는 인자이다. 이는 디렉터리 정보를 포함하는 완전경로 형태로 구성되어야 하며, NULL이 전달될 경우 부모 프로세스의 현재 디렉터리로 설정된다. NULL이 일반적으로 전달된다.

 

lpStartupInfo

STARTUPINFO 구조체 변수를 초기화한 뒤, 이 변수의 포인터를 인자로 전달한다. STARTUPINFO 변수는 생성하는 프로세스의 속성을 지정할 때 사용된다.

 

lpProcessInformation

생성하는 프로세스 정보를 얻기 위해 사용되는 인자이다. PROCESS_INFORMATION 구조체 변수의 주소값을 인자로 전달한다. 그러면 전달된 주소값이 가리키는 변수에 프로세스 정보가 채워진다.

 

예제를 통한 CreateProcess 함수의 이해

다음 예제는 AdderProcess.exe 프로세스를 CreateProcess.exe 프로세스를 통해 생성하는 CreateProcess 함수의 이해를 돕기 위한 예제이다.

//AdderProcess.cpp 
//main 함수의 전달인자를 덧셈하는  프로그램

#include "stdio.h"
#include "tchar.h"
#include "windows.h"

int _tmain(int argc, TCHAR* argv[])
{
    DWORD val1, val2;
    val1 = _ttoi(argv[1]);
    val2 = _ttoi(argv[2]);

    _tprintf(_T("%d + %d = %d \n"), val1, val2, val1 + val2);
    
    _gettchar(); //프로그램의 실행을 잠시 멈추기 위해
    return 0;
}

 

다음은 _ttoi와 _gettchar 함수가 정의되어 있는 tchar.h 파일의 일부 내용이다.

#ifdef _UNICODE
#define _ttoi _wtoi
#define _gettchar getchar
#else
#define _ttoi atoi
#define _gettchar getchar
#endif

위에서 작성한 AdderProcess를 자식 프로세스로 생성하는 CreateProcess.cpp이다.

//CreateProcess.cpp
//덧셈 프로세스를 생성

#include "stdio.h"
#include "tchar.h"
#include "windows.h"

#define DIR_LEN MAX_PATH+1

int _tmain(int argc, TCHAR* argv[])
{
    STARTUPINFO si = { 0, };
    PROCESS_INFORMATION  pi;

    si.cb = sizeof(si);
    si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
    si.dwX = 100;
    si.dwY = 200;
    si.dwXSize = 300;
    si.dwYSize = 200;
    si.lpTitle = _T("I am a boy!");

    TCHAR command[] = _T("AdderProcess.exe 10 20");
    TCHAR cDir[DIR_LEN];
    BOOL state;

    GetCurrentDirectory(DIR_LEN, cDir); // 현재 디렉터리 확인
    _fputts(cDir, stdout);
    _fputts(_T("\n"), stdout);

    SetCurrentDirectory(_T("C:\\WinSystem"));

    GetCurrentDirectory(DIR_LEN, cDir); // 현재 디렉터리 확인
    _fputts(cDir, stdout);
    _fputts(_T("\n"), stdout);

    state = CreateProcess( // 프로세스 생성
        NULL,               // 실행파일의 이름
        command,            // main 함수에 전달될 문자열
        NULL, NULL, TRUE,
        CREATE_NEW_CONSOLE,
        NULL, NULL, &si, &pi
    );

    if (state != 0)
        _fputts(_T("Creation OK! \n"), stdout);
    else
        _fputts(_T("Creation Error! \n"), stdout);

    return 0;
}

프로세스 생성 1 단계: STARTUPINFO 구조체 변수의 생성 및 초기화

다음은 STARTUPINFO 구조체 선언이다. 위 예제에서 초기화한 멤버에 대해서만 주석을 작성했다.

typedef struct _STARTUPINFO
{
    DWORD cd;             // 구조체 변수의 크기
    LPTSTR lpReserved;
    LPTSTR lpDesktop;
    LPTSTR lpTitle;       // 콘솔 윈도우의 타이틀 바 제목
    DWORD dwX;            // 프로세스 윈도우의 x 좌표
    DWORD dwY;            // 프로세스 윈도우의 y 좌표
    DWORD dwXSize;        // 프로세스 윈도우의 가로 길이
    DWORD dwYSize;        // 프로세스 윈도우의 세로 길이
    DWORD dwXCountChars;
    DWORD dwYCountChars;
    DWORD dwFillAttribute;
    DWORD dwFlags;        // 설정된 멤버의 정보
    WORD sShowWindow;
    WORD cbReserved2;
    LPBYTE lpReserved2;
    HANDLE hStdInput;
    HANDLE hStdOutput;
    HANDLE hStdError;
} STARTUPINFO, * LPSTARTUPINFO;

 

프로세스 생성 2 단계: 현재 디렉터리의 설정

현재 디렉터리는 특정 파일을 찾을 경우에 기본이 되는 디렉터리이다. 만약에 완전경로를 전달하지 않고 파일을 생성 및 개방할 경우 현재 디렉터리를 기준으로 작업은 이뤄지게 된다.

일반적으로, 프로세스가 생성되면 프로세스의 현재 디렉터리는 프로세스의 실행파일이 존재하는 디렉터리로 설정된다. 실행 중에 있는 프로세스의 현재 디렉터리 위치는 다음 함수를 이용해 확인 가능하다.

DWORD GetCurrentDirectory(
    DWORD nBufferLength,
    LPSTR lpBuffer
);

위 함수의 두 번째 전달인자 lpBuffer는 현재 디렉터리 정보가 저장될 메모리 버퍼의 포인터이고, 첫 번째 전달인자 nBufferLength는 현재 디렉터리 정보가 저장될 버퍼의 크기로, 저장 가능한 문자열 길이 정보가 전달되어야 한다.

 

추가로, MAX_PATH 상수는 헤더파일 windef.h에 선언되어 있으며, Windows에서 허용하는 완전경로(Full Path)의 최대 길이를 알려준다. 또한, 다음의 함수를 이용해 프로세스의 현재 디렉터리를 변경할 수 있다.

BOOL SetCurrentDirectory(
    LPCSTR lpPathName
);

 

프로세스 생성 3 단계: CreateProcess 함수의 호출

CreateProcess 함수 호출 시, 주의해야할 점은 다음과 같은 형태의 호출은 불가능하다는 것이다.

CreateProcess( 				// 프로세스 생성
    NULL,				// 실행파일의 이름
    _T("AdderProcess.exe 10 20"),	// main 함수에 전달될 문자열
    NULL, NULL, TRUE,
    //중략
);

이는 함수 내부적으로 두 번째 인자로 전달된 문자열에 변경을 가하기 때문에 변수 형태여야 한다. 따라서 위와 같이 호출할 경우, 런 타임에 메모리 참조 오류가 발생한다.

또한, CreateProcess 함수의 첫 번째 전달인자를 통해서 실행파일 이름을 전달할 경우, 현재 디렉터리를 기준으로 실행파일을 찾지만, 두 번째 전달인자를 통해 이름을 전달할 경우, 아래의 표준 검색경로 순서대로 실행파일을 찾는다.

 

1 표준 검색경로: 실행 중인 프로세스의 실행파일이 존재하는 디렉터리

2 표준 검색경로: 실행 중인 프로세스의 현재 디렉터리

3 표준 검색경로: Windows의 시스템 디렉터리(System Directory)

4 표준 검색경로: Windows 디렉터리(Windows Directory)

5 표준 검색경로: 환경변수 PATH에 의해 지정되어 있는 디렉터리

 

위 표준 검색 경로에서 3, 4는 다음과 같은 예제를 통해 직접 확인 가능하다.

// WinSysDir.cpp
// 시스템 디렉터리와 Windows 디렉터리 확인

#include "stdio.h"
#include "tchar.h"
#include "windows.h"

#define DIR_LEN MAX_PATH+1

int _tmain(int argc, TCHAR* argv[])
{
	TCHAR sysDir[DIR_LEN];
	TCHAR winDir[DIR_LEN];

	//시스템 디렉터리 정보 추출
	GetSystemDirectory(sysDir, DIR_LEN);

	//Windows 디렉터리 정보 추출
	GetWindowsDirectory(winDir, DIR_LEN);

	_tprintf(_T("System Dir: %s \n"), sysDir);
	_tprintf(_T("Windows Dir: %s \n"), winDir);

	return 0;
}

 

실행 결과 :

System Dir: C:\Windows\system32
Windows Dir: C:\Windows

 

+ 예제 코드를 Visual Studio 2019 버전으로 실행하는 과정에서 변수 자료형에 관한 에러가 발생했다. 아래의 블로그를 통해 프로젝트 속성을 설정하여 해결했다.

https://namunotebook.tistory.com/20


참고 자료:

윤성우. 『뇌를 자극하는 윈도우즈 시스템 프로그래밍』.한빛미디어, 2007.

'독서 > [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ]' 카테고리의 다른 글

[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 07. 프로세스간 통신(IPC) 1  (2) 2023.09.24
[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 06. 커널 오브젝트와 오브젝트 핸들  (2) 2023.09.24
[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 04. 컴퓨터 구조에 대한 두 번째 이야기  (1) 2023.09.16
[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 03. 64비트 기반 프로그래밍  (1) 2023.09.10
[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 02. 아스키코드 vs 유니코드  (1) 2023.09.09
'독서/[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ]' 카테고리의 다른 글
  • [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 07. 프로세스간 통신(IPC) 1
  • [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 06. 커널 오브젝트와 오브젝트 핸들
  • [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 04. 컴퓨터 구조에 대한 두 번째 이야기
  • [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 03. 64비트 기반 프로그래밍
coding-l7
coding-l7
  • coding-l7
    coding-l7rl0
    coding-l7
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 기타
      • 유니티
        • OfficeWorkerRunning
      • 프로그래밍 언어
        • C
        • C#
        • C++
      • CS
        • 컴퓨터 구조
        • 운영체제
      • 물리 기반 시뮬레이션
        • 기초
        • Cloth Simulation
        • Fluid Simulation
      • 코딩 테스트
        • 프로그래머스
        • 백준
      • 독서
        • [ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ]
        • [ 혼자 공부하는 컴퓨터 구조 + 운영체제 ]
        • [ CUDA 기반 GPU 병렬 처리 프로그래밍 ]
      • 영어
        • Basic Grammar In Use
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
    • 포트폴리오
  • 공지사항

  • 인기 글

  • 태그

    collision
    상수
    입자 기반 방법
    narrow range filter screen-space fluid rendering
    Flip
    OpenGL
    물리 기반 시뮬레이션
    screen space fluid rendering
    정수 승격
    컴퓨터 구조
    GLSL
    RAM
    명령어
    그리드 기반 방법
    position based dynamics
    surface turbulence
    파동 난류
    jump table
    액체 시뮬레이션
    wave simulation
    실수
    cloth simulation
    fluid simulation
    bilateral blur
    시스템 프로그래밍
    pbd
    screen-space rendering
    C언어
    fluid implicit particle
    유체 시뮬레이션
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
coding-l7
[ 뇌를 자극하는 윈도우즈 시스템 프로그래밍 ] Chapter 05. 프로세스의 생성과 소멸
글쓰기
상단으로

티스토리툴바