프로세스간에 데이터 교환(통신) 방법



Memory Mapped File (메모리 맵 파일)
하드 디스크의 실제 파일을 프로세스 주소 공간에 mapping하는 기법으로 
매핑한 포인터를 통해 파일 내용을 메모리 처럼 다룬다.
또한 여러 프로세스간 메모리 공유 방법으로도 사용되어 서로 데이터를 주고 받을 수 있게 해준다.
(하나의 파일을 두 프로그램에서 열어 수정시 수정된 내용을 바로 확인 할수 있다.)
**.하나의 메모리 맵 파일(CreateFileMapping)에 대해 여러개의 맵 뷰(MapViewOfFile) 생성이 가능
[API Overview]
CreateFileMapping() : 메모리 맵 파일 생성
flProtect 플래그 설명
PAGE_READONLY : 읽기 전용의 메모리 맵 파일 생성
PAGE_READWRITE: 읽기,쓰기 가능하게 생성. 넘겨받는 파일 핸들이
GENERIC_READ | GENERIC_WRITE로 열려있어야 함.
PAGE_WRITECOPY: 읽기,쓰기 가능하게 생성. 쓰기 수행시 별도의 복사본을 만듦(Write On Copy)
OpenFileMapping() : CreateFileMapping의 마지막 인자를 지정하여 이름을 갖는 메모리 맵 파일을 열때 사용
MapViewOfFile() : 메모리 맵 파일에 대한 뷰 생성
dwDesiredAccess 플래그 설명
FILE_MAP_WRITE : 읽기, 쓰기
FILE_MAP_READ : 읽기
FILE_MAP_ALL_ACCESS : 읽기, 쓰기
FILE_MAP_COPY : 읽기, 쓰기. 쓰기 시도시 데이터의 복사본을 만듦(Write On Copy)
FlushViewOfFile() : 수정된 내용은 성능상 캐시를 사용하는데 강제로 캐시 내용을 파일에 쓸때 사용하는 함수
UnmapViewOfFile() : Map View 닫음

[샘플 : 메모리 맵 파일을 이용한 단순한 파일 읽기/쓰기]

[샘플 : 메모리 맵 파일을 이용한 프로세스간 데이터 송수신]
프로세스간 읽기/쓰기 시에 데이터 정합성을 위해 Mutex 동기화 필요.
실제 파일이 아닌 메모리 상에 메모리 맵 파일 생성시 INVALID_HANDLE_VALUE를 핸들로 주어 생성.
ex) CreateFileMapping(INVALID_HANDLE_VALUE, ..);

WM_COPYDATA
다른 프로세스와 통신 방법 중 하나로 SendMessage로 WM_COPYDATA 메세지를 보내며
LPARAM으로 COPYDATASTRUCT에 데이터를 담아 전송하는 방법.
데이터에 포인터는 의미가 없으며 실제 데이터를 직접 카피해 줘야 한다.
또한 수신 측에서 송신 측으로 데이터를 보내고 싶으면 별도의
WM_COPYDATA 메세지를 보내고 처리해야 한다.


Pipe (파이프)
[Overview]
Named Pipe : 프로세스간 통신 전용으로 기능이 풍부하지만 이용이 까다로운 편임.
Unnamed Pipe :제한된 기능을 갖지만 구조가 단순하여 이용하기 쉬움.

[Named Pipe]
CreateNamedPipe()로 Named Pipe 생성.
ConnectNamedPipe()로 파이프를 대기 상태로 둔다.

CreateFile(), WaitNamedPipe()를 사용하여 클라이언트쪽에서 접속한다.
ReadFile()/WriteFile()에 Named Pipe 핸들을 주어 파이프를 읽고 쓸 수 있다.

DisconnectNamedPipe()로 접속을 끊고 파이프 버퍼의 데이터를 파기한다.
FlushFileBuffers()는 파기되기전에 남아있는 파이프의 데이터를 처리할때 사용할 수 있다.
CloseHandle()로 사용이 끝난 파이프 핸들을 닫는다.

HANDLE WINAPI CreateNamedPipe( //return: 파이프 핸들
 __in          LPCTSTR lpName, //"\\.pipe\ 파이프명" 형식의 파이프명 지정
 __in          DWORD dwOpenMode, //데이터 방향을 지정하는 오픈 모드.(출력, 입력, 쌍방향 등..)
 __in          DWORD dwPipeMode, //파이프 모드. 데이터의 단위 지정(바이트 혹은 메세지 단위)
 __in          DWORD nMaxInstances, //동일한 이름으로 생성할 수 있는 최대 파이프 개수
 __in          DWORD nOutBufferSize, //출력 파이프 버퍼 크기
 __in          DWORD nInBufferSize, //입력 파이프 버퍼 크기
 __in          DWORD nDefaultTimeOut, //빈 파이프가 없어 대기시 최대 대기 시간
 __in          LPSECURITY_ATTRIBUTES lpSecurityAttributes //보안 속성.
);
BOOL WINAPI ConnectNamedPipe( //return: 접속 성공 여부
 __in          HANDLE hNamedPipe, //Named Pipe 핸들
 __in          LPOVERLAPPED lpOverlapped //오버랩 IO 사용시 구조체 지정
);
파이프 생성시 오픈 모드 -> Client에서 CreateFile()시 접근 모드
PIPE_ACCESS_INBOUND -> GENERIC_WRITE
PIPE_ACCESS_OUTBOUND -> GENERIC_READ
PIPE_ACCESS_DUPLEX -> GENERIC_READ | GENERIC_WRITE
[샘플 : Client 쪽 접속]
//같은 컴퓨터라면 서버명 대신 "." 사용 가능
TCHAR* pipeName = _T("\\\\서버명\\pipe\\TestPipe");
HANDLE hPipe = CreateFile(pipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL
OPEN_EXISTING, 0, NULL); //OPEN_EXISTING는 미리 생성된 파이프에 접근을 의미

if (hPipe == INVALIDE_HANDLE_VALUE) //파이프가 없거나 모두 사용중인 경우
{
BOOL bExit = true;
if (GetLastError() == ERROR_PIPE_BUSY) //모두 사용중인 경우
{
bExit = !WaitNamedPipe(pipeName, NMPWAIT_USE_DEFAULT_WAIT);
//NMPWAIT_WAIT_FOREVER : 무기한 대기
//NMPWAIT_USE_DEFAULT_WAIT : 파이프 생성시 설정한 기본값 적용
}
if (bExit) _tprintf(_T("Cannot open pipe"));
}
[Unnamed Pipe]
CreatePipe()로 단방향 파이프 생성되며 입구, 출구의 두개의 핸들이 반환됨.
쌍방향 통신을 위해선 두개의 파이프가 필요.
[샘플 : 부모 프로세스와 자식 프로세스간의 Unnamed Pipe 통신]


클립보드(clipboard)

IPC 기타


'C++' 카테고리의 다른 글

윈도우 공유폴더 연결 방법 ( net use )  (0) 2011.04.05
VC++ ADODB SP 호출  (0) 2011.03.30
warning LNK4099: 'vc90.pdb'  (0) 2011.03.25
CRT 이야기 [펌]  (0) 2011.02.14
LocalAlloc, GlobalAlloc, HeapAlloc, VirtualAlloc  (0) 2011.02.03
파일 핸들링 API  (0) 2011.02.03
MFC tip  (0) 2011.01.25
OLEDB  (0) 2011.01.24