ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2015.01.24 뇌자극 명령 프롬프트 프로젝트
    Legacy/뇌자극 - WinSysProg 2015. 1. 24. 19:52
    728x90

    명령 프롬프트 프로젝트

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    #include <stdio.h>
    #include <stdlib.h>
    #include <tchar.h>
    #include <locale.h>
    #include <Windows.h>
     
    #define STR_LEN 256
    #define CMD_TOKEN_NUM 10
     
    TCHAR ERROR_CMD[] = _T("'%s'은(는) 실행할 수 있는 프로그램이 아닙니다. \n");
     
    TCHAR cmdString[STR_LEN];
    TCHAR cmdTokenList[CMD_TOKEN_NUM][STR_LEN];
    TCHAR seps[] = _T(" ,\t\n");
     
    int CmdProcessing(int);
    int CmdReadTokenize(void);
    TCHAR * StrLower(TCHAR *);
     
    int _tmain(int argc, TCHAR * argv[])
    {
        _tsetlocale(LC_ALL, _T("Korean"));
     
        if(argc > 2)
        {
            for(int i = 1; i < argc; i++)
                _tcscpy(cmdTokenList[i-1], argv[i]);
            CmdProcessing(argc-1);
        }
        
        DWORD isExit = NULL;
     
        while(1)
        {
            int tokenNum = CmdReadTokenize();
     
            if(tokenNum == 0)
                continue;
     
            isExit = CmdProcessing(tokenNum);
            if(isExit == TRUE)
            {
                _fputts(_T("명령어 처리를 종료합니다. \n"), stdout);
                break;
            }
        }
        return 0;
    }
     
     
    int CmdReadTokenize(void)
    {
        TCHAR * token;
     
        _fputts( _T("Best command prompt>> "), stdout );
        _getts(cmdString);
     
        token = _tcstok(cmdString, seps);
     
        int tokenNum = 0;
     
        while(token != NULL)
        {
            _tcscpy ( cmdTokenList[tokenNum++], StrLower(token) );
            token = _tcstok(NULL, seps);
        }
     
        return tokenNum;
    }
     
    int CmdProcessing(int tokenNum)
    {
        BOOL isRun;
        STARTUPINFO si = {0,};
        PROCESS_INFORMATION pi;
     
        TCHAR cmdStringWithOptions[STR_LEN] = {0,};
        TCHAR optString[STR_LEN] = {0,};
     
        si.cb = sizeof(si);
     
        if( !_tcscmp(cmdTokenList[0], _T("exit")) )
        {
            return TRUE;
        }
        else if( !_tcscmp(cmdTokenList[0], _T("start")) )
        {
            if(tokenNum > 1)
            {
                for(int i = 1; i < tokenNum; i++)
                    _stprintf(optString, _T("%s %s"), optString, cmdTokenList[i]);
                _stprintf(cmdStringWithOptions, _T("%s %s"), _T("Commandprmpt_One.exe"), optString);
            }
            else
                _stprintf(cmdStringWithOptions, _T("%s"), _T("Commandprmpt_One.exe"));
            isRun = CreateProcess (NULL, cmdStringWithOptions,
                NULL, NULL, TRUE,
                CREATE_NEW_CONSOLE,
                NULL, NULL,
                &si, &pi
            );
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }
        else if( !_tcscmp(cmdTokenList[0], _T("echo")) )
        {
            for(int i = 1; i < tokenNum; i++)
                _stprintf(optString, _T("%s %s"), optString, cmdTokenList[i]);
            
            _tprintf( _T("echo message:%s \n"), optString);
        }
        else
        {
            _tcscpy(cmdStringWithOptions, cmdTokenList[0]);
     
            for(int i = 1; i < tokenNum; i++)
                _stprintf(cmdStringWithOptions, _T("%s %s"), cmdStringWithOptions, cmdTokenList[i]);
     
            isRun =
                CreateProcess ( NULL, cmdStringWithOptions, NULL, NULL,
                    TRUE, 0, NULL, NULL, &si, &pi);
     
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
     
            if(isRun == FALSE)
                _tprintf(ERROR_CMD, cmdTokenList[0]);
        }
        return 0;
    }
     
    TCHAR * StrLower(TCHAR *pStr)
    {
        TCHAR *ret = pStr;
     
        while(*pStr)
        {
            if(_istupper(*pStr))
                *pStr = _totlower(*pStr);
            pStr++;
        }
        return ret;
    }
    cs


    1. 커널 오브젝트와 핸들

    커널 오브젝트와 핸들이 무엇인지 이해하고 이들의 관계를 설명할 수 있어야 한다.



    2. 운영체제에 종속적인 커널 오브젝트

    커널 오브젝트가 Windows 운영체제에 종속적이라는 것은 무슨 뜻인가? 그리고 운영체제에 종속적이기 때문에 갖는 특성이 무엇인지 설명해 보자.

    - 커널 오브젝트는 프로세스에 종속적인 것이 아니라, 운영체제에 종속적인 관계로 커널 오브젝트의 소멸 시점은 운영체제에 의해 결정된다.

    3. Usage Count

    Usage Count가 무엇이고, 이 값이 어디에 존재하는지 그리고 이 값이 증가 및 감소하는 시점이 언제인지 설명해 보자.

    - Usage Count는 커널 오브젝트가 가지고 있고, 이 커널 오브젝트를 참조하는 프로세스의 숫자에 비례한다. Usage Count가 0이 될 때 비로소 커널 오브젝트는 소멸한다.

    4. CloseHandle 함수

    CloseHandle 함수의 기능이 무엇인지 Usage Count 관점에서 설명해 보자.

    - 해당 핸들에 연결된 커널 오브젝트와의 연결을 끊는 것을 의미한다. 이렇게 될 경우 해당 프로세스에서는 소멸시킨 핸들에 연결된 커널 오브젝트에 접근할 수 없게 되며, Usage Count는 1 감소하게 된다. 이와 관련해서 주의할 점은 Handle을 닫는다고 하여 커널 오브젝트 또는 프로세스가 소멸되는 것은 아니다.

    5. 프로세스의 Usage Count

    프로세스는 생성과 동시에 Usage Count가 2가 된다고 하였다. 그 이유를 나름대로 정리해 보자.

    - 그 프로세스를 생성한 부모 프로세스 + 자기 자신 = 2가 된다.

    6. 종료코드

    프로그래밍 기술 중에서 종료코드에 관련된 사항은 기억하고 있는 것이 좋다.

    7. 부모 프로세스가 자식 프로세스 핸들을 곧바로 반환하는 이유

    부모 프로세스는 자식 프로세스 생성과정에서 얻게 되는 자식 프로세스 핸들을 곧바로 반환한다. 이유는 무엇이고, 자식 프로세스의 핸들 반환 시간을 늦춰야만 하는 경우에 대해서도 설명해 보자.

    - 자식 프로세스의 핸들을 부모 프로세스에서 반환하지 않을 경우 자식 프로세스를 종료하더라도 자식 프로세스의 커널 오브젝트가 소멸되지 않게된다. 이럴 경우 리소스가 낭비된다. 때문에 자식 프로세스를 종료하면 그 커널 오브젝트까지 같이 소멸시키기 위해 자식 프로세스를 생성하자 마자 핸들을 반환하는 것이다. 추가로 자식 프로세스의 핸들 반환 시간을 늦춰야 하는 경우는 자식 프로세스의 종료코드를 얻기 위해서는 자식 프로세스의 커널 오브젝트에 접근해야 하므로 핸들 반환 시간을 늦춰야 한다.

Designed by Tistory.