LPSTR, LPCSTR, LPTSTR, LPCTSTR , LPWSTR, LPCWSTR 
뭔가 다 비슷 비슷해보이죠? 

원래 c와 c++은 string이라는 똑똑한 자료구조형을 compiler차원에서 지원하고 있지 않습니다. 

그대신 가장 많이 사용하는 string을 어떻게 저장해야 할지에 대해 고심한 결과... 
결국 배열의 끝에 '\0'또는 0 또는 NULL값을 넣어 string을 표현하도록 했습니다. 
결국 가장 적은 용량의 string처리와 가장 골치아픈 string처리가 탄생하는 순간이였죠. 

어쨌거나 요점은... 
Windows에서는 이런 string처리를 위해서 char* 형을 그대로 쓰기 보다는 LPCSTR등의 표현으로 대치해 사용함으로써, 개발의 편의성을 돕고 있습니다. 

자... 그럼 서론이 길었고... 
위의 골치아픈 형을 살펴보면.. 

같은 글자들이 여러번 반복해 나옴니다. 

LP, C, STR 등이 거의 자주 반복되고, 
어떤놈들은 T 나 W를 사용하기도 하죠. 

글자를 하나씩 살펴볼까요. 

LP는 long pointer를 나타내는 약어로서 16bit시절의 윈도우의 유산입니다. 
과거 windows3.1까지의 시절에는 포인터는 모두 16bit였고, 24bit 메모리를 long pointer라는 것을 통해서 extended memory라는 이름으로 관리했었거든요.. 
현재 LP(long pointer)는 .Net에서는 64bit pointer를, VC++6.0과 그 이전 버전에서는 32bit pointer를 나타냅니다. 

C는 constant, 즉 함수의 내부에서 인자값을 변경하지 말라는 뜻입니다. 

STR은 말그대로 string자료가 될것이라는 뜻으로 내부적으로는 char형 배열에 null값 종료를 의미하고 있죠. 

자... 그럼 해석해 봅시다.. 
LPSTR = long pointer string = char * 
LPCSTR = long pointer constant string = const char * 
결과적으로는 맨 마지막과 같은 형이라는 거죠. 

그런데... 
LPCTSTR!! 요넘은 무었이냐!! 
LPCTSTR = long pointer constant t_string = const tchar * 
앗! 오타입니다. t라는 놈이 들어갔네요.. 
오타일까요? ^^ 아닙니다. t라는 놈은 우리나라를 위해 아주 중요한 역할을 하는 놈이죠.. 이것은 잠시 이후에 살펴보겠습니다. 

그럼 먼저.. 
W라는 넘을 살펴보죠... 

W 이넘은 wide char를 나타냅니다. 쉽게 말하면 unicode죠.. 
win9x에서 사용하던 multibyte와는 다릅니다. 물론 한글 조합형 코드도 아니고... 
unicode를 나타냅니다. 

자 그럼 다시 해석을 해보죠. 
LPWSTR = long pointer wide string = w_char * 
LPCWSTR = long pointer constant wide string = const w_char * 

위와 같이 해석됩니다. 


그런데 t_char('티캐릭터'라고 읽습니다.)는 무었이냐!! 

마이크로소프트가 세계 각국에 제품을 판매하면서.. 
각국의 언어에 맞추어 개발하는 것에 환멸을 느끼다가.. 
드디어 windows를 unicode기반으로 개발하는 작업에 착수했습니다. 

그런데... 문제는 char는 1Byte이고 wide char는 2Byte이므로.. 
포인터 연산을 많이하는 c, c++코드는 호환성에 치명적인 문제가 있었죠. 
그래서 컴파일러가 precompile option을 보고. 환경에 맞게 동작하는 코드를 작성할 수 있는 새로운 변수 모양의 Macro를 선언하게 되었습니다. 
그것이 바로 TCHAR, t_char라는 변수죠. 
이놈들은 자신의 운영체제가 multi-byte환경이면, char형으로, 
unicode환경이면, w_char, wide char형으로 type casting됩니다. 

그래서... 보통 windows 9x, 2000계열의 환경이라면, 
LPTSTR = LPSTR = char * 
LPCTSTR = LPCSTR = const char *가 됩니다. 

그런데.. 
아마 저 코드에서.. 
(LPSTR)(LPCTSTR) 형변환을 할때 자세히 보면.. 
const 라는 키워드만 떼내는거지요... 
그러니까 사실은 (char *)(const char *)와 같은 말입니다. 
웃기는 형변환이죠.. 
그럼 없어도 될까요? 
^^ 

없으면 당연히 오류가 나게됩니다. 
왜냐면...(LPSTR)CString을 하면.... CString형 자료의 맨 처음 주소부터 char * 형으로 형변환하기 때문이죠. 
CString형은 앞의 16Byte를 자료형을 표현하기 위해서 사용하기 때문에, 여기서부터 형 변환을 해주면 엉뚱한 값이 표현되게 됩니다. 

따라서 MFC에서 지원하는 CString class는 LPCTSTR라는 함수를 통해서 일단 안전하게 const char * 형으로 바뀐 자료형을 얻어오게 하는거죠. 

CString myString; 
(LPCTSTR)myString;이라고 해주면.. 
myString내부의 string 값을 꺼내오게 도와주는 연산자 또는 함수를 사용하게 된겁니다. 
즉 (LPCTSTR)이란 놈이 반환값이 const char* 인 함수입니다. 
정확하게 표현하면 operator overloading이라는 거지요. 

결과적으로 (LPSTR)(LPCTSTR)myString은 
myString의 내부 string 자료를 함수를 통해 자료를 꺼내온뒤에, char* type으로 안전하게 바꾸어주는 역할을 하게 되는 거지요. 

참고로, 함수의 인자가 char * 인곳에 const char* 형을 넣으면 컴파일 오류가 발생하기 때문에 (LPSTR)을 한번더 앞에 써주어서 강제 type casting을 한 것입니다. 

'Development > C/C++' 카테고리의 다른 글

[정적변수 static]  (0) 2012.10.12
[char형의 비트셋을 출력하고 싶을 때]  (0) 2012.08.19
[C언어 문법: Bit field (콜론 연산자)]  (0) 2012.06.16
[Call by Value와 Call by Reference]  (1) 2012.05.05
[Event]  (0) 2011.12.01
Posted by cyj4369
,

리눅스 커널 소스를 살펴보다가 스트럭쳐 안에 이상한 형식의 변수 선언을 보았다.

struct task_struct {
     ...
     unsigned did_exec:1;
     ...
};

이런 형태였는데, 변수를 선언한 다음 콜론(:)과 숫자가 오는 형태는 여지껏 본 적이 없었다.
구글링을 하여 찾아보니 bit field라는 이름의 C언어의 문법 중 하나라는 것을 알게 되었다.
미리 이야기하자면 위의 구문은 did_exec라는 1bit짜리 변수를 선언한 것이다.


struct f
{
    unsigned int  flag : 1;   -- bit flag: on(1) 또는 off(0)의 값을 가질 수 있다. --
    signed int    num : 4;   -- signed 4-bit field; -7...7 또는 -8...7의 값을 갖는다. --
    : 3;                            -- 스트럭쳐를 8bit로 맞추기 위한 3bit의 padding bit --
} g;

'Development > C/C++' 카테고리의 다른 글

[char형의 비트셋을 출력하고 싶을 때]  (0) 2012.08.19
[LPSTR, LPCSTR, LPTSTR, LPCTSTR , LPWSTR, LPCWSTR 의 의미‎]  (0) 2012.08.19
[Call by Value와 Call by Reference]  (1) 2012.05.05
[Event]  (0) 2011.12.01
[Semaphore]  (0) 2011.12.01
Posted by cyj4369
,

Call by Value와 Call by Reference

Programming/C/C++ 2010/06/01 23:44


1. value와 reference는 무슨 뜻인가?
먼저, value와 reference를 네이버 영어사전으로 검색해 보겠습니다.

value는 '가치'라는 뜻이 먼저 나오고, 마지막 부분에 "수학용어"로서 '값'이라는 뜻이 있다고 나옵니다.


reference는 '참조'라는 뜻이 많이 쓰이는 편이어서 통합검색부분에 바로 나오는 것 같습니다.

우리가 "지뢰를 모두 안전하게 찾으면 이기는 게임"의 특성을 잘 살려 "지뢰찾기"라고 이름을 짓듯이, 컴퓨터 용어를 지을 때 역시 관련된 특성을 영어로 잘 살리려 할 것입니다. 그래서 Call by Value와 Call by Reference를 알아보기 전에 핵심단어(value와 reference)의 사전적 의미를 알아본 것입니다.
Call by Value는 영어 그대로 값(Value)에 의한(by) 호출(Call)이고, Call by Reference역시 영어 그대로 참조(Reference)에 의한(by) 호출(Call)입니다.

2. Call by Value
Call by Value는 우리말로 "값에 의한 호출"이라는 의미로, 어떤 함수를 호출할 때 전달인자(Parameter)로 데이터 자체를 전달하는 호출 방법입니다.

2.1 스왑함수(Swap Function)의 구현 1
어떤 변수의 값을 서로 바꾸는 작업을 "스왑 한다."라고 합니다. 이는 프로그램을 만들 때 빈번히 일어나는 경우로서, 다음과 같은 작업을 거쳐야 합니다.


사람이야 머리로 두 자료(자료1, 자료2)의 위치를 바꿀 수 있지만, 컴퓨터는 바보(?)라서 임시저장공간이 반드시 있어야 합니다. 위 그림에서 숫자가 매겨진 것이 작업의 순서입니다. 값을 바꿀 자료 두 개(자료1, 자료2)에 대하여

1. "자료1"을 임시저장공간에 복사합니다.
2. "자료2"를 "자료1"에 복사합니다.
3. 임시저장공간에 저장된 "자료1"과 동일한 내용의 자료를 "자료2"에 복사합니다.
4. 필요에 따라 임시저장공간을 제거합니다.

와 같은 작업이 이루어지면 두 자료의 위치가 바뀝니다. 임시저장공간이 있어야 하는 까닭은 2번 과정을 통해 자료1의 내용이 손실되기 때문입니다.
이 내용을 바탕으로 스왑함수를 Call by Value로 구현해보겠습니다.
01./*
02.Call by Value Example 1
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int data1, int data2)
08.{
09.int temp;
10. 
11.temp=data1;
12.data1=data2;
13.data2=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(a, b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

그럴듯하게 모양이 나오는 것 같습니다. 이 예제는 main함수에 선언된 a와 b의 값을 바꾸기 위하여 Swap함수를 만들고, 이를 전달해 값을 바꾸도록 접근하고 있습니다. 다음은 결과입니다.


아니!!! a와 b의 값이 바뀌어야 하는데, 바뀌고 있지 않습니다.

2.2 Call by Value의 방식
2.1에서 Swap함수를 제대로 구현하지 못했습니다. 위의 결과가 그것을 입증하고 있는데요. 그것은 "Call by Value가 값을 전달하기 때문."이라고 설명할 수 있습니다. 위 예제에서는 변수 a와 b를 바꿀 수 있는 어떤 정보를 주지 않고, a값과 b값 자체를 전달하고 있습니다. 그러므로 a와 b의 값은 바뀌지 않습니다. 즉, Swap함수에서는 변수 a와 b의 값이 아닌, data1과 data2의 값이 교환됩니다. 다음 그림을 보면 이해가 빠를 것입니다.


위 예제에서는 변수 a와 b에 대한 정보(주소값)는 주지 않고 a와 b의 값인 10과 20만 주었습니다. data1과 data2는 "아싸가오리!"라고 외치면서 매개변수로 받았을 것입니다. 그리고 그들(data1과 data2)의 값이 바뀌고 끝이 납니다. 이 때, 변수 a와 b에 대한 정보를 주지 않았으니 변수 a와 b의 값을 교환 하고 싶어도 할 수 없게됩니다. 즉, 교환이 일어나는 메모리 주소는 0x0001과 0x0002가 아닌, 0x0003과 0x0004가 됩니다.
Call by Value는 어떤 함수의 전달인수에 특정 값 자체를 전달하는 방식으로, 특정 값 자체를 전달하다 보니 데이터 자체가 큰 경우 전달하는데 오랜시간이 걸립니다. 대신, 함수의 전달인수로 사용된 데이터 자체는 보호됩니다.
가령, 어떤 무시무시한 악당(갑자기 세균맨이 떠오르네요.)이 위의 스왑함수를 개조하여 스왐함수 내의 data1과 data2에 1을 더하는, 누가 악당 아니랄까봐 정말 악당같은 짓을 행하였습니다. 그래도 data1과 data2의 값만 변할 뿐, main함수 내에 있는 변수 a와 b는 변하지 않습니다.

3. Call by Reference
Call by Value를 통해 Call by Reference에 대해 예측하신 분들이 계셨을 것입니다. Call by Reference는 우리말로 "참조에 의한 호출"로서, 어떤 특정한 값이 아닌 그 값에 대한 정보(이를테면 데이터가 저장된 메모리 번지가 값에 대한 정보라고 할 수 있습니다.)를 전달하는 방식입니다.
2.2의 그림을 이용하자면, Call by Value가 변수 a와 b의 값인 10과 20을 전달했다면, Call by Reference는 변수 a와 b의 메모리 번지인 0x0001과 0x0002를 전달하는 방식이라고 보시면 됩니다.

3.1 스왑함수(Swap Function)의 구현 2
위의 2.1에서 교환되지 않았던 스왑함수를 고쳐보겠습니다.
01./*
02.Call by Reference Example 1
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int* data1, int* data2)
08.{
09.int temp;
10. 
11.temp=(*data1);
12.(*data1)=(*data2);
13.(*data2)=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(&a, &b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

2.1에서 data1과 data2가 int형이었던 반면, 이번 예제는 int*형이 되었습니다. 먼저 실행 결과 보겠습니다.


우리가 원하는 모양이 되었습니다. Swap함수를 호출하였더니 a와 b의 값이 바뀌었습니다. 아시는 분은 다 아시겠지만, Swap함수에 변수 a와 b 자체를 전달한 것이 아닌, a와 b의 주소값을 전달하여 a와 b에 접근할 수 있도록 하였습니다. 즉, Swap함수 내에서는 data1과 data2의 값을 바꾸는 것이 아닌, data1과 data2가 가리키는 값(a와 b)을 바꾸기 때문에 변수 a와 b의 교환이 일어납니다. 이를 그림으로 표현하면 다음과 같습니다.


우리가 실질적으로 바꾸어야 할 메모리 주소 공간은 0x0001과 0x0002이므로 이 두 주소값을 전달하여 이를 참조(reference)하여 변수 a와 b의 값을 교환할 수 있도록 유도하는 것이 목적입니다.

3.2 C++의 문법 - 레퍼런스(Reference)
사실, 3.2에는 Call by Reference의 방식에 대해 설명하려고 했습니다만, 3.1에서 충분히 설명한 것 같아 C++의 문법 중 하나인 레퍼런스에 대해 설명하겠습니다.
변수이름은 할당된 메모리 공간의 이름과 같습니다. 그래서, 원래는 메모리 주소를 직접 입력하여 메모리에 접근하여야 하지만, 이는 매우 번거롭고 비효율적인 방법이므로, C와 C++는 메모리 공간에 이름을 붙여 이 이름을 부르면 해당 메모리에 접근하도록 하였습니다.
레퍼런스란, 이름을 부여하는 것입니다. 변수를 선언할 때는 메모리 공간을 할당하면서 그 메모리 공간의 이름을 부여하지만, 레퍼런스는 이미 할당된 메모리 공간에 이름만 추가합니다.
쉽게 말해, 어떤 광고에서 어떤 배우가 한 말처럼 "이미 차려진 밥상에 밥숟가락만 얹었을 뿐"에서 밥숟가락이 레퍼런스가 되는 것입니다.
레퍼런스는 이미 할당된 메모리 공간에 대해서만 이름을 추가적으로 부여할 수 있도록 하는 것이기 때문에, 레퍼런스르 선언할 때에는 반드시 변수이름을 대입하도록 합니다. 레퍼런스를 선언할 때에는 &연산자를 사용합니다.
1.// declaration and initialization of variable
2.int a=10;
3.// declaration and initialization of reference
4.int& refa=a;
5.// .......

위 소스코드에서 refa가 레퍼런스입니다. 이 둘을 선언한 다음부터는 a와 refa는 동일한 변수입니다. 이들의 주소값을 조사해도 같은 주소가 나오고, a값이 변하면 refa값도 변합니다.(그 반대도 성립합니다.)
이것을 이용하면, 위의 스왑함수 예제 2(포인터 버전)를 레퍼런스 버전으로 수정할 수 있겠습니다.
01./*
02.Call by Reference Example 2
03.Programmed by EffortKim
04.*/
05.#include <iostream>
06. 
07.void Swap(int& data1, int& data2)
08.{
09.int temp;
10. 
11.temp=data1;
12.data1=data2;
13.data2=temp;
14.}
15. 
16.int main()
17.{
18.int a=10, b=20;
19. 
20.std::cout<<"Before\na : "<<a<<", b : "<<b<<std::endl;
21.std::cout<<"Swap Function is called.\n";
22.Swap(a, b);
23.std::cout<<"After\na : "<<a<<", b : "<<b<<std::endl;
24.return 0;
25.}

레퍼런스는 변수와 동일하므로 포인터와 같이 주소 참조 연산자(*)를 사용하지 않아도 됩니다. 또한, 초기화 할 때 변수 자체를 대입하므로 전달인수로 주소 역참조 연산자(&)를 사용하지 않아도 됩니다. (이 상황에선 사용하면 안됩니다.) 그러므로 소스코드가 포인터 버전에 비하여 깨끗합니다.

3.3 포인터냐!! 레퍼런스냐!! 그것이 문제로다!!!
Call by Reference를 구현할 때 포인터를 사용할 것인지, 레퍼런스를 사용할 것인지 고민하는 경우가 생깁니다. 두가지 방법에 대한 장단점을 소개할 것이니, 이를 보고 스스로 판단 해 보시길 바랍니다.

먼저, 포인터를 이용했을 경우 전달하는 값이 주소값이므로 &연산자를 사용하거나, 포인터를 사용해 인수로 넘겨주어야 합니다. 이를 통해 값의 변경이 있을 것임을 명시적으로 알려주는 셈이 됩니다. 특히, &연산자를 사용하여 변수의 주소를 넘길 경우엔 대놓고 "값을 변경할 것입니다."라고 광고하는 효과를 얻게됩니다. 이렇게 명시적으로 자료의 변경이 있을 것이라고 알려주면 개발자는 이를 보고 에러를 쉽게 찾아내고 디버그 하기가 수월 할 것입니다. 단, 코드가 지저분해지고(주소 참조 연산자, 주소 역참조 연산자를 모두 사용해야 하기 때문입니다.) 할당되지 않은 메모리 공간을 참조할 수 있는 잠재적인 오류가 숨어있습니다.
그리고, 레퍼런스를 이용했을 경우 변수처럼 사용하다 보니, 메모리를 직접적으로 참조하지 않아 할당되지 않은 메모리 공간을 참조할 가능성은 포인터에 비해 줄어듭니다. 코드도 포인터를 사용했을 경우보다는 더 간결해지기도 합니다. 그러나, 어떤 함수의 전달인수로 레퍼런스를 요하는 경우, 그냥 변수 이름만 적어주면 되기 때문에 이 함수가 지금 전달하려는 값을 변경할 것인지, 변경하지 않을 것인지 함수를 해석하기 전에는 알 수 없습니다. 그러므로 변경되면 안되는 변수를 잘못넘겨주어 변경되게 하는 경우에는 속수무책으로 당하기 쉽상입니다. 이런 경우는 대부분 문법적인 오류는 없기 때문에 컴파일러나 링커에 의해서 에러를 찾지는 못하는 경우가 많고, 디버깅을 통해서 알아내야 하는 부분입니다. 또한, 위의 예제에서 Swap(a, b);만 가지고는 이 Swap함수의 전달인수가 레퍼런스인지, 그냥 값인지 알 수 없습니다. 물론,Swap이라는 이름은 값을 변경할 것이라고 알려주긴 하지만, 만일 이름이 Swap이 아닌 Func나 F일 경우에는 선언부나 정의부를 보지 않는이상 값이 변경될 것인지, 변경되지 않을 것인지 알 수 없습니다.

이를 통해 어떤 방법을 써야 할 지 생각해 보셨나요? 위 문제는 Call by Reference에서가 아닌, 어느 경우에나 발생할 수 있는 경우입니다. 그래서 많은 자료에서 위 문제를 많이 언급하고 있습니다. 경우에 따라 좋은 방법을 쓰는 것이 좋겠지요? ^_^ 좋은게 좋은겁니다.

4. 끝마치면서
간략하게 Call by Value와 Call by Reference에 대해 알아보는 시간을 가졌습니다. 이는 매개변수에 값을 전달할 것인가, 값에 대한 참조를 전달할 것인가에 대한 "전달 방법"입니다. 문법적 내용이 아니라는 뜻입니다. 위에서 두 방법을 알아보았을 때 Call by Value와 Call by Reference를 위한 특벌한 문법내용을 언급한 적은 없습니다. 기본적인 문법내용을 토대로 만들어 낸 것입니다. 그러므로 다른 언어(JAVA, C#등)에서도 적용할 수 있는 방법입니다.
단, Viaual Basic에서는 포인터나 그에 상응하는 문법 내용이 없기 때문에 Call by Value와 Call by Reference를 위한 문법이 따로 존재하는 것으로 알고 있습니다. 이에 대한 자세한 정보는 MSDN 페이지인


을 참고하세요.

'Development > C/C++' 카테고리의 다른 글

[LPSTR, LPCSTR, LPTSTR, LPCTSTR , LPWSTR, LPCWSTR 의 의미‎]  (0) 2012.08.19
[C언어 문법: Bit field (콜론 연산자)]  (0) 2012.06.16
[Event]  (0) 2011.12.01
[Semaphore]  (0) 2011.12.01
[Mutex]  (0) 2011.12.01
Posted by cyj4369
,

[Event]

Development/C/C++ 2011. 12. 1. 20:32


출처
http://jurang5.tistory.com/entry/CreateEvent-사용하기

'Development > C/C++' 카테고리의 다른 글

[C언어 문법: Bit field (콜론 연산자)]  (0) 2012.06.16
[Call by Value와 Call by Reference]  (1) 2012.05.05
[Semaphore]  (0) 2011.12.01
[Mutex]  (0) 2011.12.01
[CriticalSection]의 사용  (0) 2011.12.01
Posted by cyj4369
,

[Semaphore]

Development/C/C++ 2011. 12. 1. 20:18

Semaphore

Mutex와 상당히 유사하다. 물론 Mutex와 비교해서 Semaphore는 다른 특징도 지니고 있다.

Semaphore 함수
1. Semaphore 생성 함수
HANDLE CreateSemaphore (LPSECURITY_ATTRIBUTES     lpSemaphoreAttributes, //보안 속성
LONG       lInitialCount,            // Semaphore의 생성 시 초기값 설정

LONG       lMaximumCount,     // Semaphore가 지닐 수 있는 최대 카운트 값을 결정

LPCTSTR  lpName                  // 생성되는 Semaphore에 이름을 줄 경우 사용

) ;

 

[ 세마포어의 경우, 카운트가 0인 경우 : non-signaled 상태, 0보다 큰 경우 : signaled 상태 ]

2. Semaphore 반환 함수
BOOL   ReleaseSemaphore (

HANDLE     hSemaphore,         // 반환하고자 하는 Semaphore 핸들

LONG         lReleaseCount,      // 증가시킬 크기 (일반적으로 1을 전달)

LPLONG     lpPreviousCount     // 변경되기 전의 카운트 값을 저장할 변수의 포인터를 전달
) ;

[ 반환한다는 것은 Semaphore의 카운트를 증가시킨다는 것을 의미 ]

'Development > C/C++' 카테고리의 다른 글

[Call by Value와 Call by Reference]  (1) 2012.05.05
[Event]  (0) 2011.12.01
[Mutex]  (0) 2011.12.01
[CriticalSection]의 사용  (0) 2011.12.01
[시스템 함수 정리]  (0) 2011.11.30
Posted by cyj4369
,

[Mutex]

Development/C/C++ 2011. 12. 1. 20:04

Mutex (Mutual Exclusion)

CRITICAL_SECTIOn 오브젝트 이용한 방법과 상당히 유사하다. 따라서 Mutex 또한 열쇠라고 생각하고 이해하기 바란다.

 

Mutex 오브젝트 함수
1. Mutex 오브젝트를 생성하는 함수 
HANDLE CreateMutex ( 

LPSECURITY_ATTRIBUTES    lpMutexAttributes,      // 생성된 핸들을 자식 프로세스가 상속 받도록 할 것인가에 대한 설정

BOOL      bInitialOwner,  // TRUE 전달시, 생성된 Mutex의 소유자가 함수를 호출한 쓰레드로 초기화

                                    // FALSE 전달시, Mutex의 소유자가 존재하지 않음

LPCTSTR lpName      // 생성되는 Mutex에 이름을 줄 경우 사용되는 인자 
) ; 

2. 임계 영역에 들어가기 위해 Mutex를 얻는 함수

WaitForSingleObject 함수가 Mutex를 소유하는 역할을 한다.

(이 함수는 커널 오브젝트가 non-signaled 상태에서 signaled 상태가 되기를 기다리는 함수이다.

  타임 아웃을 설정하여 무한 대기 상태에 빠지는 것을 막을 수도 있다.)
 

3. 임계 영역을 나갈 때 Mutex를 반환하는 함수

BOOL ReleaseMutex ( HANDLE hMutex ) ;        // 반환하고자 하는 Mutex를 인자로 전달

 
4. Mutex를 소멸하는 함수

BOOL CloseHandle ( HANDLE  hObject ) ;         // 소멸하고자 하는 커널 오브젝트의 핸들을 전달

Mutex 오브젝트 소유자가 존재하는 경우 non-signaled 상태, 소유자가 존재하지 않는 경우 signal 상태가 된다.

 

 
 

'Development > C/C++' 카테고리의 다른 글

[Event]  (0) 2011.12.01
[Semaphore]  (0) 2011.12.01
[CriticalSection]의 사용  (0) 2011.12.01
[시스템 함수 정리]  (0) 2011.11.30
[Mutex Thread 동기화 예제]  (0) 2011.11.30
Posted by cyj4369
,

InitializeCriticalSection()

 

하나의  공통 데이터(변수나 기타 등등) 를 특정 thread가 사용중이라면

다른 Thread들이 접근하지 못하도록 EnterCriticalSection() 로 락을 겁니다.

 

그때 그 CriticalSection, 임계영역이라고 합니다. 

그 영역을 초기화 해주는 부분입니다.

 

CriticalSection은  Multi Thread에서 가장 일반적으로 사용되는 방법이랍니다.

Multi Thread 에서 동기화하는 방법으로는 CriticalSection, Mutex, Semaphore 방법이 있습니다.

 

Win32에서의 임계영역

Win32에 대한 코드는 모두 C++를 사용했다. Win32에서의 임계영역은 다음과 같은 순서로 한다

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

//임계영역을 선언한다.
CRITICAL_SECTION cs;

//임계영역을 초기화 한다.
InitializeCriticalSection(&cs);

//임계영역으로 들어간다. 여기서는 한 번에 하나의 Thread만
//임계영역에 들어갈 수 있으며, 이미 임계영역에 들어간 
//Thread가 있으면 다른 Thread는 여기서 대기한다.


EnterCriticalSection(&cs);
try {

     // 한번에 하나의 Thread에 의해서만 실행될 수 있는 블럭이다.

}
finally {
     LeaveCriticalSection(&cs); //임계영역을 빠져나온다.
}
      DeleteCriticalSection(&cs); //임계영역을 정리한다.

'Development > C/C++' 카테고리의 다른 글

[Semaphore]  (0) 2011.12.01
[Mutex]  (0) 2011.12.01
[시스템 함수 정리]  (0) 2011.11.30
[Mutex Thread 동기화 예제]  (0) 2011.11.30
[Sleep함수]  (0) 2011.11.29
Posted by cyj4369
,

*유니코드기반의함수

SBCS 함수

WBCS 기반의 문자열 조작 함수

strlen

size_t wcslen(const wchar_t* string);

Strcpy

wchar_t* wcscpy(wchar_t* dest,const wcahr_t* src)

strncpy

wchar_t* wcsncpy(wchar_t* dest,const wchar_t* src, size_t cnt)

strcat

wchar_t* wcscat(wchar_t* dest,const wchar_t* src)

strncat

wchar_t* wcsncat(wchar_t* dest,const wchar_t* src,size_t cnt)

strcmp

int wcscmp(const wchar_t* s1,const wchar_t* s2)

Strncmp

int wcsncmp(const wchar_t* s1,const wchar_t* s2, size_t cnt)

* 문자열 입출력 함수

SBCS 함수

WBCS 기반의 문자열 입출력 함수

printf

int wprintf(const wchar_t* format [,argument]..);

scanf

int wscanf(const wchar_t* format [,argument]..);

fgets

wchar_t* fgetws (wchar_t* string,int n,

fputs

int fputws (const wchar_t* string,FILE* stream);

* 참고

_wsetlocale(LC_ALL,L"korean"); // #include<locale.h>

=> 유니코드기반으로한글을출력하고싶을사용한다.

=> 함수는나라지역에대한정보를설정하는사용되는함수다.

*tchar.h 헤더파일을참고.

===================================================== 2 ========================================================================

*GetLastError()함수

=> 에러코드를 반환해 준다.

============================================5 장 =============================================================

*GetCurrentDirectory() 함수

원형

DWORD WINAPI GetCurrentDirectory( __in DWORD nBufferLength, __out LPTSTR lpBuffer);

- 인자 값으로 버퍼의 길이와 버퍼의 주소를 넘겨 준다.

*SetCurrentDirecotry() 함수

원형

BOOL WINAPI SetCurrentDirectory( __in LPCTSTR lpPathName);

- 인자 값으로 경로를 세팅해준다. 주소 값.

*CreateProcess() 함수

원형

BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);

원본 위치 <http://msdn.microsoft.com/en-us/library/ms682425%28v=VS.85%29.aspx>

- 인자 값은 5장 CreateProcess판을 참고할 것!!!

*ZeroMemory() 함수

원형

void ZeroMemory( [in] PVOID Destination, [in] SIZE_T Length);

-> PVOID == void*

-> ULONG_PTR == SIZE_T, *PSIZE_T;

=========================================6 장 ================================================

*SetPriorityClass() 함수

- 커널 오브젝트에 저장된 프로세스 우선순위를 높인다.

원형

BOOL WINAPI SetPriorityClass( __in HANDLE hProcess, __in DWORD dwPriorityClass);

- 핸들 값과 , 높일 우선순위가 넘어간다.

*GetCurrentProcess() 함수

- 현재 프로세스의 핸들 정보가 반환 된다.

원형

HANDLE WINAPI GetCurrentProcess(void);

*CloseHandle() 함수

- 핸들 테이블의 핸들을 제거 해주고 커널 오브젝트의 UC를 줄여준다.

원형

BOOL WINAPI CloseHandle( __in HANDLE hObject);

*TerminateProcess() 함수

- 강제로 종료를 요청하는 함수

- 되도록이면 안 쓰는 것이 좋다.

원형

BOOL WINAPI TerminateProcess( __in HANDLE hProcess, __in UINT uExitCode);

================================================7 장 =================================================

*CreateMailslot() 함수

- 메일 슬롯 생성.

원형

HANDLE WINAPI CreateMailslot(

__in LPCTSTR lpName,

__in DWORD nMaxMessageSize,

__in DWORD lReadTimeout,

__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes

);

-> lpName: 생성하는 메일슬롯의 이름을 결정

-> nMaxMessageSize: 메일슬롯의 버퍼 크기를 지정. 0이 전달되면 시스템이 허용하는 최대 크기로 지정.

-> lReadTimeout: 메일슬롯을 통해 전송된 데이터를 읽기 위해서 파일 입출력 함수인 ReadFile 함수가 사용되는데 메일 슬롯이 비어 있다면 데이터가 채워질 때 까지 blocking을 하게 되

데 최대 블로킹 시간을 정해준다. MAILSLOT_WAIT_FOREVER를 인자로 전달하면 무한 블로킹. 0 일 경우 그냥 빠져 나옴.

-> lpSecurityAttributes: 핸들을 상속하기 위한 용도.

*WaitForSingleObject() 함수

- 커널 오브젝트의 상태를 확인할 수 있음.

- Signaled 상태가 되었을 때 반환된다.

- 뮤텍스를 얻을 때에도 쓴다.

원형

DWORD WINAPI WaitForSingleObject(

__in HANDLE hHandle,

__in DWORD dwMilliseconds

);

- hHandle : 커널 오브젝트의 핸들 전달

- dwMilliseconds : 대기 시간 설정. INFINITE를 인자로 전달하면, 무한정 기다림.

- 반환 값 [표]

Return code/value

Description

WAIT_ABANDONED

0x00000080L

정상적이지못한오류발생에의해서반환

WAIT_OBJECT_0

0x00000000L

시그널상태였을반환

WAIT_TIMEOUT

0x00000102L

시간초과

WAIT_FAILED

(DWORD)0xFFFFFFFF

The function has failed. To get extended error information, call GetLastError.

* WaitForMultipleObjects() 함수

원형

DWORD WINAPI WaitForMultipleObjects(

__in DWORD nCount, //배열에 저장된 핸들 개수

__in const HANDLE *lpHandles, // 핸들을 저장하고 있는 배열의 주소

__in BOOL bWaitAll, // 모두 Signaled 상태가 되기(TRUE)를 기다리고자 하는지, 아니면 하나라도 Signaled 상태 반환(FALSE)인지 결정

__in DWORD dwMilliseconds //대기 시간.

);

=> 커널 오브젝트가 둘 이상이고, 핸들이 배열로 묶여 있을 때 가능.

*GetExitCodeProcess() 함수

- 종료 코드를 가져오는 함수.

원형

BOOL WINAPI GetExitCodeProcess(

__in HANDLE hProcess,

__out LPDWORD lpExitCode

);

========================================= 8 장 ===========================================================

*GetCurrentProcess() 함수

- 현재 프로세스의 가짜 핸들을 반환

원형

HANDLE WINAPI GetCurrentProcess(void);

*DuplicateHandle() 함수

- 핸들을 복제 함

원형

BOOL WINAPI DuplicateHandle(

__in HANDLE hSourceProcessHandle, // 복제할 핸들을 소유한 프로세스

__in HANDLE hSourceHandle, // 복제할 핸들

__in HANDLE hTargetProcessHandle, // 복제된 핸들을 소유할 프로세스

__out LPHANDLE lpTargetHandle, // 복제된 핸들 값을 저장할 변수의 주소!!

__in DWORD dwDesiredAccess, // 걍 null

__in BOOL bInheritHandle, //상속 여부

__in DWORD dwOptions //옵션.

);

*CreatePipe() 함수

- 이름 없는 파이프를 생성해주는 함수

- 두 개의 핸들을 얻게 됨.

원형

BOOL WINAPI CreatePipe(

__out PHANDLE hReadPipe, //읽는 핸들

__out PHANDLE hWritePipe, //쓰는 핸들

__in_opt LPSECURITY_ATTRIBUTES lpPipeAttributes,

__in DWORD nSize

);

*CreateNamedPipe() 함수

- 이름 있는 파이프를 생성해주는 함수

- 이름있는 파이프를 만듬.

원형

HANDLE WINAPI CreateNamedPipe(

__in LPCTSTR lpName, // 파이프 이름 지정. 형식: \\.\pipe\pipename

__in DWORD dwOpenMode, //파이프 읽기 또는 쓰기 모드 설정.

__in DWORD dwPipeMode, // 모드 설정.( 데이터 전송 타입, 데이터 수신 타입, 블로킹 모드. 3가지 설정)

__in DWORD nMaxInstances, // 파이프의 최대 개수

__in DWORD nOutBufferSize, // 파이프의 출력 버퍼 사이즈

__in DWORD nInBufferSize, // 입력 버퍼 사이즈

__in DWORD nDefaultTimeOut, // 만료 시간

__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes //보안 속성.

);

*dwPipeMode에 대한 추가 설명

데이터 전송 방식

PIPE_TYPE_BYTE(바이트), PIPE_TYPE_MESSAGE(메시지) : 바이너리 형태로 전송할 것인지 메시지 방식으로 전송할 것 인지 선택

데이터 수신 방식

PIPE_READMODE_BYTE(바이트), PIPE_TYPE_MESSAGE(메시지) : 바이너리 방식(바이트 스트림)으로 읽을 지 메시지 방식으로 읽을지

함수 리턴 방식

PIPE_WAIT(블로킹), PIPE_NOWAIT(넌-블로킹) :무조건 PIPE_WAIT을 전달.

*ConnectNamePipe() 함수

파이프를 연결 요청 대기 상태로 변경시킬 때 사용하는 함수.

원형

BOOL WINAPI ConnectNamedPipe(

__in HANDLE hNamedPipe,

__inout_opt LPOVERLAPPED lpOverlapped

);

*WaitNamedPipe() 함수

- 서버의 대기 시간에 따라 클라이언트를 대기하게 끔 만들어 줌

원형

BOOL WINAPI WaitNamedPipe(

__in LPCTSTR lpNamedPipeName, //파이프 이름

__in DWORD nTimeOut // 대기 시간

);

*SetNamedPipeHandleState() 함수

- 파이프의 모드를 변경시켜준다.

원형

BOOL WINAPI SetNamedPipeHandleState(

__in HANDLE hNamedPipe, //파이프 이름

__in_opt LPDWORD lpMode, //읽기 모드와 함수 리턴방식에 대한 값을 전달.

__in_opt LPDWORD lpMaxCollectionCount, //버퍼링할 수 있는 바이트 크기

__in_opt LPDWORD lpCollectDataTimeout // 버퍼링을 허용하는 최대 시간. 클라이언트와 서버가 같은 PC 상에서 동작한다면 반드시 NULL을 전달해야 한다.

);

*FlushFileBuffers() 함수

- 파일 버퍼를 비우는 역할. 비우면서 전송하는 것?

원형

BOOL WINAPI FlushFileBuffers(

__in HANDLE hFile

);

*DisconnectNamedPipe() 함수

- 클라이언트가 에러 메시지를 받을 수 있도록 도와준다.

원형

BOOL WINAPI DisconnectNamedPipe(

__in HANDLE hNamedPipe

);

*SetEnvironmentVariable() 함수

- 환경변수에 등록한다.

원형

BOOL WINAPI SetEnvironmentVariable(

__in LPCTSTR lpName, //Key

__in_opt LPCTSTR lpValue //value

);

*GetEnvironmentVariable() 함수

- 환경 변수를 key를 통해 value 값을 가지고 와서 버퍼에 저장한다.

원형

DWORD WINAPI GetEnvironmentVariable(

__in_opt LPCTSTR lpName, //key

__out_opt LPTSTR lpBuffer, // value가 담길 버퍼

__in DWORD nSize // 버퍼 사이즈

);

===================================12 장 =========================================

*CreateThread() 함수

- 쓰레드를 생성해주는 함수

원형

HANDLE WINAPI CreateThread(

__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, //핸들의 상속여부를 결정.

__in SIZE_T dwStackSize, //스택 사이즈

__in LPTHREAD_START_ROUTINE lpStartAddress, //함수 포인터

__in_opt LPVOID lpParameter, //함수 전달 인자

__in DWORD dwCreationFlags,

__out_opt LPDWORD lpThreadId //쓰레드 식별자

);

*GetExitCodeThread() 함수

- 쓰레드 종료 시 반환 되는 값을 얻을 수 있다.

원형

BOOL WINAPI GetExitCodeThread(

__in HANDLE hThread,

__out LPDWORD lpExitCode

);

*ExitThread() 함수

- 특정 위치에서 쓰레드의 실행을 종료

원형

VOID WINAPI ExitThread(

__in DWORD dwExitCode

);

- 커널 오브젝트에 등록되는 쓰레드 종료코드를 지정.

*TerminateThread() 함수

- 외부에서 쓰레드를 종료

원형

BOOL WINAPI TerminateThread(

__inout HANDLE hThread,

__in DWORD dwExitCode

);

*_beginthreadex() 함수

- 임계영역에 접근 문제를 해결 하기 위해 독립된 메모리를 할당해준다.

원형

uintptr_t _beginthreadex(

void *security,

unsigned stack_size,

unsigned ( *start_address )( void * ),

void *arglist,

unsigned initflag,

unsigned *thrdaddr

);

*_endthreadex() 함수

- 쓰레드에 할당된 메모리 블록을 해제하는 역할

원형

void _endthreadex(

unsigned retval

);

*SuspendThread() 함수

- Running 상태의 Thread를 Blocked 상태로 만들어 준다

- suspend count를 증가시키는 역할.

원형

DWORD WINAPI SuspendThread(

__in HANDLE hThread

);

*ResumeThread() 함수

- Blocked 상태의 Thread를 Ready 상태로 만들어 준다.

- suspend count를 감소시키는 역할

원형

DWORD WINAPI ResumeThread(

__in HANDLE hThread

);

*SetThreadPriority() 함수

- 쓰레드의 우선순위 세팅

원형

BOOL WINAPI SetThreadPriority(

__in HANDLE hThread,

__in int nPriority

);

- 우선순위는 참고할 것.

*GetThreadPriority() 함수

- 쓰레드의 우선순위를 가져오는 함수

원형

int WINAPI GetThreadPriority(

__in HANDLE hThread

);

============================================ 13 장 ==================================================

*InitializeCriticalSection() 함수

- 크리티컬 섹션 오브젝트를 초기화 해주는 함수

원형

void WINAPI InitializeCriticalSection(

__out LPCRITICAL_SECTION lpCriticalSection

);

*EnterCriticalSection() 함수

- 임계영역에 접근 하기 위해서 크리티컬 섹션 오브젝트를 획득하는 함수

원형

void WINAPI EnterCriticalSection(

__inout LPCRITICAL_SECTION lpCriticalSection

);

*LeaveCriticalSection() 함수

- 임계영역을 빠져 나와서 크리티컬 섹션 오브젝트를 반환하는 함수

원형

void WINAPI LeaveCriticalSection(

__inout LPCRITICAL_SECTION lpCriticalSection

);

*DeleteCriticalSection() 함수

- 크리티컬 섹션 오브젝트의 리소스를 반환 해주는 함수,

원형

void WINAPI DeleteCriticalSection(

__inout LPCRITICAL_SECTION lpCriticalSection

);

-------- 위에는 크리티컬 기반의 동기화에 사용 되는 함수들 --------------

* InterlockedIncrement() 함수

- 임계영역의 값을 동기화 시키고 +1 시켜주는 함수.

원형

LONG __cdecl InterlockedIncrement(

__inout LONG volatile *Addend

);

*InterlockedDecrement() 함수

- 임계영역의 값을 동기화 시키고 -1 시켜주는 함수.

원형

LONG __cdecl InterlockedDecrement(

__inout LONG volatile *Addend

);

------- 위에는 인터락 함수를 이용한 동기화에 사용되는 함수들 -----------------------

*CreateMutex() 함수

- 뮤텍스의 커널 오브젝트의 핸들 값을 반환 한다.

원형

HANDLE WINAPI CreateMutex(

__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,

__in BOOL bInitialOwner,

__in_opt LPCTSTR lpName

);

*ReleaseMutex() 함수

- 뮤텍스를 Signaled 상태로 만들어 주는 함수

원형

BOOL WINAPI ReleaseMutex(

__in HANDLE hMutex

);

*OpenMutex() 함수

- 이름있는 뮤텍스의 핸들을 가져 온다.

원형

HANDLE WINAPI OpenMutex(

__in DWORD dwDesiredAccess, //뮤텍스로의 접근권한을 지정.

__in BOOL bInheritHandle, // 핸들 상속.

__in LPCTSTR lpName //뮤텍스의 이름.

);

========================================== 14 장 =========================================================

*CreateEvent() 함수

- 이벤트 오브젝트를 생성하는데 사용 되는 함수.

원형

HANDLE WINAPI CreateEvent(

__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,

__in BOOL bManualReset, // 수동 리셋(TRUE), 자동리셋(FALSE)

__in BOOL bInitialState, //signaled=TRUE, non-signaled=FALSE

__in_opt LPCTSTR lpName

);

*ResetEvent() 함수

- 수동으로 이벤트 오브젝트를 non-signaled로 바꿔 줄 때 사용

원형

BOOL WINAPI ResetEvent(

__in HANDLE hEvent

);

*SetEvent() 함수

- 이벤트 오브젝트를 signaled 상태로 바꿔 줄 때 사용.

원형

BOOL WINAPI SetEvent(

__in HANDLE hEvent

);

*CreateWaitableTimer() 함수

- 타이머 오브젝트를 생성해주는 함수.

- 타이머 오브젝트는 무조건 non-signaled 상태로 생성된다.

원형

HANDLE WINAPI CreateWaitableTimer(

__in_opt LPSECURITY_ATTRIBUTES lpTimerAttributes,

__in BOOL bManualReset,

__in_opt LPCTSTR lpTimerName

);

*SetWaitableTimer() 함수

- signaled로 바꿀 타이머 설정하는 함수.

원형

BOOL WINAPI SetWaitableTimer(

__in HANDLE hTimer,

__in const LARGE_INTEGER *pDueTime,

__in LONG lPeriod,

__in_opt PTIMERAPCROUTINE pfnCompletionRoutine,

__in_opt LPVOID lpArgToCompletionRoutine,

__in BOOL fResume

);

===================================== 17 장 ========================================

*RaiseException() 함수

- 소프트웨어 예외를 발생시키는 역할.

원형

void WINAPI RaiseException(

__in DWORD dwExceptionCode, // 발생시킬 예외의 형태를 지정

__in DWORD dwExceptionFlags, // 예외발생 이후의 실행방식에 있어서 제한을 둘 때 사용한다.

__in DWORD nNumberOfArguments, // 추가정보의 개수를 지정한다.

__in const ULONG_PTR *lpArguments // 추가정보를 전달한다.

);

1. dwExceptionCode에 대한 설명

=> dwExeptionCode에서 bit 단위 별 의미.

=> C: 커스텀 or Microsoft

=> R: Reserved

=> Sev: 심각 정도. 이건 표 참고(p571)

=> Code: Exception Code를 의미

2. dwExecptionFlags에 대한 설명

- EXEPTION_CONTINUE_EXECUTION을 넘겨 주면 EXECTION_CONTINUEW_EXECUTION의 예외처리 흐름을 막는 용도로 사용된다.

======================================== 18 장 ======================================

* CreateFile() 함수

- 파일을 생성하거나 열 때 핸들 값을 얻어오는 함수.

원형

HANDLE WINAPI CreateFile(

__in LPCTSTR lpFileName, //파일 이름.

__in DWORD dwDesiredAccess, // 읽기/쓰기 모드.

__in DWORD dwShareMode, // 파일 공유 방식 지정.

__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 보안 속성.

__in DWORD dwCreationDisposition, // 파일이 생성 되는 방법.

__in DWORD dwFlagsAndAttributes, // 파일의 특성 정보를 설정.

__in_opt HANDLE hTemplateFile // 기존에 존재하는 파일과 동일한 특성을 가지는 새 파일을 만들 때 사용.

);

-> 기타 속성 값은 MSDN을 참고 할 것.

*ReadFile() 함수

- 파일에 데이터를 읽을 때 사용하는 함수

원형

BOOL WINAPI ReadFile(

__in HANDLE hFile, //읽을 파일 핸들

__out LPVOID lpBuffer, //읽은 데이터를 저장할 버퍼의 주소 값.

__in DWORD nNumberOfBytesToRead, // 읽어 들일 데이터의 크기

__out_opt LPDWORD lpNumberOfBytesRead, // 읽어 들인 데이터의 크기의 변수 주소 값.

__inout_opt LPOVERLAPPED lpOverlapped //

);

*WriteFile() 함수

- 파일에 데이터를 쓸 때 사용하는 함수

원형

BOOL WINAPI WriteFile(

__in HANDLE hFile,

__in LPCVOID lpBuffer,

__in DWORD nNumberOfBytesToWrite,

__out_opt LPDWORD lpNumberOfBytesWritten,

__inout_opt LPOVERLAPPED lpOverlapped

);

*GetFiletime() 함수

- MAC 타임을 얻기 위한 함수.

- FILETIME 구조체는 시간 정보를 나타내는 8바이트 자료형. UTC 기반으로 시간을 표현해 준다.

원형

BOOL WINAPI GetFileTime(

__in HANDLE hFile,

__out_opt LPFILETIME lpCreationTime,

__out_opt LPFILETIME lpLastAccessTime,

__out_opt LPFILETIME lpLastWriteTime

);

* FileTimeToSystemTime() 함수

- 시간 포멧을 변경해준다.

원형

BOOL WINAPI FileTimeToSystemTime(

__in const FILETIME *lpFileTime,

__out LPSYSTEMTIME lpSystemTime

);

* 시간 포멧 변경 시 필요한 구조체.

typedef struct _SYSTEMTIME {

WORD wYear;

WORD wMonth;

WORD wDayOfWeek;

WORD wDay;

WORD wHour;

WORD wMinute;

WORD wSecond;

WORD wMilliseconds;

} SYSTEMTIME, *PSYSTEMTIME;

*SystemTimeToTzSpecificLocalTime() 함수

- UTC를 지역별, 국가별 시간대로 변경해준다.

원형

BOOL WINAPI SystemTimeToTzSpecificLocalTime(

__in_opt LPTIME_ZONE_INFORMATION lpTimeZone, //시간대에 대한 정보.NULL 전달 시 현재 시스템의 시간대 정보가 기준이 된다.

__in LPSYSTEMTIME lpUniversalTime,

__out LPSYSTEMTIME lpLocalTime

);

*GetFileSize() 함수

- file사이즈를 가져오는 함수

- 4G이상은 불가.

원형

DWORD WINAPI GetFileSize(

__in HANDLE hFile,

__out_opt LPDWORD lpFileSizeHigh

);

*GetFileSizeEx() 함수

-4G 이상의 파일 사이즈를 얻어주는 함수

원형

BOOL WINAPI GetFileSizeEx(

__in HANDLE hFile,

__out PLARGE_INTEGER lpFileSize

);

-> LARGE_INTEGER 구조체에는 8Byte를 상하위 비트로 나누어서 담는다.

*GetFileAttributes() 함수

- 파일 특성 정보는 반환 값으로 담긴다.

원형

DWORD WINAPI GetFileAttributes(

__in LPCTSTR lpFileName

);

- 32 bit DWORD 값에 비트 별로 속성 값이 들어 가게 된다. 총 12가지 정보가 들어간다.

- 비트 별 정보는 msdn을 참고할 것!

*SetFileAttributes() 함수

- 파일 특성 정보를 세팅한다

원형

BOOL WINAPI SetFileAttributes(

__in LPCTSTR lpFileName,

__in DWORD dwFileAttributes

);

*GetFileInformationByHandle() 함수

- 핸들을 이용해 파일 정보를 얻어오는 함수

원형

BOOL WINAPI GetFileInformationByHandle(

__in HANDLE hFile,

__out LPBY_HANDLE_FILE_INFORMATION lpFileInformation

);

*_BY_HANDLE_FILE_INFORMATION의 원형

typedef struct _BY_HANDLE_FILE_INFORMATION {

DWORD dwFileAttributes;

FILETIME ftCreationTime;

FILETIME ftLastAccessTime;

FILETIME ftLastWriteTime;

DWORD dwVolumeSerialNumber;

DWORD nFileSizeHigh;

DWORD nFileSizeLow;

DWORD nNumberOfLinks;

DWORD nFileIndexHigh;

DWORD nFileIndexLow;

} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;

*GetFullPathName() 함수

- 파일 이름을 통해서 파일경로 정보를 얻어주는 함수

원형

DWORD WINAPI GetFullPathName(

__in LPCTSTR lpFileName,

__in DWORD nBufferLength, //저장 가능한 문자열의 길이임을 주의할 것!!

__out LPTSTR lpBuffer,

__out LPTSTR *lpFilePart //버퍼의 특정 위치를 가리키는 포인터 값이 저장. 마지막 역슬래시 다음 번지 주소 값이 저장됨.

);

*SetFilePointer() 함수

- 파일 포인터의 위치를 정해준다.

원형

DWORD WINAPI SetFilePointer(

__in HANDLE hFile,

__in LONG lDistanceToMove, //32bit 기반일 때 이 인자 값만 사용. 이동시킬 거리를 지정.

__inout_opt PLONG lpDistanceToMoveHigh, //64bit 기반일 때 상위 4Byte 값이 담긴다. 32bit에서는 NULL 전달.

__in DWORD dwMoveMethod

);

*CreateDirectory() 함수

- 디렉터리 생성.

원형

BOOL WINAPI CreateDirectory(

__in LPCTSTR lpPathName,

__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes

);

*RemoveDirectory() 함수

- 디렉토리 제거

원형

BOOL WINAPI RemoveDirectory(

__in LPCTSTR lpPathName

);

*GetCurrentdirectory() 함수

- 현재 디렉토리를 얻어온다.

원형

DWORD WINAPI GetCurrentDirectory(

__in DWORD nBufferLength,

__out LPTSTR lpBuffer

);

*SetCurrentDirectory() 함수

- 현재 디렉토리 위치를 변경한다.

원형

BOOL WINAPI SetCurrentDirectory(

__in LPCTSTR lpPathName

)

* GetSystemDirectory() 함수

- 시스템 디렉터리의 위치를 얻어온다.

원형

UINT WINAPI GetSystemDirectory(

__out LPTSTR lpBuffer,

__in UINT uSize

);

*GetWindowsDirectory() 함수

- window 디렉토리의 위치를 얻어온다

원형

UINT WINAPI GetWindowsDirectory(

__out LPTSTR lpBuffer,

__in UINT uSize

);

*SearchPath() 함수

- 파일의 위치를 찾아준다.

원형

DWORD WINAPI SearchPath(

__in_opt LPCTSTR lpPath,

__in LPCTSTR lpFileName,

__in_opt LPCTSTR lpExtension,

__in DWORD nBufferLength,

__out LPTSTR lpBuffer,

__out_opt LPTSTR *lpFilePart

);

-> 표준 검색 경로

1. 실행 중인 프로그램이 로드 된 디렉토리

2. 현재 디렉토리

3. 시스템 디렉토리

4. windows 디렉토리

5. 환경변수 PATH에 등록된 디렉토리

*FindFirstFile() 함수

- 파일 목록 중 첫 번째 파일의 핸들 값을 반환. 정보는 두 번째 인자에 저장.

원형

HANDLE WINAPI FindFirstFile(

__in LPCTSTR lpFileName,

__out LPWIN32_FIND_DATA lpFindFileData

);

*FindNextFile() 함수

- 파일 목록 중 다음 파일의 핸들 값을 반환. 정보는 두 번째 인자에 저장.

원형

BOOL WINAPI FindNextFile(

__in HANDLE hFindFile,

__out LPWIN32_FIND_DATA lpFindFileData

);

*FindClose() 함수

- 생성된 커널 오브젝트를 해제.

원형

BOOL WINAPI FindClose(

__inout HANDLE hFindFile

);

*파일 정보 저장되는 구조체.

typedef struct _WIN32_FIND_DATA {

DWORD dwFileAttributes;

FILETIME ftCreationTime;

FILETIME ftLastAccessTime;

FILETIME ftLastWriteTime;

DWORD nFileSizeHigh;

DWORD nFileSizeLow;

DWORD dwReserved0;

DWORD dwReserved1;

TCHAR cFileName[MAX_PATH];

TCHAR cAlternateFileName[14];

} WIN32_FIND_DATA, *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;

================================================ 19 장 =====================================

*GetOverlappedResult() 함수

- I/O 연산이 완료된 이후에 전송된 데이터 크기 확인을 위함.

원형

BOOL WINAPI GetOverlappedResult(

__in HANDLE hFile, // 입력 및 출력 결과 학인을 위한 파이프 핸들

__in LPOVERLAPPED lpOverlapped, // overlapped 구조체 변수의 주소 값

__out LPDWORD lpNumberOfBytesTransferred, // 실제 전송이 완료된 바이트 크기를 얻기 위한 변수의 주소 값

__in BOOL bWait // I/O 연산이 끝나지 않은 상황에서의 처리를 결정.

);

*WriteFileEx() 함수

- 완료 루틴이 추가 됨.

원형

BOOL WINAPI WriteFileEx(

__in HANDLE hFile,

__in_opt LPCVOID lpBuffer,

__in DWORD nNumberOfBytesToWrite,

__inout LPOVERLAPPED lpOverlapped,

__in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine //완료 루틴.

);

*ReadFileEx() 함수

- 완료 루틴이 추가 됨

원형

BOOL WINAPI ReadFileEx(

__in HANDLE hFile,

__out_opt LPVOID lpBuffer,

__in DWORD nNumberOfBytesToRead,

__inout LPOVERLAPPED lpOverlapped,

__in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine

);

*OVERLAPPED_COMPLETION_ROUTINE 함수 포인터 모양.

원형

typedef VOID (WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE) (

[in] DWORD dwErrorCode,

[in] DWORD dwNumberOfBytesTransfered,

[in] LPVOID lpOverlapped

);

*SetWaitableTimer() 함수

- 완료 루틴 타이머. 일정 시간이 되면 콜백함수를 호출한다.

원형

BOOL WINAPI SetWaitableTimer(

__in HANDLE hTimer,

__in const LARGE_INTEGER *pDueTime,

__in LONG lPeriod,

__in_opt PTIMERAPCROUTINE pfnCompletionRoutine,

__in_opt LPVOID lpArgToCompletionRoutine,

__in BOOL fResume

);

* SetWaitableTimer 함수의 네 번째 인자 값.

원형

VOID CALLBACK TimerAPCProc(

__in_opt LPVOID lpArgToCompletionRoutine,

__in DWORD dwTimerLowValue,

__in DWORD dwTimerHighValue

);

*QueueUserAPC() 함수

- APC Queue에 호출하고자 하는 함수 정보를 전달 할 때 사용하는 함수

원형

DWORD WINAPI QueueUserAPC(

__in PAPCFUNC pfnAPC, //비동기로 호출될 함수를 지정

__in HANDLE hThread, // APC Queue를 소유하는 쓰레드 핸들을 지정.

__in ULONG_PTR dwData // 등록된 함수 호출 시 전달할 인자.

);

========================================== 20 장 =================================================

*VirtualAlloc() 함수

- 가상 메모리를 할당해주는 함수

- MEM_RESERVE 와 MEM_COMMIT으로 메모리의 상태를 설정해줄 수 있다.

원형

LPVOID WINAPI VirtualAlloc(

__in_opt LPVOID lpAddress, //메모리의 시작 주소. NULL 전달시 임의의 주소 할당됨.

__in SIZE_T dwSize, //할당하고자 하는 메모리의 크기를 바이트 단위로.

__in DWORD flAllocationType, //메모리 할당의 타입을 결정. MEM_RESERVE, MEM_COMMIT

__in DWORD flProtect //페이지별 접근방식에 제한을 두는 용도로 사용.

);

*VirtualFree() 함수

- 할당한 메모리를 해제 해주는 함수.

원형

BOOL WINAPI VirtualFree(

__in LPVOID lpAddress,

__in SIZE_T dwSize,

__in DWORD dwFreeType //MEM_DECOMMIT과 MEM_RELEASE 를 전달.

);

*HeapCreate() 함수

- 힙을 생성하는 함수

원형

HANDLE HeapCreate(

DWORD flOptions, // 생성되는 힙의 특성을 부여 (0 을 전달시 가장 일반적인 힙 생성)

// HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생

// HEAP_NO_SERIALIZE : 생성된 힙의 메모리 할당과 해제에 대해 동기화 처리를 하지 않는다.

SIZE_T dwInitialSize, // dwMaximumSize 에서 지정한 메모리 중에서 초기에 할당할 COMMIT 페이지를 지정한다

SIZE_T dwMaximumSize // 생성되는 힙의 크기 결정.

// 지정하는 크기에 해당하는 페이지의 수만큼 RESERVE 상태가 된다.

// 0이 아닐 경우 힙은 증가 가능 한 메모리(Growable Heap)가 된다

);

출처http://dakuo.tistory.com/128

*HeapDestroy() 함수

- 힘을 해제시키는 함수

원형

BOOL HeapDestroy(

HANDLE hHeap // 반환하고자 하는 힙의 핸들

);

출처http://dakuo.tistory.com/128

*HeapAlloc() 함수

- 힙에 메모리를 할당하는 함수.

- 요청 크기에 해당하는 페이지 수만큼 COMMIT 상태로 변경시킨다.

원형

LPVOID HeapAlloc(

HANDLE hHeap, // 메모리 할당이 이뤄질 힙의 핸들

DWORD dwFlags, // HEAP_GENERATE_EXCEPTIONS : 오류 발생시 NULL이 아닌 예외 발생

// HEAP_NO_SERIALIZE : 함수 호출 시 동기화 처리되지 않는다.

// (HeapCreate 함수호출에서 지정했다면 중복 지정 할 필요는 없다)

// HEAP_ZERO_MEMORY : 할당된 메모리는 0으로 초기화

// 둘 이상의 속성을 비트 단위 연산자 OR( | )로 동시 지정 가능

SIZE_T dwBytes // 할당하고자 하는 메모리의 크기를 지정

// (증가 가능 한 힙이 아닐 경우 최대 크기 0x7FFF8)

);

출처http://dakuo.tistory.com/128

*HeapFree() 함수

- 힙에 메모리를 해제하는 함수

- Reserve 상태도 가능

원형

BOOL HeapFree(

HANDLE hHeap, // 해제할 메모리를 담고 있는 힙을 지정

DWORD dwFlags, // HEAP_NO_SERIALIZE 가 인자로 올 수 있다, 일반적 : 0

// (HeapCreate 함수호출에서 지정했다면 중복지정할 필요는 없다)

LPVOID lpMem // 해제할 메모리의 시작 주소 지정

);

출처http://dakuo.tistory.com/128

*CreateFileMapping() 함수

- 파일 연결 오브젝트 생성을 위한 함수

원형

HANDLE WINAPI CreateFileMapping(

__in HANDLE hFile, //파일 핸들

__in_opt LPSECURITY_ATTRIBUTES lpAttributes, //보안 속성

__in DWORD flProtect, //PAGE_READONLY, PAGE_READWRITE

__in DWORD dwMaximumSizeHigh, // 연결할 메모리 최대 크기의 상위 4 바이트, 대용량 파일이 아니면 보통 0

__in DWORD dwMaximumSizeLow, // 메모리 최대 크기의 하위 4 바이트

__in_opt LPCTSTR lpName // 파일 연결 오브젝트의 이름 지정. NULL을 전달 할 수 있음

);

*MapViewOfFile() 함수

- 파일과 메모리를 실제로 매핑 시켜주는 함수.

원형

LPVOID WINAPI MapViewOfFile(

__in HANDLE hFileMappingObject, // 커널 오브젝트의 핸들

__in DWORD dwDesiredAccess, // 연결된 메모리의 접근권한. CreateFileMapping 함수에대해 종속적이다.?

__in DWORD dwFileOffsetHigh, // 메모리에 연결할 파일의 오프셋을 지정한다.

__in DWORD dwFileOffsetLow, // 오프셋 하위 4 비트

__in SIZE_T dwNumberOfBytesToMap //메모리에 연결할 실제 크기를 바이트 단위로 지정.

);

*UmapViewOfFile() 함수

- 매핑된 메모리를 해제.

원형

BOOL WINAPI UnmapViewOfFile(

__in LPCVOID lpBaseAddress

);

*FlushViewOfFile() 함수

- 메모리에 캐쉬된 데이터를 파일에 저장하게 해주는 함수.

원형

BOOL WINAPI FlushViewOfFile(

__in LPCVOID lpBaseAddress, //파일에 저장할 메모리의 시작 주소

__in SIZE_T dwNumberOfBytesToFlush // 파일에 저장할 데이터 크기를 바이트 단위로 지정.

);

[출처] 시스템 함수 정리|작성자 smuoon4680

'Development > C/C++' 카테고리의 다른 글

[Mutex]  (0) 2011.12.01
[CriticalSection]의 사용  (0) 2011.12.01
[Mutex Thread 동기화 예제]  (0) 2011.11.30
[Sleep함수]  (0) 2011.11.29
[thread에서 _beginthreadex의 void *arglist로 스레드에 여러 인수 넘겨주는 방법]  (0) 2011.11.23
Posted by cyj4369
,

// Kernel object Mutex Thread 동기화 예제
// 1.signaled == 소유가 가능한 상태:
// WaitForSingleObjet 함수를 호출하여 전달된 mutex Handle인자를
// non-signaled 상태로 변경하여 이미 소유되어진 상태로 만든다. (소유 잠금 함수)
// non-signaled == 이미 소유되어진 상태:
// ReleaseMutex 함수를 호출하여 전달된 mutex Handle인자를
// singnaled 상태로 변경하여 소유가능 상태로 만든다. (소유 해제 함수)

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>

DWORD WINAPI ThreadIncrement(void *arg);
void ErrorHandling(char *message);

char thread1[] = "A Thread";
char thread2[] = "B Thread";

// 임계영역에 해당되는 전역변수 선언
// 다중 thread함수에 의해 값이 변경되는 변수
int number = 0;
// 핸들 자료형으로 mutex핸들로 사용할 변수 선언
HANDLE hMutex;

int main(int argc, char *argv[])
{
HANDLE hThread[2]; // 핸들 자료형으로 thread핸들로 사용할 변수 선언
DWORD dwThreadID[2]; // 생성되는 thread의 ID로 사용할 변수 선언

// mutex를 생성
// (보안관련 설정: NULL, 소유여부 설정: FALSE(==signaled) , Mutex이름: NULL)
// 소유가 가능한 상태로 mutex 를 생성
hMutex = CreateMutex(NULL, FALSE, NULL);

// mutex 생성 실패시 처리
if(hMutex==NULL)
ErrorHandling("CreateMutex() Error");

// thread에 안전한 함수 호출 방식으로 thread함수 호출함과 인자를 넘겨 주면서 thread ID생성
hThread[0] = (HANDLE) _beginthreadex(NULL, 0, ThreadIncrement, (void*)thread1, 0, &dwThreadID[0]);
hThread[1] = (HANDLE) _beginthreadex(NULL, 0, ThreadIncrement, (void*)thread2, 0, &dwThreadID[1]);

// thread 생성 실패시 처리
if(hThread[0] == 0 || hThread[1] == 0)
ErrorHandling("_beginthreadex() Error");

// thread함수 처리 종료 까지 대기한다.
if(WaitForMultipleObjects(2, hThread, TRUE, INFINITE) == WAIT_FAILED)
ErrorHandling("WaitForMultipleObjects() Error");

// thread함수에 의해 변경된 임계영역에 해당하는 number 값을 출력
printf("main() function end, last number : %d \n", number);

// 생성되었던 mutex핸들을 소멸 시킨다.
// CloseHandle함수는 어떠한 handle이라도 소멸 시킬수 있다.
// 여기서는 mutex 핸들을 소멸 시키는 것을 보여주고 있다
CloseHandle(hMutex);

return 0;
}

DWORD WINAPI ThreadIncrement( void *arg )
{
int i;

for(i=0; i<5; i++){
// mutex를 non-signaled 상태로 변경(소유를 한다음 소유 불가능 상태로 잠금)
WaitForSingleObject(hMutex, INFINITE);
Sleep(100); // 실행결과를 눈으로 확인 하기 위해 사용 ^^
number++;
printf("Run : %s, number : %d \n", (char*)arg, number);
// mutex를 signaled 상태로 변경(소유를 포기한다음 소유가능 상태로 해제함)
// 참고로 참조하는 부분도 mutex로 묶어준 이유는 참조하는 순간 다른 thread함수에 의해
// 값이 변경되는 것을 막기 위함이다.
ReleaseMutex(hMutex);
}

return 0;
}

void ErrorHandling( char *message )
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}

Posted by cyj4369
,

[Sleep함수]

Development/C/C++ 2011. 11. 29. 20:14
#include <windows.h>헤더 사용

Sleep(1000);
1초 슬립 
Posted by cyj4369
,