190701-2 - 핸들, 동기, 신호/비신호
(1일차) 교육을 받으면서 노트필기 했던 내용을 날것 그대로 업로드합니다.
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
void main()
{
//const char* s = "Hello!"; // 상수 메모리 문자열
////s[0] = 'a'; // 변경할 수 업
//printf("%s\n", s);
char cur[MAX_PATH];
char sys[MAX_PATH];
char win[MAX_PATH];
// 현재 작업 디렉토리
GetCurrentDirectory(MAX_PATH, cur); //● 작업 디렉토리 : 프로세스는 자기만의 작업디렉토리가 있다.
//SetCurrentDirectory("C:\\Temp");
//GetCurrentDirectory(MAX_PATH, cur);
// 시스템 디렉토리
GetSystemDirectory(sys, MAX_PATH);
// 윈도우즈 디렉토리
GetWindowsDirectory(win, MAX_PATH);
printf("현재 작업 디렉토리: %s\n", cur);
printf("시스템 디렉토리: %s\n", sys);
printf("윈도우즈 디렉토리: %s\n", win);
}
● 클래스의 이름으로 윈도우를 찾을 수 있다.
●윈도우는 프로세스가 뜨면 자동적으로 프라이머리 쓰레드가 하나 뜬다. 무조건 프로세스의 ID가하나있고 쓰레드의 ID가 하나 있다. 프로세스 커널오브젝트와 쓰레드 커널오브젝트가 서로 다르다.
● 여태 만들었었던 윈도우들은 쓰레드가 소유하게된다.
● UI쓰레드도 하나씩 돌고있다.
● ID만 있으면 핸들을 얻을 수 있다.
● 이름으로 윈도우 핸들을 받아온다 -> 윈도우 핸들로 프로세스 아이디를 받는다.(쓰레드 아이디도 받는다.) -> 프로세스 아이디로 프로세스 핸들을 얻어온다. -> 얻은 권한을 사용한다.
● 윈도우 핸들 : 윈도우 최대화 등 윈도우를 컨트롤할 수 있다.
● 프로세스 핸들 : 종료 등을 할 수 있다.
#include <stdio.h>
#include <windows.h>
void main()
{
//HWND hWnd = FindWindow(
// 0, // 윈도우 클래스 이름
// "제목 없음 - 메모장" // 윈도우 이름(윈도우 타이틀 이름)
// );
HWND hWnd = FindWindow( "notepad", 0); // ● 클래스이름 으로 윈도우를 찾아서 핸들을 반환한다. (윈도우의 핸들)
if( hWnd == NULL)
{
printf("메모장을 실행하시오!\n");
return;
}
DWORD processID;
DWORD threadID;
threadID = GetWindowThreadProcessId( hWnd, &processID );
// ●윈도우의 핸들로 프로세스의 아이디를 찾는다.
//● 반환으로는 쓰레드의 아이디를 찾는다. (파라미터로 프로세스의 아이디 또한 건져온다.)
// ID로 프로세스 핸들 얻기
// PROCESS_TERMINATE : TerminateProcess() 호출 위한 권한 설정
HANDLE hProcess;
hProcess = OpenProcess( //● 프로세스의 핸들을 얻어옴
PROCESS_TERMINATE|PROCESS_QUERY_LIMITED_INFORMATION, //● 종료시킬 수 있는 권한의 핸들을 얻겠다.
0, processID); // ● 메모장 프로세스핸들을 사용하여 종료가능
printf("메모장의 윈도우 핸들 %d\n", hWnd);
printf("메모장의 프로세스 ID %d\n", processID);
printf("메모장의 프로세스 핸들 %d\n", hProcess);
//프로세스의 커널오브젝트 종료 코드 값을 받음.
DWORD exitCode;
GetExitCodeProcess(hProcess, &exitCode);
if(exitCode == STILL_ACTIVE)
printf("메모장 프로세스가 사용 중~\n");
printf("메모장을 종료하려면 '엔터'키 치시오\n");
getchar();
//메모장 프로세스 핸들을 이용하여 종료 시킴.
TerminateProcess(hProcess, 100); // ● 비정상 종료를 강제로 만들어냄.
// ● 비정상 종료가 바로 보장되지는 않는다.(싱크)
GetExitCodeProcess(hProcess, &exitCode);
if(exitCode == STILL_ACTIVE)
printf("메모장 프로세스가 사용 중~\n");
else
printf("메모장의 종료 코드: %d\n", exitCode);
}
#include <stdio.h>
#include <windows.h>
//● 싱크로나이제이션 (동기, 순서를 제어) 를 알아보는 예제
void main()
{
DWORD processID;
printf("확인할 프로세스 ID 입력: ");
scanf_s("%d", &processID); // ● 1.정수값을 입력받아서
//● 보안 문제로 _s 추가되었다. 스택오버플로우 어택
//● 문자열을 기록하는 곳은 모두다 그 문자열의 크기를 지정하게 되어있다.
HANDLE hProcess;
hProcess = OpenProcess( //● 2. 프로세스 핸들을 찾는다.
SYNCHRONIZE, // wait functions 사용 권한 부여
//● ↑ 동기화(순서제어) wait하는 핸들. wait로 시작하는 함수를 호출할 수 있는 권한
0, processID);
if(hProcess == NULL)
{
printf("프로세스 ID : %d의 프로세스가 없습니다.\n");
return;
}
printf("프로세스 ID %d\n", processID);
printf("프로세스 핸들 %d\n\n", hProcess);
printf("프로세스 ID %d가 종료하기를 기다립니다~!\n", processID);
WaitForSingleObject(hProcess, INFINITE); // ● 중요한함수. (현재 프로세스가 wait를 한다.)
//● 3.가리키고있는 핸들의 커널오브젝트가 신호상태가 되기를 대기한다.
//● INFINITE : 무한정 기다리겠다
printf("프로세스 ID %d가 종료했습니다.\n", processID);
}
●커널오브젝트는 신호, 비신호를 가지고있다. 신호상태/비신호상태.
쓰레드와 프로세스는 종료될 때 신호상태가 된다. 실행되고 있을 때는 비신호 상태이다.
● 윈도우즈 에서는 쓰레드
● 구조체의 첫 변수는 자신 구조체의 크기를 나타내는 경우가 많다.
향후 멤버 추가를 할 때 문제가 발생하는 것을 막기 위해서 사용한다.
DWORD cb; 라는 카운트 바이트를 주어서 무조건 자신의 구조체의 사이즈를 명시하도록한다.
● 내가 얻은 핸들은 사용하지 않을 거면 무조건 닫아야한다.
● CreateProcess
● 파일찾기 (cmd 창에서의 실행)
-
실행 위치
-
작업 위치 (DLL)
-
윈도우즈 디렉토리
-
시스템 디렉토리
-
path 설정
#include <stdio.h>
#include <windows.h>
void main() //● 프로세스와 윈도우의 관계 예제
{
STARTUPINFO si={sizeof(STARTUPINFO),}; //● 사이즈를 꼭 명시하게 되어있다. !!
PROCESS_INFORMATION pi; // ● 4개정보를 가져오는 아웃파라미터로 사용(프로세스,스레드 의 핸들과 아이디)
CreateProcess(
NULL, //프로그램 이름 ●중요
"notepad.exe", //프로그램 명령행 인자(프로그램이름이 NULL경우 프로그램 이름까지 포함할 수 있음) ●중요
NULL, // 프로세스 보안속성
NULL, // 쓰레드 보안속성
FALSE, // 상속여부 ●중요 (FALSE는 상속안함) (커널 오브젝트, 자식오브젝트에 테이블을 물려줄 것인가)
0, //생성 플래그 우선 순위 지정(HIGH_PRIORITY_CLASS 등) 0: 기본 우선 순위 및 새 콘솔 창 실행(CREATE_NEW_CONSOLE) ●중요
NULL, //환경변수 설정 NULL이면 부모의 환경 변수 사용
NULL, // 현재 디렉토리 설정
&si, // 메인 윈도우가 어떻게 보일지 초기화 구조체 ●중요
&pi // 생성한 프로세스의 정보 구조체 out param ●중요
);
////
CreateProcess(NULL, "notepad.exe",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
//● 절대 경로를 표시하는 코드
TCHAR Path[MAX_PATH];
GetWindowsDirectory(Path, MAX_PATH);
lstrcat(Path, "\\notepad.exe"); //● 결합
CreateProcess(Path, NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi); //● 첫 번째 경로 써서 프로그램 실행
CreateProcess(NULL, "notepad.exe c:\\Setup.log",NULL,NULL,
FALSE,0,NULL,NULL,&si,&pi);
//STARTUPINFO 구조체(윈도우 옵션은 아래 세 가지.
si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE; //● 사용자가 지정한 위치에 지정한 크기로 자리를 잡을 수 있다.
si.dwX = 50; // 위치, 크기가 CW_USEDEFAULT 로 설정된 윈도우만 가능
si.dwY = 50;
si.dwXSize = 200;
si.dwYSize = 200;
//CreateProcess(NULL, "TestWindow.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
getchar();
// 핸들은 닫아야 한다.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
● 메인 함수의 표준 타입
#include <stdio.h>
int main(int argc, char** argv)
{
printf("명령행 인자 개수: %d\n", argc);
for(int i = 0 ; i < argc ; ++i)
printf("argv[%d]: %s\n", i, argv[i]);
}
-
int main(void){}
-
int main(int, char**){} : 프로그램인수의 개수, 프로그램인수의 문자열 테이블 주소
-
첫 번째 문자열은 프로그램이름
● 명령행 인자 불러서 대화상자(다이얼로그) 출력하기
#include <windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("CmdLine");
//●명령행 인수2
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
//●첫 번째
MessageBox(NULL, lpszCmdParam, "명령행 인수-lpszCmdParam", MB_OK);
//●두 번째
for (int i = 0; i < __argc; i++)
MessageBox(NULL, __argv[i], "명령행 인수-argv", MB_OK);
//●세 번째 // ● 유니코드 에서만 가능
LPSTR cmd = GetCommandLine();
MessageBox(NULL, cmd, "명령행 인수-GetCommandLine", MB_OK);
////●네 번째
int nArg;
LPWSTR *p=CommandLineToArgvW(GetCommandLineW(),&nArg);//● 명령행 인자 얻어오기
//●GetCommandLineW() 토큰 별로 잘라주는 역할 (인자 구분해줌)
for (int i = 0; i < nArg; ++i) {
MessageBoxW(NULL, p[i], NULL, MB_OK);
}
LocalFree(p);
return 0;
}
'System Programming' 카테고리의 다른 글
[system programming] 핸들, 커널 오브젝트, 프로세스 등 (0) | 2019.07.04 |
---|---|
[system programming] WS_CHILD, SuspendThread, ResumeThread 등 (0) | 2019.07.04 |
[system programming] TLS, ResumeThread, nterlockedIncrement 등 (0) | 2019.07.04 |
[system programming] 커널오브젝트와 핸들, 핸들 테이블, 신호 비신호 상태, 쓰레드 등 (0) | 2019.07.04 |
[system programming] 커널오브젝트, 아스키코드와 유니코드 (0) | 2019.07.03 |