// 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
,

<input type="button" onclick="javascript:history.back()" value="뒤로">


<input type="button" onclick="javascript:history.forward()" value="앞으로">


<input type="button" onclick="javascript:history.go(-3)" value="3단계 뒤로">


<input type="button" onclick="javascript:history.go(0)" value="현제 페이지">


<input type="button" onclick="javascript:history.go(3)" value="3단계 앞으로">


window.location.reload(); 또는,

<a href="javascript:location.reload()">새로고침</a>

Posted by cyj4369
,
Old February 25th, 2004, 11:40 AM
Member
 
Join Date: Oct 2003
Posts: 204
urika is an unknown quantity at this point (<10)
putting values in void *arglist

hi ,
i want to run a threads using _beginthread(...)
(no MFC)
inside the threadfunc i want to call a function with many variables.
how do i use the void *arglist so it points to a few variables ?
i hope my question makes sence 
thank u
Reply With Quote
  #2    
Old February 25th, 2004, 11:47 AM
gstercken's Avatar
Moderator
Power Poster
 
Join Date: Sep 2002
Location: 14° 39'19.65"N / 121° 1'44.34"E
Posts: 9,815
gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)
Re: putting values in void *arglist

Quote:
Originally posted by urika 
how do i use the void *arglist so it points to a few variables ?
Usually by creating a class or struct which contains the variables.
You would then use the void* to pass the pointer to an instance of
that class or struct, which you would have to cast back to the actual
type before accessing the members.
__________________
Guido Stercken-Sorrenti
Reply With Quote
  #3    
Old February 25th, 2004, 11:51 AM
Member
 
Join Date: Oct 2003
Posts: 204
urika is an unknown quantity at this point (<10)
thanks!
Reply With Quote
  #4    
Old February 29th, 2004, 05:34 AM
Member
 
Join Date: Oct 2003
Posts: 204
urika is an unknown quantity at this point (<10)
i call a function :
Code:
 bool MapViewInit(GEO p1, GEO p2, DISPLAY Disp, CONTROL Ctrl, HINSTANCE hInst)
{
		MapThreadArgList maparglist;  ////?????
		maparglist.Ctrl=Ctrl;
		maparglist.Disp=Disp;
		maparglist.p1=p1;
		maparglist.p2=p2;
		maparglist.hInst=hInst;
		HANDLE handle1 =(HANDLE)_beginthread( MapThreadFunc,0,
(void *)&maparglist); // create thread COUT << "\n >>> MapViewInit Run Successfully <<<\n"; return true; }
in order to run the thread i do :
Code:
void MapThreadFunc( void* args )
{
		GEO p1;
		GEO p2;
		DISPLAY Disp;
		CONTROL Ctrl;
		HINSTANCE hInst;
		MapThreadArgList arglist = *((MapThreadArgList*)args);
		p1=arglist.p1;
		p2=arglist.p2;
		Disp=arglist.Disp;
		Ctrl=arglist.Ctrl;
		hInst=arglist.hInst;
...
...
...
after i cast back to MapThreadArgList the info in arglist.p1 (and the others ) is lost.
what am i doing wrong?
Reply With Quote
  #5    
Old February 29th, 2004, 06:02 AM
gstercken's Avatar
Moderator
Power Poster
 
Join Date: Sep 2002
Location: 14° 39'19.65"N / 121° 1'44.34"E
Posts: 9,815
gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)gstercken has a reputation beyond repute (3000+)
Quote:
Originally posted by urika 
what am i doing wrong?
You are creating maparglist on the stack - it will be destroyed when it gets out of
scope (when you return from MapViewInit()). Allocate it on the heap, or keep it as a
member variable instead.
__________________
Guido Stercken-Sorrenti
Reply With Quote
  #6    
Old February 29th, 2004, 07:55 AM
Member
 
Join Date: Oct 2003
Posts: 204
urika is an unknown quantity at this point (<10)
thanks , it now works
Reply With Quote

결론
구조체를 사용하여 쓰레드에 넘겨줄 인수를 모두 넣는다. (구조체 정의를 전역변수로 해야 함)
구조체의 객체를 만든 다음 객체멤버에 값을 넣어준다.
통째로 객체를 넘겨준다.
스레드에서 구조체의 객체를 만들어 파라메터의 객체를 받는다.
쓰면된다~ 

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

[Mutex Thread 동기화 예제]  (0) 2011.11.30
[Sleep함수]  (0) 2011.11.29
[CreateThread(), _beginthread(), _beginthreadex()의 차이]  (0) 2011.11.22
[select FD_SET FD_Zero FD_Clr FD_IsSet]  (0) 2011.11.22
[_beginthreadex 형변환문제]  (0) 2011.11.22
Posted by cyj4369
,
윈도우즈에서 스레드를 생성하는 API는 CreateThread(), _beginthread(), _beginthreadex() 이렇게 3개의 함수가 존재합니다. 

CreateThread()와 _beginthread(), _beginthreadex()의 차이점은 다음과 같습니다.
  • CreateThread()는 스레드를 생성하는 기능만 담당한다.
  • _beginthread(), _beginthreadex()는 내부적으로 CreateThread() 를 사용하여 스레드를 생성하고 C Runtime library에서 내부적으로 필요로 하는 메모리 영역을 초기화 해주는 역할을 하게 됩니다. 초기화 되는 메모리 영역은 각 스레드 마다 따로 관리되게 됩니다.


그렇다면 _beginthread(), _beginthreadex()의 차이는 무엇일까요? 의외로 이 차이에 대해서 대답을 명쾌하게 해주는 분이 많지가 않습니다. 이제부터 그 차이를 설명해 보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  
uintptr_t _beginthread( 
   void( *start_address )( void * ),
   unsigned stack_size,
   void *arglist 
);

uintptr_t _beginthreadex( 
   void *security,
   unsigned stack_size,
   unsigned ( *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr 
);

함수 원형을 보고 알 수 있는 파라메터에 의한 차이점은 다음과 같습니다.

  • _beginthreadex()는 security를 이용하여 보안 관련 설정을 할 수 있다.
  • _beginthreadex()는 initflag를 이용하여 스레드의 초기 동작을 정의 할 수 있다.
  • _beginthreadex()는 thrdaddr을 이용하여 thread id를 받을 수 있다.
  • _beginthreadex()는 __stdcall 형식의 함수 포인터를 thread 실행 함수로 받는다.
  • _beginthreadex()는 함수 실행 실패시에 0을 리턴한다. (_beginthread는 -1을 리턴한다.)

여기에 더해서 가장 중요하게 기억해야 할 한가지의 차이점이 더 존재합니다. (이 내용이 글을 쓰는 이유이기도 합니다. ^^)
_beginthread()는 스레드가 생성되고 스레드 함수의 실행이 종료 되면 스레드의 정리 작업을 해주게 됩니다. 이러한 형태는 편리한 점이 있지만 단점도 존재하게 되는데 바로 스레드의 실행 완료후에 해당 스레드의 정보를 조회 할 수 있는 방법이 없다는 것입니다. 

예를 들어 스레드의 종료시에 exit 코드가 무엇인지 알기 위해서 GetExitCodeThread()를 사용할 수 있습니다. 이때 첫번째 인자로 스레드의 핸들을 파라메터로 넘겨줘야 되는데 _beginthread()로 생성된 스레드의 핸들은 GetExitCodeThread()를 사용할 수 없습니다. 

1
2
3
4
BOOL WINAPI GetExitCodeThread(
  HANDLE hThread,
  LPDWORD lpExitCode
);

왜 그럴까요? _beginthread()로 생성된 스레드 핸들은 스레드 함수의 실행이 종료될 때 _beginthread() 내부에서 CloseHandle()을 호출하기 때문에 프로그래머가 GetExitCodeThread()를 사용할 수 있는 시점에서는 이미 소멸된 핸들이 되기 때문입니다.

_beginthreadex()는 위와 같은 문제를 해결하기 위해 스레드가 종료될때 내부적으로 CloseHandle()를 호출하지 않고 사용자가 명시적으로 해제하도록 변경되었습니다.

결과적으로 내용을 정리하면 다음과 같습니다.

  • _beginthread()로 생성된 스레드 핸들은 스레드 종료시에 CloseHandle()이 내부적으로 호출되어 신경쓸 필요가 없지만 스레드 함수 완료 후 스레드 핸들을 이용한 어떠한 API 함수도 실행 시킬 수 없습니다.
  • _beginthreadex()로 생성된 스레드 핸들은 스레드가 실행완료된 후 내부적으로 CloseHandle()을 실행시키지 않기 때문에 스레드 핸들을 이용한 API 함수를 실행할 수 있지만 사용자가 명시적으로 CloseHandle()을 호출해 주어야 합니다. 만약 CloseHandle()을 해주지 않으면 핸들이 계속 쌓이게 되는 Resource leak이 생기게 됩니다.
Posted by cyj4369
,

select

select 함수는 한개 또는 그 이상의 소켓 상태를 결정하고, 동기 입출력을 수행 하기위해 필요할 경우 대기 하는 함수입니다.

int select (
int
nfds,
fd_set FAR *
readfds,
fd_set FAR *
writefds,
fd_set FAR *
exceptfds,
const struct timeval FAR *
timeout
);

Parameters

nfds
[입력] 버클리 소켓과 호환되는 소켓을 제외 하고는 이 매개변수는 무시됩니다. 버클리 소켓에서 이 매개변수는 I/O 변화를 감지 할 총 소켓의 갯수+1 의 값을 지정하는 용도로 사용합니다.

readfds
[입/출력] 읽기상태의 변화를 감지할 소켓을 지정합니다.

writefds
[입/출력] 쓰기상태의 변화를 감지할 소켓을 지정합니다.

exceptfds
[입/출력] 예외상태 변화를 감지할 소켓을 지정합니다.

timeout
[입력]
select 함수가 기다리기 위한 시간입니다. NULL 일경우 지정한 I/O변화가 발생했을 때까지 계속 기다립니다.

Remarks

select 함수는 한개 또는 그 이상의 소켓상태(I/O의 발생유무 상태)를 결정하는데 사용됩니다. FD_SET 구조체의 타입의 인자인 readfds, writefds, exceptfds는 각각 읽기, 쓰기, 예외상황 발생과 같은 I/O변화가 발생 했을 때 이를 감지할 대상이 되는 소켓들을 지정하는 배열형 구조체 입니다. 즉, 이 세가지 구조체를 통하여 어떤 소켓에서 어떤 I/O 변화 발생을 감지할지를 선택하여 지정할 수 있습니다. FD_SET 구조체를 처리하기 위해서 일련의 매크로들이 제공되게 됩니다. 이러한 매크로들은 버클리 소켓과 호환성이 있습니다. 하지만, 내부적인 표현 방법은 근본적으로 다릅니다.

readfds 매개변수에는 "입력받을 수 있는 상태"(readability)와 같은 입력(Input)에 대해 변화가 발생 했을때 감지할 대상이 되는 소켓들을 지정합니다. 예를들어 소켓이 리슨 상태라면, 상대방의 접속의 요청에 대한 감지나, 수신큐에 데이터가 수신되었을 때 이를 감지 할 수 있게 됩니다. 어플리케이션은 이런 상황이 감지 되었을때 접속을 허용 하거나 데이터를 수신할 수 있습니다.

writefds 매개변수에는 "출력 할 수 있는 상태"(writability)와 같은 출력(Output)에 대해 변화가 발생 했을때 감지할 대상이 되는 소켓들을 지정합니다. 예를들어 소켓이 connect 함수를 처리하고 있으며, 소켓이 성공적으로 접속이 완료되었을때 다른 데이터를 송신 할 수 있다 라는 변화의 감지나, sendto, WSASendTo 등의 함수가 성공적으로 수행 될수 있을때가 언제인지 감지 할 수 있게 됩니다. 어플리케이션은 이런 상황이 감지 되었을때 소켓에 대한 다른 처리를 하거나, 데이터를 송신 할 수 있습니다.

exceptfds 매개변수는 out-of-band 데이터의 감지를 위해서, 또는 예외적인 에러 상황을 감지하기 위해서 사용됩니다.

readfds, writefds, 또는 exceptfds 매개변수중 두개는 NULL을 가질 수 있습니다. 하지만, 적어도 한개는 NULL 이면 않됩니다. 또한 NULL이 아닌 FD_SET 구조체는 적어도 한개의 소켓을 가지고 있어야 한다는 점을 명심하세요.

windsock(2).h 헤더 파일에는 소켓기술자 세트(ex. FD_SET)를 처리하기 위해서 4가지 종류의 매크로를 정의 해 놓고 있습니다. FD_SETSIZE 값은 소켓기술자 세트(ex. FD_SET)에 들어갈 수 있는 소켓 기술자의 최대 갯수를 결정하는 수치입니다. (FD_SETSIZE 의 기본치는 64입니다. 이값은 winsock(2).h 헤더파일에서 FD_SETSIZE 가 정의 되어 있지 않을 경우 FD_SETSIZE를 64로 정의 하므로 이 헤더파일을 인클루드 하기전에 다른 값을 FD_SETSIZE에 정의해서 변경 할 수 있습니다.)
내부적으로, 소켓기술자 세트로 사용되는 FD_SET 구조체 안에 있는 소켓핸들은 버클리 유닉스와 같은 비트 플래그로 표현되지 않습니다(버클리 유닉스 에서는 세트되어 있다는 것을 1로 그렇지 않은 것을 0으로 표현하죠.). 이 소켓핸들 데이터 표현법은 확실히 정의된 것이 아닙니다. 이렇게 확실히 정의 해 놓지 않은 이유는, 다른 소켓환경 사이에서 소프트웨어를 포팅 하려할 때, 많은 확장성을 제공해 주기 위함입니다. FD_SET 구조체를 처리하는 매크로는 다음과 같습니다.

FD_CLR(s, *set)
지정된 소켓 기술자(descriptor)를 세트에서 제거 합니다.

FD_ISSET(s, *set)
지정된 소켓 기술자가 세트에 있을 경우 0이 아닌값을 반환하고, 없을 경우 0을 반환합니다.

FD_SET(s, *set)
지정된 소켓 기술자를 세트에 추가 합니다.

FD_ZERO(*set)
모든 소켓 기술자를 세크에서 제거합니다.


FD_SET

typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;

Element Usage
fd_count 설정하는 소켓의 번호
fd_array 설정된 소켓의 배열


FD_Zero

Clear all file descriptors in set

Declaration

Source position: oldlinux.pp line 1594

procedure FD_Zero(

var fds: fdSet

);

Description

FD_ZERO clears all the filedescriptors in the file descriptor set fds.

For an example, see Select.

Errors

None.


FD_Clr

Clears a filedescriptor in a set

Declaration

Source position: oldlinux.pp line 1595

procedure FD_Clr(

fd: LongInt;

var fds: fdSet

);

Description

FD_Clr clears file descriptor fd in filedescriptor set fds.

For an example, see Select.

Errors

None.




FD_IsSet

Check whether a filedescriptor is set

Declaration

Source position: oldlinux.pp line 1597

function FD_IsSet(

fd: LongInt;

var fds: fdSet

):Boolean;

Description

FD_Set Checks whether file descriptor fd in filedescriptor set fds is set.

For an example, see Select.

Errors

None.

Posted by cyj4369
,
 
2003-01-09 오후 8:18:50   /  번호: 270644   category: VC++ 일반  /  조회: 167
 [급질문]_beginthreadex 에서 BOOL 함수 호출..그리고 파라메터  
리턴 값이 BOOL 인 함수를 쓰레드로 쓸려면 3번째 파라미터에 어떻게 선언해줘야되죠??
그리고 구조체를 파라미터로 넘길려고 그러는데..자꾸 이런에러가 뜨네요.
error C2664: '_beginthreadex' : cannot convert parameter 3 from 'unsigned int (struct st_ComPort *)' to 'unsigned int (__stdcall *)(void *)'
        None of the functions with this name in scope match the target type

어떻게 해야 되죠?? 파라미터를 넘겨야 되죠??
 
  2004-10-15 오전 1:15:26   /  번호: 474101  /  
 Re: _beginthreadex 형변환문제 답변.   
  

 c++ 은 자료형을 엄격히 구분해서 발생하는 문제입니다.


(HANDLE)_beginthreadex(NULL, 0, ClientConn, (void*)clntSock, 0, (unsigned *)&dwThreadID);


요렇게 사용하면 당근 님이 묻는 Error가 발생합니다.


이것땜시 저도 아주 두시간을 헤맸어용...ㅜㅜ;


문제는 세번째 인자에 있습니다. 요걸 이렇게 바꾸면 형변환 문제 해결... 아래 에러 왕짜증..

error C2664: '_beginthreadex' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned int (__stdcall *)(void *)'

        None of the functions with this name in scope match the target type


음 그니까 (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall*)(void*))ClientConn, (void*)clntSock, 0, (unsigned *)&dwThreadID);


위에걸 이렇게 바꿔주시면 해결 될거에요....^^


즐공하세용!!


출처 : 데브피아(http://www.devpia.com)

Posted by cyj4369
,

DWORD = unsigned  long

LPVOID = 헝가리안 표기법에 의해 LP라는 것은 long pointer임 LPVOID는 void*를 의미

 

/*
 http://sosal.tistory.com/
 * made by so_Sal
 */



스레드 (혹은 쓰레드, Thread) 에 대해서 잘 모르신다면
링크로~! ^-^ :: LINK_

/*
 * CreateThread()
 * ExitThread()
 * GetExitCodeThread()

 * _beginthreadex()
 *  ResumeThread();
 * _endthreadex()
 *  -------------
 */
Windows에서 쓰레드를 생성하는 가장 기본적인 함수는
CreateThread 입니다.

HANDLE CreateThread(
1.        LPSECURITY_ATTRIBUTES lpThreadAttributes,
2.        SIZE_T dwStackSize,
3.        LPTHREAD_START_ROUTINE lpStartAddress,
4.        LPVOID lpParameter,
5.        DWORD dwCreationFlags,
6.        LPDWORD lpThreadId        );

1. LPSECURITY_ATTRIBUTES lpThreadAttributes,
SECURITY_ATTRIBUTES 구조체는,
생성하는 핸들에 대해 보안속성을 

2. SIZE_T dwStackSize //dw는 DWORD겠죠 ㅎㅎ
쓰래드는 고유의 스택을 가지고 있습니다. 스택 크기를 지정합니다.
0 (또는 NULL) :: Default 값으로 1mb가 적용됩니다.

3. LPTHREAD_START_ROUTINE lpStartAddress

쓰레드가 작동할 함수의 이름을 넣으시면 됩니다.
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)
                  (LPVOID lpThreadParameter);
typedef PTHREAD_START_ROUTINE    LPTHREAD_START_ROUTINE;

함수 예)
DWORD WINAPI ThreadEx(LPVOID lpParameter){
        return 0;
}

4. LPVOID lpParameter
함수의 인자로 넘어가는것과 같습니다.
더블 포인터도 가능합니다.

5. DWORD dwCreationFlags, //Flag 입니다.
CREATE_SUSPEND
    
:: suspend count 1로 설정 ( 스레드 priority control 관련글 참고 링크 :: LINK_ )
     :: suspend count가 0이 되기 전까지는, 스레드는 동작하지 않습니다.
        이 인자를 넣을 시에, 원하는 시기에 스레드를 시작할 수 있습니다.
        DWORD ResumeThread(HANDLE hThread)   ::  Suspend Count 1 감소
        DWORD SuspendThread(HANDLE hThread)   ::  Suspend Count 1 증가

STACK_SIZE_PARAM_IS_A_RESERVATION 


     :: Reserve stack size를 변경하려면 위 플레그를 추가 한 후 
        스레드 생성 함수들의 매개변수 dwStackSize파라미터를 사용한다.

아래는 CreationFlag이지만, 프로세스에서만 쓰인다. 
CREATE_NEW_CONSOLE
DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS 

6. LPDWORD lpThreadId
생성시에 이 변수로 쓰레드ID가 전달됩니다.
필요 없다면 NULL.

return :: HANDLE.
CreateThread 함수의 리턴값은, 스레드를 가리키는 핸들

스레드는 독립된 스택을 할당받기 때문에 메모리를 차지하게 됩니다.
메모리가 허용하는 만큼 스레드 생성이 가능합니다.







void
 ExitThread(DWORD dwExitCode)
이 함수는 실행중인 스레드를 종료하고자 할 때 호출하는 함수입니다.
(사실 return과 다를 바 없다.)
return으로 종료되는 스레드나, 이 함수로 종료되는 스레드나
모두 아래에 설명할 GetExitCodeThread 함수로 리턴값 (혹은 ExitCode값)을
반환받을 수 있다.







스레드의 리턴값을 가져오는 함수입니다.
BOOL GetExitCodeThread(
1        HANDLE hThread,
2        LPDWORD lpExitCode );

1. HANDLE :: 정상적인 리턴으로 종료된 스레드를 가리키는 핸들값
2. lpExitCode :: DWORD 자료형 변수의 주소값을 넣어주면
                       스레드의 리턴값 DWORD값을 반환

다중 프로세스의 경우에, GetExitCodeProcess() 함수 또한,
위와 같이 사용할 수 있습니다. (자료형, 매개변수가 같습니다.)





#include<process.h> 헤더파일이 필요합니다.
uintptr_t _beginthreadex(
          void *_Security,
          unsigned int _StackSize,
          unsigned int(*_StartAdrdress)(void *),
          void *_ArgList,
          unsigned int _InitFlag,
          unsigned int *_ThrdAddr    );

매개변수는 CreateThread와 일치합니다.
매개변수들의 자료형을 더욱 범용적으로 쓰기 위해서
자료형의 형태가 수정되었습니다.

CreateThread() 와 위 함수의 가장 큰 차이점은,
독립적인 메모리 블록 할당에 있습니다.
_beginthreadex() 함수 역시 내부적으로 CreateThread()를 호출합니다. 
종료호출로 ExitThread() 대신, 아래 함수로 대신합니다.
(ExitThread() 함수를 쓰는 이유는 독립적인 "메모리 블록 할당" 에 있습니다.)



void _endthreadex(unsigned retval);
ExitThread() 함수와 역시 동일합니다. 하지만,
_endthreadex() 함수를 쓰는 이유는, 
CreateThread()와 _beginthreadex() 함수간의 차이에 있습니다.
_beginthread() 함수에서는 독립적인 메모리 블록 할당을 한다고 하였습니다.
따라서 스레드 종료시에, 할당한 메모리를 반환해야만 합니다.
이 역할을 하는 함수가 _endthreadex() 입니다.
















======================== CreateThread() 사용 함수 예제 ========================


/*
 * CraeteThread()함수를 이용하여 스레드를 생성한 후
 * 각각의 스레드에 매개변수로 1~10을 넘깁니다.
 * 스레드는 매개변수로 받은 숫자 1~10을 전역변수 STotal 변수에 +=으로 더하고,
 * 매개변수값을 리턴합니다.
 * 메인루틴에서는 스레드가 리턴한값을 차례대로 GetExitCodeThread() 함수를 통해
 * 반환하여 모두 더하고, 전역변수와 리턴값의 합을 출력합니다.
 * ExitThread() 함수는 사용하지 않고, return을 이용했습니다. 
 * ExitThread() 함수를 이용해 직접 짜보시면 이해에 더욱 도움이 될 것 같습니다.
 */


#include<stdio.h>
#include<windows.h>
#include<tchar.h>

#define MAX_THREADS (10)

DWORD STotal = 0;
DWORD WINAPI ThreadProc(LPVOID lpParam);
        // 생성될 Thread가 수행할 내용이 담긴 함수

int _tmain(int argc,TCHAR *argv[]){

 DWORD cntOfThread=0;
 DWORD dwThreadID[MAX_THREADS];
 HANDLE hThread[MAX_THREADS];

 DWORD Total =0;
 DWORD Result=0;
 

while(1){
    if(cntOfThread == MAX_THREADS){
      _tprintf( _T("MAXIMUM THREAD NUMBER : %d\n") ,cntOfThread);
       break;
    }
    hThread[cntOfThread] =
     CreateThread(
         NULL,0,ThreadProc,
         (LPVOID)cntOfThread,
         0,
         &dwThreadID[cntOfThread]);
         cntOfThread++;
}  //while문을 이용하여 10개의 스레드 생성

 Sleep(1000);
 // 스레드가 자신의 할일을 모두 수행하고, 리턴값을 남기고 사라짐
 // 리턴값을 이용하여 Total 계산

 for(DWORD i=0; i<cntOfThread; i++){
  GetExitCodeThread(hThread[i],&Result);
  Total += Result;
  CloseHandle(hThread[i]);
 }
 
 _tprintf( _T(" Total :: %d \n"), Total);      //스레드의 리턴값으로 얻은 Total
 _tprintf( _T("STotal :: %d \n"), STotal);   //스레드가 전역변수에 접근하여 계산된 값
 return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParam){
   STotal += (DWORD)lpParam; // 전역변수도 접근 가능
   return (DWORD)lpParam;      // 리턴값       전달 가능
}





======================== _beginthreadex() 사용 함수 예제 ========================
/*
 * 위 CreateThread() 예제와
 * 같은 일을 수행합니다.
 */



#include<stdio.h>
#include<windows.h>
#include<tchar.h>
#include<process.h> //beginthreadex() 함수 사용시 필요 헤더파일

#define
 MAX_THREADS (10)

DWORD STotal = 0;
unsigned int WINAPI ThreadProc(LPVOID lpParam);
        // 생성될 Thread가 수행할 내용이 담긴 함수.
        // CreateThread와는 다르게 unsigned int 자료형을 사용합니다.

int _tmain(int argc,TCHAR *argv[]){

 DWORD cntOfThread=0;
 DWORD dwThreadID[MAX_THREADS];
 HANDLE hThread[MAX_THREADS];

 DWORD Total =0;
 DWORD Result=0;
 

while(1){
    if(cntOfThread == MAX_THREADS){
      _tprintf( _T("MAXIMUM THREAD NUMBER : %d\n") ,cntOfThread);
       break;
    }
    hThread[cntOfThread] =
     (HANDLE) _beginthreadex(       //HANDLE로의 형변환이 필요합니다.
         NULL,0,ThreadProc,
         (LPVOID)cntOfThread,
         0,
         (unsigned *)&dwThreadID[cntOfThread]); 
         cntOfThread++;
}  //while문을 이용하여 10개의 스레드 생성

 Sleep(1000);
 // 스레드가 자신의 할일을 모두 수행하고, 리턴값을 남기고 사라짐
 // 리턴값을 이용하여 Total 계산

 for(DWORD i=0; i<cntOfThread; i++){
  GetExitCodeThread(hThread[i],&Result);
  Total += Result;
  CloseHandle(hThread[i]);
 }
 
 _tprintf( _T(" Total :: %d \n"), Total);      //스레드의 리턴값으로 얻은 Total
 _tprintf( _T("STotal :: %d \n"), STotal);   //스레드가 전역변수에 접근하여 계산된 값
 return 0;
}

unsigned int WINAPI ThreadProc(LPVOID lpParam){ //unsigned int 자료형
   STotal += (DWORD)lpParam; // 전역변수도 접근 가능
   return (DWORD)lpParam;      // 리턴값       전달 가능
}

Posted by cyj4369
,
이클립스 설치

http://www.eclipse.org/downloads/ 


 

 

원활한 웹 개발을 위해서 반드시 형광색이 표시된 Eclipse IDE for JAVA EE 버전을 받으시는 것이 좋다. 우측에 32비트와 64비트 두가지 중 하나로 선택하여 다운로드 할 수 있으니 자신의 운영체제에 맞는 부분을 클릭하시면 된다.

 

 

이후 상기 이미지와 같은 부분의 링크를 클릭하시면 다운로드가 진행된다. 이클립스는 특별히 어디다 설치해도 지장이 없으니 자신이 가장 편하다고 생각되는 폴더/작업 환경에 다운로드 받는다.

 

이후 다운로드 받은 압축파일을 알집이나 winrar등을 이용하여 풀어주도록 한다.

 

 

압축을 풀면 eclipse 폴더 안에 다음과 같은 파일과 폴더들이 있는데

eclipse.exe 가 실행파일이다. eclipse.exe 를 실행한다.

 

 

이클립스 로고와 함께 워크스페이스를 어디로 설정할지를 묻는 창이 뜬다.

이곳에서 지정하는 폴더에 여러분께서 작업하시는 결과물과 이클립스 설정 정보가 모두 저장되니 적당한 폴더명을 지정해주시면 된다.

 

나중에 워크스페이스를 따로 바꿀수도 있지만 이의 경우 설정파일과 소스파일들을 다시 옴겨주어야 하는 번거로움이 있으니 자주 사용할 임의 폴더로 설정한다. 설정 후  OK버튼 클릭

 






톰캣 설치

 

첨부된 파일을 설치한다.
설치할 위치를 잘 기억해 둬야 한다.

<tomcat서버 만들기>
1. 서버 탭을 보이게 한다.
 이클립스 윈도우 탭 -> Show View -> Servers선택
2. 서버 생성
서버탭에서 오른쪽 클릭 -> Apache -> tomcat선택 -> next -> finish



오라클 설치



 이 경로에서 버전에 맞는 오라클 설치
설치하면 아이디는 SYSTEM이고, 비밀번호는 본인이 설정해 기억해야 한다.
 설치하고 나면 디폴트값으로 포트넘버 8080을 사용한다. 그러나 이 번호는 톰캣과 충돌하기 때문에 바꿔줘야 한다. 
1. cmd창을 연다.
2. SQL PLUS 실행 : sqlplus /nolog
3. 데이터베이스 접속 : CONNECT SYSTEM/설치할 때 입력한 패스워드
4. 포트 변경 명령 수행 : EXEC DBMS_XDB/SETHTTTPPORT(8087)
5. SQL PLUS 종료 : exit


<이클립스 오라클 연동>
1. Data Source Explore 탭을 보이게 한다.
이클립스 윈도우 탭 -> Show View -> Data Source Explore 선택
 
2. 새로운 데이터베이스 연결 생성
Database Connection에서 오른쪽 클릭 -> new... -> Oracle선택 하고 next -> 맨 위에 Drivers에서 오른쪽에 동그란 버튼 선택 -> 설치한 버전에 맞는 드라이버 선택 -> 오른쪽 JAR List탭으로 이동 ->원래 있던 JAR파일 지우고 Add JAR/Zip... 버튼 클릭 -> oracle설치한 폴더에 들어가서 \app\oracle\product\10.2.0\server\jdbc\lib경로로 이동 해 ojdbc14.JAR파일 추가 -> OK버튼 클릭 -> General 탭에서 SID를 db에서 xe로 바꾸고 Host를 server에서 localhost로 바꾼다. -> 비밀번호를 입력 하고 Finish 클릭

 



<프로젝트 생성>
1. 프로젝트 생성
새 프로젝트 생성 -> Web에 Dynamic Web Project 선택하고 next -> 프로젝트 이름 지정 -> Target Runtime에서 톰캣 확인 -> Dynamic Web version과 Configuration 확인 후 finish



2. ojdbc14.jar파일 추가
oracle설치한 폴더에 들어가서 \app\oracle\product\10.2.0\server\jdbc\lib경로로 이동 해 ojdbc14.JAR파일을 찾아  다음 경로에 넣어준다



3. sql명령 입력할 파일 생성
원하는 폴더에서(위에서는 ch08) 오른쪽 클릭 -> new.. -> SQL File을 찾아 이름 정하고 생성 -> 다음과 같이 설정
 


-> 필요한 SQL문을 입력하여 사용하면 된다. 만들어진 테이블은 아래 Data Source Explore에서 확인하거나 인터넷 창을 실행시켜 127.0.0.1:8087/apex를 입력해 로그인하여 객체 브라우저에서 확인해 볼 수도 있다.

Posted by cyj4369
,
1. CAPTURE FILTERS

capture 필터의 구문은 TCPdump처럼 Lipcap(Linux)이나 Winpcap(Windows) 라이브러리를 사용하는 프로그램에서 쓰는 것과 같습니다. Capture 필터는 캡쳐 도중 아무 때나 수정이 가능한 display 필터와는 다르게, 반드시 캡쳐를 시작하기 전에 설정을 해주어야 합니다.

capture 필터를 설정하는 방법은 다음과 같습니다:
- capture -> options 을 선택합니다.
- "capture filter" 칸에 직접 작성하거나, 다음 번 캡쳐에 다시 사용할 수 있는 필터 이름을 부여하기 위해 "capture filter" 버튼을 클릭합니다.
- 데이터를 캡쳐하기 위해 Start버튼을 클릭합니다.





Syntax:
Protocol
Direction
Host(s)
Value
Logical Operations
Other expression
Example:
tcp
dst
10.1.1.1
80
and
tcp dst 10.2.2.2 3128
Protocol:
사용 가능한 값: ether, fddi, ip, arp, rarp, decnet, lat, sca, moprc, mopdl, tcp and udp.
프로토콜을 지정하지 않으면 모든 프로토콜을 사용합니다.

Direction:
사용 가능한 값: src, dst, src and dst, src or dst
출발지나 목적지를 지정하지 않으면 "src or dst" 키워드가 사용됩니다.
예를 들어, "host 10.2.2.2"은 "src or dst host 10.2.2.2"과 동일합니다.

Host(s):
사용 가능한 값: net, port, host, portrange.
호스트를 지정하지 않으면 "host" 키워드가 사용됩니다.
예를 들어, "src 10.1.1.1"은 "src host 10.1.1.1"과 같은 의미입니다.

Logical Operations:
사용 가능한 값: not, and, or.
부정 연산("not")이 가장 높은 우선순위를 갖습니다. 논리합("or")과 논리곱("and")는 같은 우선순위를 가지며 왼쪽에서 오른쪽으로 처리됩니다.
예를 들어,
"not tcp port 3128 and tcp port 23"은 "(not tcp port 3128) and tcp port 23"과 동일하게 작용합니다.
"not tcp port 3128 and tcp port 23" 은 "not (tcp port 3128 and tcp port 23)"과는 동일하지 않습니다.



사용 예:

tcp dst port 3128
목적지가 TCP 포트 3128인 패킷을 보여줍니다.

ip src host 10.1.1.1
출발지 IP 주소가 10.1.1.1인 패킷을 보여줍니다.

host 10.1.2.3
출발지와 목적지 IP 주소가 10.1.1.1인 패킷을 보여줍니다.

src portrange 2000-2500
출발지의 UDP, TCP 포트가 2000-2500 사이인 패킷을 보여줍니다.

not imcp
icmp 패킷을 제외한 모든 패킷을 보여줍니다. (icmp는 보통 ping 프로그램에서 사용합니다.)

src host 10.7.2.12 and not dst net 10.200.0.0/16
출발지 IP 주소가 10.7.2.12이면서, 목적지 IP 네트워크가 10.200.0.0/16이 아닌 패킷을 보여줍니다.

(src host 10.4.1.12 or src net 10.6.0.0/16) and tcp dst portrange 200-10000 and dst net 10.0.0.0/8
출발지 IP 주소가 10.4.1.12이거나, 출발지 네트워크가 10.6.0.0/16인 패킷중에서 목적지 TCP 포트 범위가 200-10000이면서, 목적지 IP 네트워크가 10.0.0.0/8인 패킷을 보여줍니다.


참고:

"\" 기호는 키워드 자체가 값을 나타낼 때 사용합니다.
"ether proto \ip"( \ip는 "ip"과 동일합니다.)
이것은 IP 프로토콜을 타켓으로 하게 됩니다.

"ip proto \icmp"(\icmp는 "icmp"과 동일합니다.)
이것은 일반적으로 ping 유틸리티에서 사용되는 icmp 패킷을 타켓으로 하게 됩니다.

"multicast"와 "broadcast" 키워드는 "ip" 나 "ether" 다음에 사용할 수 있습니다.
"no broadcast"는 broadcast 요청을 제외하고 싶을 때 유용하게 사용할 수 있습니다.



capture 필터의 구문에 대한 정보가 필요하시면 TCPdump man page을 참고하세요.
Other capture filters examples can be found in the Wiki Wireshark website.

페이지 처음으로



2. DISPLAY FILTERS:

display 필터는 캡쳐된 데이터에서 원하는 정보를 찾을 때 사용합니다.
display 필터의 검색 능력은 capture 필터 보다 더 뛰어납니다. 그리고 필터의 내용을 바꾸고 싶을 때 캡쳐 작업을 다시 시작하지 않아도 됩니다.

Syntax: Protocol .
String 1
.
String 2
Comparison operator
Value
Logical Operations
Other expression
Example:
ftp
passive
ip
==
10.2.3.4
xor
icmp.type
Protocol:

OSI layer 2에서 layer 7 사이에 있는 매우 다양한 프로토콜을 사용 할 수 있습니다. 그것들은 메인 화면에 보이는 "Expression..." 버튼을 클릭하면 볼 수 있습니다.





아래에 보이는 그림에서 간단한 설명과 함께 지원 가능한 프로토콜들을 확인 할 수 있습니다:





Wireshark 웹사이트에서 프로토콜과 그것의 하위 카테고리에 대한 설명을 제공하고 있습니다.]

String1, String2 (선택 사항)

각 프로토콜의 하위 프로토콜 카테고리.
그것을 보기 위해서, 프로토콜을 선택한 뒤 "+" 표시를 클릭하세요.



비교 연산자:

6개의 비교 연산자를 사용 할 수 있습니다:

영문 표기: C언어 표기: 의미:
eq
==
같다
ne
!=
틀리다
gt
>
크다
lt
<
작다
ge
>=
크거나 같다
le
<=
작거나 같다
논리 표현 식:

영문 표기: C언어 표기: 의미:
and
&&
논리곱
or
||
논리합
xor
^^
배타적 논리합
not
!
부정
프로그래머들이 잘 아는 "XOR"은 배타적 논리합 연산으로 사용됩니다. 두 가지 조건 사이에서 사용되었을 때, 두 가지 조건 중 오직 한가지만 만족했을 때 결과 화면에 보여집니다.
다음의 display 필터를 이용하여 예시를 보여드리겠습니다:
"tcp.dstport 80 xor tcp.dstport 1025"
목적지가 TCP 포트 80이거나 출발지가 TCP 포트 1025인 (두 가지 모두인 경우는 제외하고) 패킷이 결과로 화면에 나타납니다.



사용 예:

snmp || dns || icmp SNMP 혹은 DNS 혹은 ICMP 트래픽을 보여줍니다.
ip.addr == 10.1.1.1
출발지나 목적지의 IP 주소가 10.1.1.1인 패킷을 보여줍니다.

ip.src != 10.1.2.3 or ip.dst != 10.4.5.6
출발지의 IP 주소가 10.1.2.3이 아니거나 목적지의 IP 주소가 10.4.5.6이 아닌 패킷을 보여줍니다.
다른 말로 하자면, 화면에 보여지는 패킷은 다음과 같을 것입니다:
출발지 IP 주소 : 10.1.2.3이 아닌 모든 주소, 목적지 IP 주소 : 10.1.2.3이 아닌 모든 주소
그리고
출발지 IP 주소 : 모든 주소, 목적지 IP 주소 : 10.4.5.6이 아닌 모든 주소

ip.src != 10.1.2.3 and ip.dst != 10.4.5.6
출발지 IP 주소가 10.1.2.3이 아니면서, 동시에 목적지 IP 주소가 10.4.5.6이 아닌 패킷을 화면에 보여줍니다.
다른 말로 하자면, 화면에 보여지는 패킷은 다음과 같을 것입니다:
출발지 IP 주소 : 10.1.2.3이 아닌 모든 주소, 그리고 목적지 IP 주소 : 10.4.5.6이 아닌 모든 주소

tcp.port == 25 출발지와 목적지의 TCP 포트가 25인 패킷을 보여줍니다.
tcp.dstport == 25 목적지의 TCP 포트가 25인 패킷을 보여줍니다.
tcp.flags TCP 플래그를 가지고 있는 패킷을 보여줍니다.
tcp.flags.syn == 0x02 TCP SYN 플래그를 가지고 있는 패킷을 보여줍니다.
필터 구문에 문제가 없다면, 녹색으로 하이라이트 될 것이며, 잘못됐다면 붉은색으로 하이라이트 될 것입니다.

올바른 구문
잘못된 구문
display 필터에 대한 추가 정보는 Wireshark official websiteWiki Wireshark website에서 찾을 수 있습니다.
Posted by cyj4369
,