^(코딩캣)^ = @"코딩"하는 고양이;
썸네일 이미지
[단편 FreeBSD 사용법] FTP 서버 설정하기
단편 FreeBSD 사용법 FTP 서버 설정하기 이번 포스팅에서는 FreeBSD에서 FTP 서버를 구축하고 외부에서 접속을 테스트해보겠다. inetd 활성화하기 FreeBSD에는 FTP, HTTP, SSH, Telnet 등의 기본적인 서버가 내장되어 있으므로 설정을 통해 이를 활성화하기만 하면 된다. # vi /etc/inetd.conf 위 명령을 실행하여 미리 구성된 설정 파일에서 FTP 설정에 붙은 주석을 제거한다. 3번째 열에 tcp로 적힌 행은 IPv4로 접속 가능한 FTP 서버를 의미하고, tcp6으로 적힌 행은 IPv6로 접속 가능한 FTP 서버를 의미한다. 둘 중 하나, 또는 둘 다 주석을 제거하면 해당 프로토콜로 FTP 서버가 구축된다. 그 다음 rc.conf를 열어 inetd를 사용 가능..
Operating System/Unix × FreeBSD
2019. 12. 27. 11:14

[단편 FreeBSD 사용법] FTP 서버 설정하기

Operating System/Unix × FreeBSD
2019. 12. 27. 11:14

단편 FreeBSD 사용법


 

FTP 서버 설정하기


이번 포스팅에서는 FreeBSD에서 FTP 서버를 구축하고 외부에서 접속을 테스트해보겠다.

 

inetd 활성화하기


FreeBSD에는 FTP, HTTP, SSH, Telnet 등의 기본적인 서버가 내장되어 있으므로 설정을 통해 이를 활성화하기만 하면 된다.

# vi /etc/inetd.conf

 

위 명령을 실행하여 미리 구성된 설정 파일에서 FTP 설정에 붙은 주석을 제거한다. 3번째 열에 tcp로 적힌 행은 IPv4로 접속 가능한 FTP 서버를 의미하고, tcp6으로 적힌 행은 IPv6로 접속 가능한 FTP 서버를 의미한다. 둘 중 하나, 또는 둘 다 주석을 제거하면 해당 프로토콜로 FTP 서버가 구축된다.

 

그 다음 rc.conf를 열어 inetd를 사용 가능하게 수정 후 이를 실행한다.

# vi /etc/rc.conf

 

 

# /etc/rc.d/inetd start

 

 

로컬에서 테스트하기


다음과 같이 ftplocalhost에 접속해본다.

$ ftp localhost

 

 

방화벽 FTP 포트 개방하기


외부에서 접속할 수 있도록 방화벽의 FTP 포트를 개방한다. FTP 포트 번호는 TCP 21번이다.

다음은 임의의 IP를 가진 외부에서 서버의 21번 포트로 들어오는 패킷을 허용하는 명령이다. NIC는 네트워크 카드이며 ifconfig으로 인터넷에 접속된 네트워크 카드의 이름을 확인할 수 있다.

# ipfw -add allow tcp from any to any 21 in via /* NIC */ setup keep-state

 

예를 들어,

# ipfw -add allow tcp from any to any 21 in via em0 setup keep-state

 

다음은 서버의 21번 포트에서 접속자로 나가는 패킷을 허용하는 명령이다.

# ipfw -add allow tcp from any to any 21 out via /* NIC */ setup keep-state

 

예를 들어,

# ipfw -add allow tcp from any to any 21 out via em0 setup keep-state

 

위 명령은 ipfw의 rules 파일에 적어 놓으면 재부팅할 때에 편리하다.

 

외부에서 테스트하기


외부에서 테스트하여 로컬에서 테스트한 것과 같은지 확인한다.

 

카테고리 “Operating System/Unix × FreeBSD”
more...
썸네일 이미지
[단편 FreeBSD 사용법] bash 설치 및 사용하기
단편 FreeBSD 사용법 bash 설치 및 사용하기 FreeBSD는 기본적으로 csh를 기본 shell로 사용한다. 루트와 일반 사용자의 shell을 bash로 바꾸어보겠다. bash 설치 sudo 또는 루트 계정에서 bash 패키지를 설치한다. # pkg install bash 각 사용자에서 bash 적용 먼저 which 명령을 실행하여 bash가 어디에 설치되어 있는지 확인한다. 본 포스팅의 경우 /usr/local/bin/bash가 검색된다. # which bash 루트 사용자에게 bash를 적용하려면 아래와 같이 실행한다. chsh는 Change Shell의 약어이다. -s는 지정된 경로에 있는 shell로 바꾸라는 옵션이다. 앞서 확인한 /usr/local/bin/bash를 입력하면 된다. #..
Operating System/Unix × FreeBSD
2019. 12. 24. 19:13

[단편 FreeBSD 사용법] bash 설치 및 사용하기

Operating System/Unix × FreeBSD
2019. 12. 24. 19:13

단편 FreeBSD 사용법


bash 설치 및 사용하기


FreeBSD는 기본적으로 csh를 기본 shell로 사용한다. 루트와 일반 사용자의 shell을 bash로 바꾸어보겠다.

 

bash 설치


sudo 또는 루트 계정에서 bash 패키지를 설치한다.

# pkg install bash

 

 

각 사용자에서 bash 적용


먼저 which 명령을 실행하여 bash가 어디에 설치되어 있는지 확인한다. 본 포스팅의 경우 /usr/local/bin/bash가 검색된다.

# which bash

 

루트 사용자에게 bash를 적용하려면 아래와 같이 실행한다. chsh는 Change Shell의 약어이다. -s는 지정된 경로에 있는 shell로 바꾸라는 옵션이다. 앞서 확인한 /usr/local/bin/bash를 입력하면 된다.

# chsh -s /usr/local/bin/bash

 

루트가 아닌 특정 사용자에게 bash를 적용하려면 위 명령 끝에 사용자명을 적어주면 된다.

# chsh -s /usr/local/bin/bash <사용자>

 

 

로그아웃 후 다시 로그인하면 다음과 같이 shell이 리눅스의 것과 같은 bash로 적용되었음을 확인할 수 있다.

 

카테고리 “Operating System/Unix × FreeBSD”
more...
썸네일 이미지
[단막 FreeBSD 오류해결] FreeBSD 인터넷 연결
단막 FreeBSD 오류해결 FreeBSD 인터넷 연결 이 포스트는 FreeBSD의 인터넷 연결 오류를 해결한 개인의 경험을 정리한 것이다. 본 해법은 절대적인 해법이 아니기 때문에, 하드웨어 설정 상태에 따라 다양한 방법을 시도해 보아야 할 것이다. 문제 상황: 인터넷이 연결되지 않는다. ping, traceroute 모두 먹히지 않는다. 즉 인터넷 접속이 안 된다. FreeBSD에 NIC가 잡혀있는가 다음의 명령을 실행해 보았다. NIC가 제대로 잡혀있을뿐만 아니라 DHCP에 따라 공유기로부터 IP 주소(IPv4, IPv6 모두)까지 제대로 할당받았음을 확인 가능하다. # ifconfig DNS 설정이 양호한가 수 차례의 삽질 끝에 찾아낸 방법으로는, 무슨 이유에서인지는 알 수 없으나 FreeBSD에..
Operating System/Unix × FreeBSD
2019. 12. 24. 18:40

[단막 FreeBSD 오류해결] FreeBSD 인터넷 연결

Operating System/Unix × FreeBSD
2019. 12. 24. 18:40

단막 FreeBSD 오류해결


FreeBSD 인터넷 연결


이 포스트는 FreeBSD의 인터넷 연결 오류를 해결한 개인의 경험을 정리한 것이다. 본 해법은 절대적인 해법이 아니기 때문에, 하드웨어 설정 상태에 따라 다양한 방법을 시도해 보아야 할 것이다.

 

문제 상황: 인터넷이 연결되지 않는다.


ping, traceroute 모두 먹히지 않는다. 즉 인터넷 접속이 안 된다.

 

FreeBSD에 NIC가 잡혀있는가


다음의 명령을 실행해 보았다. NIC가 제대로 잡혀있을뿐만 아니라 DHCP에 따라 공유기로부터 IP 주소(IPv4, IPv6 모두)까지 제대로 할당받았음을 확인 가능하다.

# ifconfig

 

 

DNS 설정이 양호한가

수 차례의 삽질 끝에 찾아낸 방법으로는, 무슨 이유에서인지는 알 수 없으나 FreeBSD에 DNS 로컬 캐싱 기능(다시 말해서 FreeBSD가 DNS 서버로 작동하면서 DB를 자체 운영하고 FreeBSD가 외부 인터넷으로 접속할 때 도메인을 자기 자신으로부터 참조하는 것)이 켜져 있으면 도메인을 통한 인터넷 접속이 불가할 수 있다. 이와 관계된 설정 파일이 /etc/resolv.conf를 열어보면 DNS 주소가 루프백(127.0.0.1)으로 되어 있고, 공유기의 아이피 주소가 주석처리 되어 있음을 확인할 수 있다.

 

원인을 찾았으니 이를 해결해보도록 한다. 아래 명령을 사용하여 DNS 로컬 캐싱을 끈다.

# sysrc local_unbound_enable="NO"
# service local_unbound stop

 

그리고나서 vi/etc/resolv.conf를 수정한다. 127.0.0.1를 참조하는 라인을 삭제하고, 공유기 아이피 주소에 붙은 주석을 해제한다.

이후 도메인을 통한 ping, traceroutehost 명령까지 잘 작동됨을 확인할 수 있다.

 

카테고리 “Operating System/Unix × FreeBSD”
more...
썸네일 이미지
[단막 FreeBSD 사용법] syslogd 콘솔 출력 끄기
단막 FreeBSD 사용법 syslogd 콘솔 출력 끄기 FreeBSD를 사용 중 콘솔에 갑작스럽게 syslogd 메시지가 뜬다면 사용이 불편할 수 있다. 이럴 때는 다음과 같이 syslogd의 콘솔 출력을 끌 수 있다. syslogd daemon 종료 및 부팅 시 자동 시작 방지 우선 syslogd daemon을 종료한다. $ su # /etc/rc.d/syslogd stop vi로 /etc/rc.conf를 연 다음 syslogd_enable="YES"라고 적힌 항목을 찾아 다음과 같이 수정한다. 해당 내용이 없을 경우 아래의 내용을 직접 적는다. syslogd_enable="NO" syslogd의 출력을 파일로 돌리기 앞서 설명한 방법은 syslogd를 완전히 종료하고 부팅 시 자동으로 실행되는 것까..
Operating System/Unix × FreeBSD
2019. 12. 22. 10:53

[단막 FreeBSD 사용법] syslogd 콘솔 출력 끄기

Operating System/Unix × FreeBSD
2019. 12. 22. 10:53

단막 FreeBSD 사용법


syslogd 콘솔 출력 끄기


FreeBSD를 사용 중 콘솔에 갑작스럽게 syslogd 메시지가 뜬다면 사용이 불편할 수 있다.

이럴 때는 다음과 같이 syslogd의 콘솔 출력을 끌 수 있다.

 

syslogd daemon 종료 및 부팅 시 자동 시작 방지


우선 syslogd daemon을 종료한다.

$ su
# /etc/rc.d/syslogd stop

 

 

vi/etc/rc.conf를 연 다음 syslogd_enable="YES"라고 적힌 항목을 찾아 다음과 같이 수정한다. 해당 내용이 없을 경우 아래의 내용을 직접 적는다.

syslogd_enable="NO"

 

 

syslogd의 출력을 파일로 돌리기


앞서 설명한 방법은 syslogd를 완전히 종료하고 부팅 시 자동으로 실행되는 것까지 막는 방법이다. 그러나 서버를 운영하고자 할 때 로그는 필요하기도 하므로, 콘솔 대신 파일로 출력하고자 할 때는 다음과 같이 수행한다.

우선 syslogd daemon을 종료한다.

$ su
# /etc/rc.d/syslogd stop

 

그 다음 vi/etc/syslog.conf 파일의 내용을 수정한다. 이미 syslogd의 출력을 파일로 출력할 수 있도록 내용이 적혀져 있으므로 이 라인에 붙은 주석 기호 #을 제거한다. 없을 경우 아래와 같이 입력한다.

console.info /var/log/console.log

 

그리고나서 해당 경로에 빈 텍스트 파일을 하나 만들고 퍼미션을 600이상 부여한다. 이는 /etc/syslog.conf의 주석에 지시사항으로 나와있다. 이후 중지했던 syslogd daemon을 시작하면 작업 완료다.

# touch /var/log/console.log
# chmod 600 /var/log/console.log
# /etc/rc.d/syslogd restart

 

 

카테고리 “Operating System/Unix × FreeBSD”
more...
썸네일 이미지
[단편 FreeBSD 사용법] 일반 계정에서 su, sudo 명령 사용하기
단편 FreeBSD 사용법 일반 계정에서 su, sudo 명령 사용하기 su명령은 일반 계정에서 루트 계정의 Shell을 띄울 때 사용하는 명령이다. FreeBSD에서는 일반 계정에서 su를 사용하고자 할 때, 다음과 같이 Sorry 메시지를 띄우며 루트 계정으로의 진입을 거부한다. 루트 계정에서 휠 사용자 추가하기 (첫번째 방법) 휠wheel은 서버에서 관리자 작업을 수행할 수 있는 사용자(계정)들을 말한다. 일반 계정이 su 명령을 사용하려면 그 계정을 휠 그룹에 추가해야 한다. 우선, 서버를 관리자 계정으로 로그인한다. 그리고 다음과 같이 파일 시스템(/)을 읽고 쓰기가 가능한 상태로 재마운트한다. # mount -u -w / -w 옵션은 지정된 포인트에 대해 읽고 쓸 수 있는 권한을 지정하여 마운..
Operating System/Unix × FreeBSD
2019. 12. 22. 01:07

[단편 FreeBSD 사용법] 일반 계정에서 su, sudo 명령 사용하기

Operating System/Unix × FreeBSD
2019. 12. 22. 01:07

단편 FreeBSD 사용법


일반 계정에서 su, sudo 명령 사용하기


su명령은 일반 계정에서 루트 계정의 Shell을 띄울 때 사용하는 명령이다. FreeBSD에서는 일반 계정에서 su를 사용하고자 할 때, 다음과 같이 Sorry 메시지를 띄우며 루트 계정으로의 진입을 거부한다.

 

루트 계정에서 휠 사용자 추가하기 (첫번째 방법)


wheel은 서버에서 관리자 작업을 수행할 수 있는 사용자(계정)들을 말한다. 일반 계정이 su 명령을 사용하려면 그 계정을 휠 그룹에 추가해야 한다. 우선, 서버를 관리자 계정으로 로그인한다. 그리고 다음과 같이 파일 시스템(/)을 읽고 쓰기가 가능한 상태로 재마운트한다.

# mount -u -w /

 

-w 옵션은 지정된 포인트에 대해 읽고 쓸 수 있는 권한을 지정하여 마운트하라는 뜻이다. -u는 이미 마운트된 포인트를 다시 마운트하라는 의미이다. 어차피 서버가 부팅될 때 파일 시스템(/)이 마운트되어야 하므로 이를 쓰기 가능한 상태로 재마운트한다는 의미이다. 윈도우로 치면, C:\ 위치에 파일을 추가하고 수정할 때 UAC 확인창이 뜨면서 관리자 권한으로 상승해야 하는 것과 비슷한 조치이다. 그러고 나서 다음 명령을 실행한다.

# pw usermod 계정 -G wheel

pw는 서버의 사용자 및 그룹을 추가/수정/관리하는데 사용되는 명령이다. pw usermod는 사용자를 수정한다는 의미이다. -G Wheel은 휠 사용자 명단에 해당 계정을 추가하라는 의미이다.

 

루트 계정에서 휠 사용자 추가하기 (두번째 방법)

먼저 루트 계정으로 로그인하고 다음과 같이 파일 시스템을 쓰기 가능한 상태로 재마운트 한다.

# mount -u -w /

 

그리고나서 vi/etc/group파일에 다음과 같은 내용을 추가한다.

wheel:*:0:계정

 

아마도 해당 라인에는 이미 루트 계정이 들어가 있을 것이다. 이 때는 컴마를 붙이고 곧바로 휠 사용자로 지정할 계정들을 적는다.

wheel:*:0:root,계정,계정,...

 

재부팅 후 사용


서버를 재부팅하고 일반 계정으로 로그인 후 su를 실행하면 루트 계정으로 쉘이 진입함을 확인할 수 있다. exit를 입력하여 루트 계정을 빠져나갈 수 있다. 한번 더 입력하면 일반 계정도 로그아웃되어 최초 로그인 화면으로 넘어간다.

 

sudo 기능 사용하기


sudo는 아래 명령을 실행하여 패키지를 설치해야 한다.

# pkg install sudo

 

visudo를 실행하여 약 90번째 라인에 있는 주석을 제거한다. 휠 사용자는 sudo를 이용할 수 있게 하는 것인데 만일 특정 사용자에게만 sudo를 이용할 수 있게 하려면 다음과 같은 형식으로 한 줄씩 추가하면 된다.

<사용자> ALL=(ALL) ALL

 

 

루트 사용자에서 빠져 나온 후 다음과 같이 sudo를 실행하여 잘 작동하는지 확인할 수 있다.

 

카테고리 “Operating System/Unix × FreeBSD”
more...
썸네일 이미지
[Windows API] 크리티컬 섹션을 사용하여 스레드간 변수 공유
Windows API 본 시리즈에서는 Windows API 개별 함수에 대해 간략한 사용법 및 응용에 대해 정리한다. 이전 게시글: 스레드의 생존 여부 확인하기 다음 게시글: OutputDebugString을 printf처럼 서식(포맷) 적용하여 사용하기 크리티컬 섹션을 사용하여 스레드간 변수 공유 본 포스팅에서는 크리티컬 섹션(CRITICAL_SECTION) 구조체를 사용하여 스레드간 변수를 공유하는 방법에 대해 정리한다. CRITICAL_SECTION 스레드간 공유하고자 하는 변수와 함께 CRITICAL_SECTION 구조체 변수를 선언한다. /* 스레드간 공유하고자 하는 정수형 변수 */ DWORD g_dwInteger = 0; /* 상기 정수형 변수에 접근하려면 아래 구조체를 통해 권한을 얻어야 ..
API/Windows API
2019. 12. 19. 11:19

[Windows API] 크리티컬 섹션을 사용하여 스레드간 변수 공유

API/Windows API
2019. 12. 19. 11:19

Windows API


본 시리즈에서는 Windows API 개별 함수에 대해 간략한 사용법 및 응용에 대해 정리한다.

이전 게시글: 스레드의 생존 여부 확인하기

다음 게시글: OutputDebugString을 printf처럼 서식(포맷) 적용하여 사용하기

 

크리티컬 섹션을 사용하여 스레드간 변수 공유


본 포스팅에서는 크리티컬 섹션(CRITICAL_SECTION) 구조체를 사용하여 스레드간 변수를 공유하는 방법에 대해 정리한다.

 

CRITICAL_SECTION


스레드간 공유하고자 하는 변수와 함께 CRITICAL_SECTION 구조체 변수를 선언한다.

/* 스레드간 공유하고자 하는 정수형 변수 */
DWORD g_dwInteger = 0;
/* 상기 정수형 변수에 접근하려면 아래 구조체를 통해 권한을 얻어야 한다. */
CRITICAL_SECTION g_stCriticalSection;

 

InitializeCriticalSection


CRITICAL_SECTION 구조체를 사용하기 위해서는 반드시 리셋되어야 한다. 구조체를 리셋하는 함수는 InitializeCriticalSection이다.

VOID InitializeCriticalSection(
    LPCRITICAL_SECTION lpCriticalSection 
);

 

lpCriticalSection 매개변수를 통해 리셋할 CRITICAL_SECTION을 지정한다.

InitializeCriticalSection(&g_stCriticalSection);

 

EnterCriticalSection, LeaveCriticalSection


VOID EnterCriticalSection(
    LPCRITICAL_SECTION lpCriticalSection  
);
BOOL TryEnterCriticalSection(
    LPCRITICAL_SECTION lpCriticalSection
);
VOID LeaveCriticalSection(
    LPCRITICAL_SECTION lpCriticalSection
);

스레드간 공유 변수에 접근할 때 EnterCriticalSection으로 크리티컬 섹션에 진입하고 공유 변수 사용이 끝나면 LeaveCriticalSection으로 크리티컬 섹션을 벗어난다. EnterCriticalSection은 타 스레드에서 크리티컬 섹션을 사용하고 있을 때 대기한다. 대기과정(현재 스레드의 중지) 없이 즉시 사용중 여부를 확인하고자 하면 TryEnterCriticalSection을 사용한다. 임계영역에 진입했다면 TRUE를 반환하고 그렇지 못했다면 FALSE를 반환한다.

EnterCriticalSection(&g_stCriticalSection);
{
    /* ... g_dwInteger에 대한 읽고 쓰기 */
}
LeaveCriticalSection(&g_stCriticalSection);

 

실행 예제


다음은 크리티컬 섹션의 실행 예이다. 창에 대한 스레드, 콘솔창에 대한 스레드 총 2개의 스레드가 실행중이며 콘솔창으로 1부터 30까지 센 후 콘솔창은 닫힌다. 창의 버튼을 클릭하면 콘솔창에서 세고 있는 숫자는 1로 리셋된다. 이 과정에서 크리티컬 섹션이 사용된다.

크리티컬 섹션을 사용하여 공유 변수가 수정될 수 있다.
카테고리 “API/Windows API”
more...
썸네일 이미지
[단막 Windows API] 스레드의 생존 여부 확인하기
단막 Windows API 스레드의 생존 여부 확인하기 본 포스팅에서는 특정 핸들(HANDLE)에 대한 스레드의 생존 여부, 다시 말해서 현재 실행중인지 종료되었는지 여부를 확인하는 방법을 정리한다. GetExitCodeThread 스레드의 생존 여부를 확인할 수 있는 함수로는 GetExitCodeThread가 있다. 이 함수의 원형은 다음과 같다. BOOL GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode ); hThread는 생존 여부를 확인하고자 하는 스레드의 핸들(HANDLE)이다. lpExitCode를 통해 특정 스레드의 생존 또는 종료 코드를 얻을 수 있다. 생존 여부를 확인할 수 있으면 TRUE를 반환하고 그렇지 않으면(즉, 오류가 발생하면) F..
API/Windows API
2019. 12. 18. 22:57

[단막 Windows API] 스레드의 생존 여부 확인하기

API/Windows API
2019. 12. 18. 22:57

단막 Windows API


스레드의 생존 여부 확인하기


본 포스팅에서는 특정 핸들(HANDLE)에 대한 스레드의 생존 여부, 다시 말해서 현재 실행중인지 종료되었는지 여부를 확인하는 방법을 정리한다.

 

GetExitCodeThread


스레드의 생존 여부를 확인할 수 있는 함수로는 GetExitCodeThread가 있다. 이 함수의 원형은 다음과 같다.

BOOL GetExitCodeThread(
    HANDLE hThread,
    LPDWORD lpExitCode
);

 

hThread는 생존 여부를 확인하고자 하는 스레드의 핸들(HANDLE)이다. lpExitCode를 통해 특정 스레드의 생존 또는 종료 코드를 얻을 수 있다.

생존 여부를 확인할 수 있으면 TRUE를 반환하고 그렇지 않으면(즉, 오류가 발생하면) FALSE를 반환한다. 이 때 오류 내용은 GetLastError 함수로 확인 가능하다.

스레드의 생존 여부를 위해 GetExitCodeThread를 호출하는 예이다.

BOOL fResult = FALSE;
DWORD dwExitCode = 0;
/* ... */
fResult = GetExitCodeThread(/* THREAD */, &dwExitCode);

 

위와 같이 호출하여 dwExitCode의 값이 STILL_ACTIVE이면 해당 스레드는 현재 실행중인 상태임을 의미한다. 해당 스레드가 종료되었다면, 종료 당시 스레드 프로시저가 리턴한 값이 보관된다. 여기서 알 수 있는 사실은, 스레드 프로시저를 작성할 때 종료 코드를 STILL_ACTIVE와 중복시키면 안 된다는 사실이다. STILL_ACTIVE의 실제 값은 정수 259이다.

 

실행 예제


static TCHAR szTextBuffer[4096];
HANDLE hThread = /* CreateThread(...) */;
DWORD dwErrorCode = 0;
/* ... */
GetExitCodeThread(hThread, &dwErrorCode);
if (dwErrorCode == STILL_ACTIVE) {
    _stprintf(szTextBuffer, TEXT("WM_USER: hThread = %08p, dwErrorCode = STILL_ACTIVE\n"), hThread);
} else {
    _stprintf(szTextBuffer, TEXT("WM_USER: hThread = %08p, dwErrorCode = %08lx\n"), hThread, dwErrorCode);
}
OutputDebugString(szTextBuffer);
/* ... */

 

버튼으로 채워진 창을 하나 열고, 이 창이 열릴 때 오랜 시간이 걸리는 작업을 수행하는 콘솔창도 하나 더 띄운다. 이 콘솔창은 스레드가 종료되면 자동으로 닫힌다. 버튼을 클릭하면 GetExitCodeThread을 실행하여 해당 스레드의 생존 여부를 디버그 출력창으로 보일 것이다.

스레드가 실행중일 때는 STILL_ACTIVE 값이 반환된다.

 

스레드가 종료되었을 때는 해당 프로시저의 리턴 값을 알 수 있다.
카테고리 “API/Windows API”
more...
썸네일 이미지
[단막 Windows API] CreateThread로 스레드 생성하기
단막 Windows API CreateThread로 스레드 생성하기 본 포스팅에서는 CreateThread를 사용하여 스레드를 생성하는 간단한 예를 정리한다. 새 스레드에서 실행할 프로시저 형식 새 스레드에서 호출할 프로시저의 형식(시그니처)은 다음과 같이 정의한다. DWORD (LPVOID lpParam); lpParam 매개변수는 CreateThread 함수를 실행할 때 스레드로 전달될 수 있다. 위 형식을 따라 콘솔 창을 열고 1부터 30까지 세는데 1,000 밀리세컨드마다 지연시키는 프로시저를 작성해 보겠다. lpParam에는 이 스레드를 만든 부모 창 HWND를 전달한다고 약속한다. DWORD ThreadProc(LPVOID lpParam) { HWND hWnd = (HWND)lpParam; /..
API/Windows API
2019. 12. 15. 20:13

[단막 Windows API] CreateThread로 스레드 생성하기

API/Windows API
2019. 12. 15. 20:13

단막 Windows API


CreateThread로 스레드 생성하기


본 포스팅에서는 CreateThread를 사용하여 스레드를 생성하는 간단한 예를 정리한다.

 

새 스레드에서 실행할 프로시저 형식


새 스레드에서 호출할 프로시저의 형식(시그니처)은 다음과 같이 정의한다.

DWORD <NAME>(LPVOID lpParam);

 

lpParam 매개변수는 CreateThread 함수를 실행할 때 스레드로 전달될 수 있다.

위 형식을 따라 콘솔 창을 열고 1부터 30까지 세는데 1,000 밀리세컨드마다 지연시키는 프로시저를 작성해 보겠다. lpParam에는 이 스레드를 만든 부모 창 HWND를 전달한다고 약속한다.

DWORD ThreadProc(LPVOID lpParam) {
    HWND hWnd = (HWND)lpParam;
    /* 새 콘솔창을 띄운다. */
    AllocConsole();
    
    /* 새 콘솔창에 맞추어 표준 입출력 핸들을 다시 연다. */
    freopen("CONIN$", "r", stdin);
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
    
    printf("Console Created!\n");
    
    /* 1000 밀리세컨드의 간격을 두고 1부터 30까지 출력한다. */
    while (TRUE) {
        static int count = 0;
        
        printf("count = %d\n", ++count);
        Sleep(1000);
        
        if (count >= 30) break;
    }
    
    /* 5000 밀리세컨드의 여유를 두고 콘솔창을 닫는다. */
    Sleep(5000);
    FreeConsole();
    
    /* 이 스레드를 종료한다. */
    return 0;
}

 

새 스레드 생성 및 실행


CreateThread의 원형은 다음과 같다.

HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES   lpThreadAttributes,
    DWORD                   dwStackSize,
    LPTHREAD_START_ROUTINE  lpStartAddress,
    LPVOID                  lpParameter,
    DWORD                   dwCreationFlags,
    LPDWORD                 lpThreadId
);

 

매개변수에 대한 자세한 내용은 MSDN을 참조한다. 여기에서는 간략한 사용법만을 보기 위해 각종 보안 코드들은 생략한다. 다음은 가장 간단한 호출법이다. lpStartAddress(3번째 매개변수)에 앞서 작성한 프로시저를 지정하고, lpThreadId(마지막 매개변수)에 새로 생성된 스레드의 ID값이 전달된다. 반환되는 값은 생성된 스레드의 핸들(HANDLE)이다.

hThread = CreateThread(NULL, 0, [PROCEDURE], (LPVOID)[PARAMETER], 0, &[THREAD ID]);

 

다음은 실제 소스에 작성한 예이다.

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
    /* 중략 */
    switch (uMessage) {
    /* 중략 */
    case WM_CREATE:
    {
        /* 창을 생성할 때 스레드도 함께 생성한다. */
        HANDLE hThread = NULL;
        DWORD dwThreadId = 0;
        
        hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)hWnd, 0, &dwThreadId);
    }
    break;
    /* 중략 */
    }
    /* 중략 */
}

 

실행 결과


프로그램을 실행하면 빈 창과 함께 콘솔창이 출력된다. 콘솔창이 1부터 30까지 세고 닫히는 동안 창에서는 GUI 이벤트를 독립적으로 수행할 수 있다.

1부터 30까지 센 다음 콘솔창을 닫는다. 이 창의 스레드는 창의 스레드와 다르다.
카테고리 “API/Windows API”
more...

“2019/12” (8건)