안녕하세요. 까막입니다.

UAC 관련하여 최근 작업을 진행하면서 찾은 자료를 공유해보고자 올려봅니다.


문제 : UAC 상에서 관리자 권한으로 상승 시킨 어플리케이션과 탐색기 간의 Drag & Drop 가 동작하지 않는 문제

해법 : ChangeWindowMessageFilter 를 이용하여 WM_DROPFILES 관련 메시지를 필터에 걸리지 않도록 수정


용어 1 : UIPI (User Interface Privilege Isolation) 사용자 인터페이스 권한 격리

용어 2 : ChangeWindowMessageFilter 함수


참조 1 : Helge Klein 사이트

참조 2 : 띠깜의 하얀세상


ChangeWindowMessageFilter  함수는 낮은 무결성 수준의 발신자(어플리케이션)로 부터 수신되는 메시지를  

UIPI 의 메시지 필터 기능에 일부 혹은 전부를 추가하거나 삭제하는 기능을 가지고 있습니다.


제가 진행한 작업처럼 관리자 기능을 가진 어플리케이션에, 일반 유저 권한으로 수행된 탐색기의 WM_DROPFILES 메시지가 날라오면

보안 수준이 다르기 때문에 자동으로 필터하여 프로세스의 안전을 보장합니다.


드래그 & 드롭에 관한 메시지는 다음과 같은 메시지 일부를 필터에 추가하여 줌으로써, 기능이 동작하도록 설정할 수 있습니다.

(MSDN 의 Remark 에 따르면 안전한 프로세스 관리를 위하여, 필요한 메시지만 필터하도록 권고 하므로 

 기능이 잘 안된다고 루프를 돌려서 모든 메시지를 추가하는 일이 없도록 주의 하십시오.)

ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);

ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);

ChangeWindowMessageFilter (0x0049, MSGFLT_ADD); 


위 코드를 프로그램의 초기화 코드 위치나 다이알로그의 WM_INITDIALOG 핸들러 위치에 삽입하시면 됩니다.

아래는 샘플 코드...


BOOL CK4iRestoreDlg::OnInitDialog()

{

CDialog::OnInitDialog();


ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);

ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD);

ChangeWindowMessageFilter(0x0049, MSGFLT_ADD);


      // bla bla bla ...
}

테스트는 아래의 OS 상에서 기능이 테스트 되었습니다.
Windows 2003 Server x64/x86 kor/eng
Windows 2008 Server x64 kor/eng
Windows 2012 Server x64 eng/jp

Windows 7 x64 jp


안녕하세요. 까막입니다.

이번에 겪은 일이 있어, 혹시나 다른 분들도 이런일로 당황하시지 않았으면 하는 바램에 몇자 적어봅니다.

(배포 패키지 수행중에 서버 PC가 자동으로 재부팅이 되어 버리더군요 @.@)


현재 작업하는 제품은 Visual Studio 2013 커뮤니티 에디션으로 작성을 하고 있고요, 언어는 VC++ 입니다.

제품을 패키지화 해서 배포할 때는 아래의 vc redistributable package 를 함께 배포하죠.


Visual C++ Redistributable Packages for Visual Studio 2013



해당 배포 패키지는 위의 그림에서 보시는 것 처럼 몇가지 설치 옵션을 제공합니다.

(해당 옵션은 /? 파라미터로 확인 가능합니다.)


이러한 패키지는 설치하고자 하는 머신에 이미 설치되어 있을 수도 있고, 설치 과정에서

구지 사용자가 일일이 첵크하면서 확인할 필요가 없기 때문에 저는 /quiet 옵션으로 패키지를 구성하였습니다.


설명에도 나와있지만 /norestart 옵션을 구성하지 않는 이상, 장치를 재부팅 할 때는 prompt 하도록 되어있지요.

(/norestart 옵션을 구성하면, 재 부팅을 완전히 막아버리기 때문에 재 부팅에 관한 프롬프트가 아예 안나오겠지요)


여기서 장치를 재부팅한다는 의미는 업데이트를 해야하는데, 쓰기가 금지되었거나 사용중이거나 lock 되어서

업데이트는 필요하지만 지금은 업데이트를 할 수 없으니, 예약 작업을 걸어두고 재시작 되면 자동으로 

업데이트를 진행한다는 의미입니다.


이번 버전의 문제인지 저 /quiet 옵션으로 패키지를 수행하면, 업데이트 필요시 어떠한 프롬프트 없이

자동으로 서버를 재시작 해버립니다. 

(기존 버전은 /q 옵션을 쓰더라도 재시작 과정은 물어보았거든요..)

/quiet 옵션으로 설치 과정이 눈에 보이지 않기 때문에, 왜? 갑자기 꺼지는지 조차 알 길이 없습니다.


반응이 빠른 분은 강제 로그오프 과정중에 재빨리 취소할 수 있긴 하지만 아주 당혹 스럽습니다.


/quiet 옵션 대신에 /passive 옵션을 이용하시길 권장드립니다.


안녕하세요. 까막임돠~

오랜만에 글을 쓰네요, 언제나 항상 오랜만인... 게으른 까막 ㅡㅠ;


오늘은 최근 Open SSL 1.0.2 를 적용하면서 나온 부산물을 글로 적어볼까 합니다.

항상 그렇듯이 windows 기반이고요, 이제는 64 bit OS 만 대상으로 작업을 하게 되네요.

32 bit 는 빌드 환경만 바꾸면 되니, 사실 2개의 작업은 차이가 없습니다.


개발 환경은 Windows 2008 Server R2 x64 이고요, 툴은 MSVS-2013 공짜 버전을 사용하였습니다.


1. 우선 최신 버전을 다운 받아야 겠죠?

   https://www.openssl.org/source/


2. Active Perl 사이트에서 커뮤니티 에이션을 다운 받습니다.

   http://www.activestate.com/activeperl/downloads


3. 소스는 적당한 곳에 압축을 풀고, 펄은 설치를 합니다.


4. MSVS 2013 에서 콘솔 컴파일을 하려면 손으로 환경설정하는 노가다가 아주 끝내줍니다.

   자동으로 이런 환경을 제공해주니 사용해 주어야 겟지요..ㅎ

  

  

   해당 메뉴를 이용하면 다음과 같은 창이 열립니다.



  

  64비트 컴파일 환경을 수행하면 이런 환경 변수가 모두 적용된 cmd 창이 뜹니다.

  모든 작업이 완료될 때까지 쭉 써야할 이쁜이죠..


5. 우선 기본 소스가 풀린 폴더 BASE 라고 표현하죠. 해당 경로로 cmd 창에서 이동합니다.

   가장 첫 번째 작업으로 perl 을 이용하여 64비트 빌드 환경을 마춰주죠.

   cmd> perl Configure VC-WIN64A


   두 번째로. win64a 배치 파일을 수행하여 빌드 환경을 다시 마춰줍니다.

   cmd> ms\do_win64a


   마지막으로, nmake를 이용하여 빌드하면 끝~

   cmd> nmake -f ms\ntdll.mak


   이렇게만 해줘도, BASE 폴더에 out32dll 폴더와, tmp32dll 폴더에 빌드된 파일이 쭉 생기죠.

   모든 lib, dll, exe 는 BASE\out32dll 폴더에 다 들어있습니다.


   이번 1.0.2 버전은 windows 빌드 환경에 세심하게 신경썼는지, 아주 이쁘게 한방에 빌드가 되네요.

   

6. 이렇게 만 끝내면 상당히 아쉽지요?

   다음으로는 보통 가져다 쓰는 libeay32.lib 및 ssleay32.lib 를 사용하게 되는데, 이것 저것 좀 건드리다 보면

   unresolved external symbol 에러를 마주 치는 경우가 많습니다.

   

   분명 소스에는 있는 함수인데, 내가 만드는 프로그램에서 호출해서 쓰면 못쓰는 경우죠.

   라이브러리를 만들 때, 해당 함수를 export 하지 않았기 때문에 외부에서 못쓰는 거죠.


   BASE 폴더의 하위 폴더중에 util 폴더가 있습니다.

   libeay.num파일과 ssleay.num 파일이 있습니다. 


   내가 호출하는 함수가 어느 라이브러리 연관있는지는 개발자 본인이 가장 잘 알테고,

   그렇게 사용해야할 함수를 해당 파일을 열어서 등록해주면 됩니다.

   

   노트패드나 다른 에디터로 열어보시면 그냥 아실 수 있습니다.


   문제는 이러한 export 등록만 하면 되는게 아니고, 해당 함수의 정의부를 사용하는 해더에도 정의 해주어야 합니다.

   BASE\SSL\ssl.h 파일에 내가 사용하는 함수의 정의부를 함께 기록해주어야 합니다.


   이렇게 해주시면 ssl 내부의 함수도 내가 만드는 프로그램에서 자유자재로 쓸 수 있습니다.

 

   요렇게 해서 5번 과정을 이용하여 빌드하고 나면 ms 폴더에 있는 ssleay32.def 나 libeay32.def 파일에 추가한 함수가

   등록되어 있는걸 볼 수 있습니다. 사실 요걸 직접 수정해도 되는데, 환경 설정할 때마다 자동으로 덮어써지는 파일이기 

   때문에 귀찬고 실수 할 여지가 많죠.


7. ssl 을 이용하여 개발할 때 필요한 필수 항목이 디버깅 환경을 갖추는 거죠?

   지금까지는 그냥 release 환경 하에서, 쓸 수 만 있는거지 디버깅은 안됩니다.


   설치 폴더의 ms 폴더에 가서 do_win64a.bat 를 복사하여, do_win64a_debug.bat 파일을 하나 만듭니다.


   

   이 그림이 오리지널 파일이고요.



   

   요 그림이 디버깅 환경으로 변경한 그림입니다. 아주 쉽죠 @.@???

   cmd> ms\do_win64a_debug 

   cmd> nmake -f ms\ntdll_debug.mak


   이렇게 빌드하시면, 디버깅 환경도 짠 갖췄습니다.

   

   라이브러리나 dll 을 .dbg 폴더에 있는걸 가져다 쓰시면 디버깅 준비도 끝났습니다.


8. 이렇게 openssl 1.0.2 를 디버깅 환경하에서 사용할 수 있도록 모든 준비가 끝났지만

   openssl.exe 툴을 이용하여 디버깅을 하려면 저 소스를 이용해서 직접 빌드하고 수정할 수 있어야겠지요?

   저 실행 파일을 직접 디버거에 물려서 소스랑 같이 수정해가면서 빌드하면 좋겠지요?

    

sample.zip


   위의 sample.zip 파일의 압축을 풀어서 해당 내부에 있는 파일 4개를 BASE 폴더의 하부에 있는 apps 폴더에 

   복사하여 넣어 둡니다.

   

   요렇게 선택된 4개의 파일입니다.


   openssl.vcxproj 프로젝트 파일을 열어서 간단하게 F5 키를 눌러서 빌드해 줍니다.


   8.1 아무 문제 없으면 좋겠지만 첫번째 오류는 e_os.h 를 찾을 수 없다는 겁니다.

      BASE\tmp32dll 폴더나 BASE\tmp32dll.dbg 폴더에 있는 e_os.h 를 복사하여

      BASE\apps 폴더에 넣어주고, 다시 빌드 합니다.


   8.2 이렇게 끝나주면 가장 좋구요. 다음과 같이 winsock  관련 오류가 뜨면 한가지 작업을

      더 진행해 주어야 합니다.



     그림과 같이 윈속 관련된 에러가 뜬다. 저번 버전은 안그랬는데.. 안뜨면 좋고 위와 같이 윈속 관련 에러가 뜨면 apps.c 파일의 다      음 위치에 아래 코드를 추가한다.



     

     요렇게 한줄 추가해 주시고, 빌드해주시면 이제 openssl.exe 플젝을 디버거를 걸어 가면서 놀 수 있습니다.

     새로운 플젝을 만들 때도, 위에 소스 대충 가져다 만들면 별다른 문제 없이 쓸 수도 있구요..




     해당 플젝에 디버거 걸어서 소스 트레이스 하는 모습입니다.

     모두 잼난 열공.. 하셔요.. ~





   



오랫동안 내 정신을 갉아먹던 문제를 해결하였습니다. 

기쁜 마음에.. 내용은 생략...결과 그림만 흔적으로 남겨 봅니다.


아래 그림은 로컬 디스크 WD 7200 rpm 2TB (WDC WD2003FZEX-00Z4SA0) 디스크에

단일 파일 그룹으로 구성한 Database 의 테이블 내에 초당 10만 쿼리를 기록(삽입)하는 그림입니다.


아래 그림은 해당 프로세스가 구동되는 시스템 사양입니다.


아래 그림은 해당 시스템 구동중 프로세스 사용 정보입니다.


초당 10만 쿼리면, 응답도 10만개 합이 초당 20만 로우정도를 실시간으로 DB에 삽입하는 결과를 말합니다.

한시간 기준으로 테이블에 삽입되는 로우는 7억2천만건 정도.. 



삼재에 사재....오재 인줄 알았던 2014년 괜춘하게 마무리~











SSL Cipher Suites Issue


Windows RT 8.1, Windows 8.1 and Windows Server 2012 R2 Update April, 2004 

해당 업데이트에서 신규 Cipher 와 보안상 문제 취급되던 TLS_RSA_WITH_RC4_128_MD5, TLS_RSA_WITH_RC4_128_SHA

이슈가 발생하고 있네요. 문서상에서는 위 2개의 Cipher를 지원하는 것으로 기록되어 있지만 업데이트된 서버나 

클라이언트 OS의 특성에 따라 해당 2개의 Cipher 가 SSL Cipher Order List에서 사라지는 현상이 있습니다.


또한 Windows 7, Windows Server 2008 부터 Cipher top order 에 있던 AES가 클라이언트 오더링에서 하위로 밀리는

현상도 발생하고 있어서 TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA 해당 우선 순위가 

밀려서 다른 Cipher 로 통신하는 현상도 발생되고 있는데.. 같은 OS를 가진 여러서버를 업데이트 하였을 경우

간혹 위 문제를 발생시키는 서버가 발견되고 있습니다.



아래는 해당 업데이트로 새로 추가된 Cipher들의 목록

Cipher suite

FIPS mode enabledProtocolsExchangeEncryptionHash
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384YesTLS 1.2DHAESSHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256YesTLS 1.2DHAESSHA256
TLS_RSA_WITH_AES_256_GCM_SHA384YesTLS 1.2RSAAESSHA384
TLS_RSA_WITH_AES_128_GCM_SHA256YesTLS 1.2RSAAESSHA256

 

아래는 해당 업데이트 이후 새로 정렬된 기본 오더 리스트

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_RC4_128_MD5 TLS_RSA_WITH_NULL_SHA256 TLS_RSA_WITH_NULL_SHA SSL_CK_RC4_128_WITH_MD5 SSL_CK_DES_192_EDE3_CBC_WITH_MD5


현재 위의 분홍색2개로 통신하던 어플리케이션들은 분명 오더 리스트에 있음에도 불구하고 통신이 안되는 

폭탄을 맞는 일이 발생하고 있습니다.. 


저 같은 경우는 그런 경우는 아닙니다만, 젤 위의 파랑생 Cipher를 지원하기 위한 OpenSSL 업데이트 작업

그에 따른 프로그램 수정, 테스트와 배포.. 여러가지 폭탄을 맞은듯 ㅠㅠ;;;

요건 MS기술 링크: http://support.microsoft.com/kb/2929781


오랜만에 MMF (Memory Mapped File)를 살펴볼 일이 있어 예전 자료를 찾아다 쓰면서.. 

이것 저것 실험하는 중 불편한 코드 정리 및 대충 알던거 살펴보기.. 잘모르던거 제대로 알기.. 

이런 저런 관점에서 정리해보는 글입니다.


MMF가 무엇인지 어떤 장단점을 가지고 있는지와 관련된 내용이나 참조 사항은 다음 링크..

위키 : http://ko.wikipedia.org/wiki/메모리_맵_파일

이전자료 : http://crowback.tistory.com/198

MSDN : http://msdn.microsoft.com/en-us/library/ms810613.aspx


우선 정리된 클래스 골격



class CMMFObject

{
#define BIGINT LARGE_INTEGER

public:
    CMMFObject()
    {
        m_FileSize.QuadPart = 0;
        m_FileHandle        = INVALID_HANDLE_VALUE;
        m_hMemoryMap        = NULL;
        m_pMemoryMap        = NULL;
        m_bAudoDelete       = false;
        m_FilePath[0]       = 0;
    }

    virtual ~CMMFObject() { Close(); }


    /* 만들어져 있는 MMF를 열 때 사용하는 열기 함수 */
    DWORD Open(const TCHAR* pszMapName, DWORD dwDesiredAccess = FILE_MAP_READ);


    /* 파일 핸들이 있거나 시스템 페이지를 이용하여 MMF를 생성하는 함수 */
    DWORD Create(HANDLE hFile, const TCHAR* pszMapName, LONGLONG iFilesize, LPSECURITY_ATTRIBUTES lpAttributes = NULL);


    /* 파일을 직접 지정하여 MMF를 생성하는 함수 */
    DWORD Create(const TCHAR* pszMapFilePath, const TCHAR* pszMapName, LONGLONG iFilesize, bool bAudoDelete = true, LPSECURITY_ATTRIBUTES lpAttributes = NULL);


    /* 열려 있는 모든 내부정보를 닫고, 초기화 */

    DWORD Close(DWORD rc = ERROR_SUCCESS);


    /* 생성된 MMF의 접근 가능한 주소 */

    LPBYTE GetPtr() { return m_pMemoryMap; }

protected:

    DWORD __MapViewOfFile(DWORD dwDesiredAccess )
    {
        m_pMemoryMap = (BYTE*)::MapViewOfFile(m_hMemoryMap, dwDesiredAccess, 0, 0, 0);
        if(!m_pMemoryMap)
            return Close(GetLastError());

        return ERROR_SUCCESS;
    }

    CMMFObject(const CMMFObject& ) { /* barrier */ }
    CMMFObject& operator = (const CMMFObject &) { return *this; /* barrier */ }

private:
    BIGINT m_FileSize;
    HANDLE m_FileHandle;
    HANDLE m_hMemoryMap;
    LPBYTE m_pMemoryMap;
    TCHAR  m_FilePath[MAX_PATH];
    bool   m_bAudoDelete;
};




간단한 사용법


CMMFObject a;
CMMFObject b;

/* a 객체는 C:\\a.map 파일을 열거나 생성하여 1024 크기로 만들고, 이름을 LOCAL_FILE 으로 지정한다.

    b 객체는 LOCAL_FILE 이름을 가진 MMF를 읽고/쓰기 모드로 연다. */
if(a.Create(_T("C:\\a.map"), _T("LOCAL_FILE"), 1024) == ERROR_SUCCESS)
    _tcscpy((LPTSTR)a.GetPtr(), _T("까마귀날자 배떨어진다."));


if(b.Open(_T("LOCAL_FILE"), FILE_MAP_READ | FILE_MAP_WRITE) == ERROR_SUCCESS)
    _tcscpy((LPTSTR)b.GetPtr(), _T("날아도 배 안떨어져요."));


/* a 객체는 시스템 페이지를 이용하여 1024 크기로 만들고, 이름을 SYSTEM_PAGE 으로 지정한다.

    b 객체는SYSTEM_PAGE 이름을 가진 MMF를 읽기 모드로 연다. */
if(a.Create(INVALID_HANDLE_VALUE, _T("SYSTEM_PAGE"), 1024) == ERROR_SUCCESS)
    _tcscpy((LPTSTR)a.GetPtr(), _T("까마귀날자 배떨어진다."));


if(b.Open(_T("SYSTEM_PAGE"), FILE_MAP_READ) == ERROR_SUCCESS)
    _tcscpy((LPTSTR)b.GetPtr(), _T("날아도 배 안떨어져요.")); <- 에러: 읽기 모드로만 열어서 쓰기 금지


CMMFObject c(a);   <- 에러: 복사 생성에 의한 다중 참조 금지

CMMFObject d = b;  <- 에러: 대입 연산에 의한 다중 참조 금지



코드를 다시 정리하면서...


1. MMF는 생성 시점에 바로 메모리에 올라가지 않는다.

     실제 생성한 MMF를 액세스 하는 시점에 해당 사용한 영역 만큼만 메모리에 올라간다.

     즉, 1 GB 짜리 MMF를 생성해도 시스템 메모리 사용량은 변함이 없고, 거기에 읽고/쓰는 영역이 생기면 그 때 변화한다.


2. 32 Bit OS에서 이론적으로 4GB까지 MMF를 생성할 수 있다고 하는데... 

     일반적으로 32 bit Windows 에서는 1.5~1.8 GB 까지 생성가능하다. 

     쫌더 쓰려면?  /3GB boot parameter 를 이용하여 2.5~2.7 GB 까지 가능하기는 하지만.. 서버용으로는 쓰기 곤란하다.

     즉, 32 Bit OS 에서는 많이 써봐야 1.8 GB 정도로 보면 된다.


3. MMF를 생성하면 메모리가 증가 하겠지만, 오픈 할 때도 증가???

     MMF를 생성하면 당연히 할당한 크기만큼 메모리가 증가한다. 

     그런데 MMF를 열면,  원래 MMF가 지정한 크기만큼 메모리가 다시 증가한다. 또 열면 또 그만큼 증가한다.


     아래의 그림을 참고하자. a는 MMF를 생성, b는 MMF를 읽기모드로 오픈한 객체 정보의 비교이다. 

     데이터에 모두 b 라는 문자열을 가졌지만.. 해당 메모리의 주소가 서로 다르다.

     MMF의 오픈이라는 의미는 생성해둔 MMF 주소를 가져다 빌려쓰는게 아닌.. 같은 크기만큼의 메모리를 만들어서

     미러형식으로 데이터의 동기화를 이루어 공유하는 것처럼 보이는 방식이다.


4. 파일을 직적 연결하여 MMF를 생성했을 때, 메모리 방식과 직접 파일 액세스 방식은 혼용하면 않된다.

     내가 직접 만든 파일로 MMF를 생성할 경우, 2가지 방식으로 액세스 할 수 있는 상태가 된다.

     하나는 직접 파일을  read/write 하는 방식과 다른 하나는 메모리를 매핑된 MMF의 주소를 이용함 메모리 방식이다.

     각각 혹은 2가지 방식을 동시에 사용할 수 있지만.. 매핑된 메모리에 쓴 내용이 바로 디스크에 반영되지 않기 때문에

     2가지 방식으로 데이터를 액세스 하면 같은 위치 영역의 디스크 데이터와  메모리 데이터가 틀어질 수 있다.


5. 그럼 파일이 빠르냐?  MMF가 빠르냐?

     MMF가 디스크에 스왑되어 있을 경우는 메모리에 올라갈 동안 지연이 일부 생기지만.. 일단 메모리에 올라간 이후라면 

     MMF가 빠르다.. 랜덤 액세스일 경우는 성능 차이가 많이 벌어진다. 

     하지만 MMF는 파일 크기를 변경할 수 없기 때문에 쓰기 작업을 이용하여 늘려가면서 쓰는것이 불가능하다.

     또한, 작업중 디스크에 스왑되기 전에 전원이 꺼진다던가 하면 작업 내용이 사라진다..  





어제에 이어 오늘도 이 내용을 쓰게 되는군요..


어제 나름대로 MSSQL의 주석문 처리에 대하여 이해했다고 생각했는데.. ㅠㅠ

다음은 예시 그림..


<그림 1 - 어제 나름대로 이해한 바탕으로 주석 예시 만든것>


나의 머리를 복잡하게 만드는 아래 그림

<그림 2 - 또다시 의도하지 않는 결과를 토해내는 미친 sql>


아래는 상황을 좀더 자세하게 비교한 그림

<그림 3 - GO 문의 위치에 따라 다르게 동작하는 sql 엔진>


GO문이 특수하다는건 알겟지만.... 저런 짖거리를 하는 ms가 점점더 미워짐.. 

오늘도 하루가 날라가네 그려 ㅠㅠ;;;



주로 MSSQL 쪽 프로그래밍을 하다보니.. 여러가지 내부적인 것들을 건드리게 되는군요.


<그림 1 - 기본>


위 그림은 일반적인 블록 주석문과 라인 주석문에 대한 구문이고.. 

단순한 수행 쿼리입니다.

수행해 보면 결과가 정상적으로 1 이 나옵니다..


그렇다면 아래 2번 그림의 쿼리는 어떨까요?

<그림 2 - 먼가 다른 주석처리>


프로그래머 관점이라면 저기 붉은 사각박스의 /* 가 하나 더 들어갔다고 해서..

위 그림처럼 주석 처리가 되면 안되겠지요..


수행하면 당연히 에러를 토해냅니다.

메시지 113, 수준 15, 상태 1, 줄 5

주석 끝 표시('*/')가 없습니다.


사실 의도된 결과는 아래 그림처럼 나오길 바랬습니다.

<그림 3 - 내가 원했던 결과>


자 그렇다면 MSSQL에서는 그림 2번과 그 결과처럼 /*는 페어처리를 하도록 설계된 것인가?

그림 2번 내용을 조금 바꾸어 보도록 하죠.


<그림 4 - 이제서야 보이는 설계 의도>


<그림 5 -  mssql 2008 ssms>                                <그림 6 - msvs 2008>


지금 까지 여러가지를 테스트해본 결과.. 쿼리를 고속으로 파싱해야 하는 sql 엔진 입장에서

내부적으로 다중 중첩된 블록 주석문을 처리하는것이 상당히 부담스러웠던거 같습니다.

첫번째 의견은 위와 같았는데.. 실제로 구현이나 파싱처리에서 보면 sql 처럼 처리하는게

로직적으로 더 부담이 되겠네요. 주석의 끝을 명시해야 하는것도 그렇고..

아마도 스크립트로 의도되지 않은 동작을 일으키지 못하도록 방어하는 입장에서 작성된거라 생각듭니다.


그래서 블록 주석문은 /*의 갯수가 나오면 기존 블록에 포함되던 말던.. 나온 갯수 만큼 */ 의 페어를

맞추어 주로록 의도적으로 설계된듯하네요..


어쨋든 저렇게 의도 되었다는 것을 알게는 되었지만.. 

일부 로직을 새로 짜야한다능.. ㅠㅠ


오늘의 팁하나.

MSSQL에서 tempdb에 임시테이블을 만들고 통계를 작성하면, 거기서 작성된 통계를

오리지날 테이블에 업데이트 시킬수가 없다. 

콜레이션 문제가 발생하기 때문이다.. 끝~


마지막 포스팅을 한지 벌써 일년정도가 흘렀습니다.

시간은 30대의 마지막을 흘러 가고

아이들은 점점 커가고

머리는 점점 나빠져 가는군요...

제 자신의 블로그 조차 거의 들어와보지 않다가, 2000년도 경에 제작한 음성채팅소스에 대한
문의가 있어서 우연히 살펴보게 되었습니다.

날 코딩에 어줍잔은 비동기 소켓에 UDP를 사용한다며, 용법도 몰라서 TCP인줄도 모르고
쓰고, 머가 그리 할짓이 없었는지.. 고양이 캐릭터나 리전으로 잘라내고 ㅠㅠ 

http://euler.synap.co.kr/  사이트를 우연히 들어갔다가 3번째 문제에서 막힌 내 자신이 한심하기도 하구요
(이건 어디까지나 개인적인 푸념입니다. 나름 수학은 좀 한다고 수치해석좀 돌리고 했었는데)
(소인수분해가 기억속에서 지워졌는지 도무지 기억이 안나네요 ㅠㅠ 덕분에 다시 책좀보구 있어욤)

지금도 일을 하나 하면, 2가지 일이 튀어나오는 신기한 회사에서

열심히 일하고 있고 ( 는 다분히 개인적인 의견입니다. ㅎㅎ)

이 회사도 7월이면 만으로 7년이 되는군요.. 아 길기도 하다.. 

DB보안쪽인데, 고객분들이 써보시고 마케팅하는 영업없는 이상한 회사이기도 하지요 ㅠㅠ;

이제서야 첨으로 IOCP를 공부하는데 어렵네요.

프로그램에서 손을 놓는 그날까지.. 화이팅~ ^^~
 
아침에 들어보는 클래식 한곡.. ^^;

근데 신기한건, 악보 없이 들었던 느낌을 그냥 손가는 대로 친다는데.. 굇수로세 -_-)b~

--------------------------------------------------------------------------------

요거 아침에 집에 오기 전에 짧은 10분 내로 처리해야 해서.. 엄청 급하게 쳤다.
마음에 쏙 드는건 아니지만.. 그냥 그런대로 들어줄 만 하길래 올려본다. ㅎㅎ




오리지날포스팅) http://hopi.tistory.com/entry/천공의-성-라퓨타-피아노-쇼트-버젼

+ Recent posts