std::thread 사용법

간단히 스레드를 만들어 테스트 해야할 일이 있어 std::thread를 찾아보고 만들어봤다.

예전에는 boost::thread를 이용했었는데 C++11에 오면서 아예 다 내장되었다는게 놀랍고 신기하다.

#include <iostream>
#include <thread>
#include <windows.h>

char* target_msg = "test";
char msg[1024] = {0,};

void callback_function(int thread_num)
{
    while(true)
    {
        strcpy_s(msg, target_msg);
        //std::cout << "copy (" << thread_num << ")" << std::endl;
        Sleep(10);
    }
}

int main(void)
{
    std::thread thread1(callback_function, 1);
    std::thread thread2(callback_function, 2);

    thread1.join();
    thread2.join();

    return 0;
}

윈도우에서 C++ Boost 사용하기

윈도우에서 C++ 작업시 유용한 Boost 라이브러리를 사용하기 위해서는 빌드를 해야한다. 파일시스템 등을 다루는 등의 운영체제에 의존하는 기능들을 사용하기 위해 빌드해야한다고 한다.

  1. http://www.boost.org 에 들어가서 Boost를 다운 받는다.
  2. 압축을 풀고 디렉토리에 들어가 bootstrap.bat 를 실행한다.
  3. b2 –help 를 실행해서 한번 도움말을 쭉 읽어본다.
  4. 윈도우 커맨드창을 열고 해당 다음의 명령을 입력하여 빌드를 시작한다. 64비트, 디버그/릴리즈 모두, 멀티쓰레드, MPI 사용 안함으로 빌드한다.
  5. b2 variant=debug,release link=static,shared threading=multi address-model=64 –without-mpi -j8 stage
  6. 빌드 옵션은 여러가지가 더 있다. 찾아봐서 자기가 필요한대로 설정한다.
  7. -j8은 몇개의 작업을 동시에 하는지를 결정한다. 4코어인 경우에는 -j4를 해주면 모든 코어를 다 사용하게 된다. 적당하게 설정하는 것이 좋다.

빌드에는 시간이 꽤 걸린다.

다음의 링크를 참조했다.

CentOS에 FreeTDS 설치하기

Step 1. 소스 다운로드

http://www.freetds.org 에서 FreeTDS 소스를 받는다.

Step 2. 압축 해제

다음의 명령으로 압축을 푼다.

gunzip freetds-stable.tgz

압축을 풀면 tar 파일이 하나 나온다. tar xvf 명령으로 압축을 해제한다.

tar xvf freetds-stable.tar

Step 3. 컴파일

압축 해제가 되면 freetds 폴더가 나오는데 여기에 들어가서 컴파일을 시작한다. configure / make / make install 명령으로 실행한다. 난 소스 설치할 때 위치를 지정해서 설치하는 편이라 –prefix 로 위치를 지정했다.

[dongbum@localhost freetds-0.91]$ ./configure --prefix=/usr/local/FreeTDS --enable-msdblib
[dongbum@localhost freetds-0.91]$ make
[dongbum@localhost freetds-0.91]$ make install

실행을 다 하고 나면 /usr/local/FreeTDS 에 freetds 관련 파일들이 설치된다.

Step 4. 라이브러리 파일 경로 설정

/etc/profile 에 LD_LIBRARY_PATH에 freetds의 라이브러리 파일들을 연결해준다. /etc/profile 파일을 vi로 연다음 다음처럼 추가한다.

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/FreeTDS/lib

설정이 적용되도록 재부팅을 한번 해준다.

Step 5. odbc.ini 파일 수정

/etc/odbc.ini 파일에 내가 사용할 DB의 이름을 설정해준다. 내 경우에는 freetds 외에도 sqlite 설정도 같이 추가하였다.

[dongbum@localhost log]$ cat /etc/odbc.ini
[111.222.333.444]
Driver = FreeTDS
Description = 111.222.333.444
Trace = No
Servername = 111.222.333.444
Database = 기본DB이름

[TEST_SQLITE3]
Description = TEST SQLITE
Driver = SQLite
Database = /test/sqlite/test_sqlite.db
StepAPI = NO

Step 6. odbcinst.ini 파일 수정

/etc/odbcinst.ini 파일에도 다음과 같은 설정을 추가해준다. 역시 SQLite를 사용하기 위한 설정도 추가하였다.

[FreeTDS]
Description = v0.64 with protocol v4.2
Driver = /usr/lib64/libtdsodbc.so
UsageCount = 5

[SQLite]
Description = ODBC for SQLite
Driver = /usr/local/lib/libsqlite3odbc.so
Setup = /usr/local/lib/libsqlite3odbc.so
FileUsage = 1
CPTimeout =
CPReuse =

/usr/lib64/libtdsodbc.so 파일은 /usr/local/FreeTDS/lib/libtdsodbc.so 파일을 향하도록 심볼릭링크를 걸어준다.

Step 7. freetds.conf 파일 수정

마지막으로 freetds.conf 파일을 수정해준다. 난 /usr/local/FreeTDS에 설치하였으므로 /usr/local/FreeTDS/etc/freetds.conf 파일을 수정해주면 된다.

[global] 섹션에

client charset = EUCKR
text size = 4290000000
tds version = 4.2

를 추가한다. 캐릭터셋과 tds 버전 등을 지정하는 문구 같은데 이 옵션에 대해 정확히는 나도 잘 모르겠다. 그리고 아까 추가한 서버이름을 그대로 추가해준다.

[111.222.333.444]
host = 111.222.333.444
port = 1433
tds version = 8.0

여기까지 다 설정하고나면 FreeTDS 사용이 가능하다.

리눅스에서 MSSQL 접속이 쉬운게 아니란걸 다시 한번 느낀다.

운영체제별 Pre-defined 정보

프로그램 작성 중 멀티플랫폼으로 개발할 때 현재 작업 중인 컴퓨터에 따라 다른 코드를 사용하게 될 일이 생긴다.

운영체제별로 미리 정의된 define 정보를 따라 다른 코드를 사용하도록 분기하는데 이때 사용하는 define 정보에 대해 모아놓은 사이트가 있었다.

http://sourceforge.net/p/predef/wiki/Home/

내 환경은 회사 컴퓨터 2대는 리눅스와 윈도우, 집 컴퓨터는 맥인 환경에서 같은 코드를 여기저기서 작업할 일이 많은데 최소한 세가지 운영체제에 대한 define 정보는 알고 있어야할듯하다.

CentOS에서 Jenkins 설치하기

jenkins_logo

CentOS에서 Jenkins를 설치하기 위한 문서이다.

CentOS 6.4이고 Jenkins는 2013년 11월 17일 버전으로 한다.

젠킨스를 설치할 디렉토리를 설정하고 거기에 젠킨스 홈페이지인 http://jenkins-ci.org 에서 최신버전을 받아 넣는다. 현재 가장 최신 버전은 1.539 버전이다. 다운로드 받을려면 wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war 명령으로 war 파일을 받을 수 있다. 내 경우에는 /home/jenkins 디렉토리를 만들고 거기에 war 파일을 받아 넣었다.

톰캣의 환경설정을 한다. 내 경우에는 톰캣을 아파치와 연동해서 사용하고 있다.

톰캣의 서버 설정파일인 /etc/tomcat6/server.xml에 가서 다음의 내용르 추가한다.

<Host name="jenkins.도메인.com" appBase="/home/jenkins" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
 <Alias>jenkins.도메인.com</Alias>
 </Host>

난 Alias를 해놨기 때문에 Catalina 디렉토리의 jenkins.도메인.com 디렉토리의 ROOT.xml 파일을 수정해야했다. ROOT.xml 파일에는 다음의 내용을 넣는다.

<?xml version="1.0" encoding="UTF-8"?>
 <Context path="" docBase="" debug="1">
 </Context>

만약 Alias를 쓰지 않는다면 위의 server.xml 설정 파일 중 <Alias></Alias> 부분을 위의 내용으로 바꾸어주면 된다.

service tomcat6 restart 명령으로 톰캣을 재시작한다. 재시작하고 웹브라우저를 연다음 아까 설치한 http://jenkins.도메인.com:8080/jenkins 으로 접속해본다.

안된다…

방화벽의 8080 포트를 열어줘야한다. /etc/sysconfig/iptables 에서 8080 포트를 열어주고 service iptables restart 를 입력하여 방화벽을 재시작한다.

다시  http://jenkins.도메인.com:8080/jenkins 으로 접속하면 다음과 같은 화면이 뜬다.

jenkins_error

JENKINS_HOME이 설정되어 있지 않아 다른 디렉토리를 설정한다는 내용이다.

war 파일을 넣어놓은 디렉토리에 젠킨스 홈디렉토리롤 쓸 디렉토리를 추가한다. 내 경우에는 /home/jenkins/.jenkins 로 정했다.

그다음 /etc/profile에 다음의 내용을 추가한다.

export JENKINS_HOME=/home/jenkins/.jenkins

바로 적용을 위해서 source /etc/profile 을 입력한다. 내용이 적용되면 톰캣을 재시작한다.

다시 같은 위치로 들어가보면 다음처럼 젠킨스 사용 준비가 완료된다.

jenkins_ready

이제 젠킨스를 사용하면 된다.

리눅스에서 boost 라이브러리 빌드하기

부스트 라이브러리를 리눅스에서 사용하기 위한 절차를 기록해본다.

내 서버의 경우는 CentOS 6.4 버전이며 yum을 이용해 최신의 업데이트가 모두 다 되어있는 상태다.

일단 boost.org에서 최신 소스를 받는다. 이 글을 쓰고 있는 2013년 10월 14일 기준으로 1.54 버전이 가장 최신이다. unix용으로는  tar.gz과 tar.bz2 형식으로 제공되고 있는데 아무래도 압축효율이 높은 bz2 파일을 다운 받았다.

적당한 디렉토리에 받은 파일을 놓고 bunzip2 명령을 이용해 압축을 해제하면 tar 파일이 나온다. tar xvf boost_1_54_0.tar 명령을 이용해서 압축을 해제한다.

압축을 해제한 디렉토리로 들어가서 ./bootstrap.sh 파일을 실행한다.

[root@83rpm boost_1_54_0]# ./bootstrap.sh
Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2
Detecting Python version... 2.6
Detecting Python root... /usr
Unicode/ICU support for Boost.Regex?... not found.
Backing up existing Boost.Build configuration in project-config.jam.1
Generating Boost.Build configuration in project-config.jam...
Bootstrapping is done. To build, run:
./b2
To adjust configuration, edit 'project-config.jam'.
Further information:
- Command line help:
./b2 --help
- Getting started guide:
http://www.boost.org/more/getting_started/unix-variants.html
- Boost.Build documentation:
http://www.boost.org/boost-build2/doc/html/index.html
[root@83rpm boost_1_54_0]#

위와 같은 메시지가 나타난다.

메시지에 나타난대로 ./b2 명령어를 입력하면 빌드가 시작된다. 내 서버의 CPU는 Xeon E3 1220 인데도… 꽤나 오래걸린다. 빌드하는 동안 CPU 사용률이 30~50% 정도를 왔다갔다한다. 대략 10~15분 정도 걸리는 것 같다.

cc.compile.c++ bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/token_ids.o
gcc.compile.c++ bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/wave_config_constant.o
common.mkdir bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/cpplexer
common.mkdir bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/cpplexer/re2clex
gcc.compile.c++ bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/cpplexer/re2clex/aq.o
gcc.compile.c++ bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/cpplexer/re2clex/cpp_re.o
gcc.archive bin.v2/libs/wave/build/gcc-4.4.7/release/link-static/threading-multi/libboost_wave.a
common.copy stage/lib/libboost_wave.a
...updated 1084 targets...
The Boost C++ Libraries were successfully built!
The following directory should be added to compiler include paths:
/backup/program/boost_1_54_0
The following directory should be added to linker library paths:
/backup/program/boost_1_54_0/stage/lib
[root@83rpm boost_1_54_0]#

한참 기다리면 위와 같은 메시지가 나온다. 부스트 라이브러리 빌드에 성공했다는 메시지와 컴파일러에서 인클루드할 경로, 라이브러리 경로를 알려주는 메시지이다.

이것으로 끝.

윈도우에서 빌드할 때는 여러가지 옵션을 넣고 한 것 같은데 리눅스에서는 너무 쉽게 끝나서 뭔가 이상하다. 혹시나 이 빌드 방법이 잘못되었다면 다음번에 수정해 나가도록 한다.

boost::thread_group

부스트의 쓰레드 그룹을 사용하기 위한 코드

출처 : http://nerv2000.tistory.com/76

#include "boost/thread.hpp"

class threadFunc
{
    int m_a;
public:
    threadFunc( int a )
    {
        m_a = a;
    }

    void operator()()
    {
        printf("[%d]일단 들어왔네!!! [%d]n", boost::this_thread::get_id(), m_a );

        Sleep(5000);

        printf("[%d] 끝났네 [%d]n", boost::this_thread::get_id(), m_a );
    }
};

int main()
{
    boost::thread_group tg;

    tg.create_thread( threadFunc(1) );                        // 1번 스래드 생성
    tg.add_thread(new boost::thread( threadFunc(2) ) );        // 2번 스래드 생성
    tg.add_thread(new boost::thread( threadFunc(3) ) );        // 3번 스래드 생성

    //모든 스래드가 종료 될때까지 대기
    tg.join_all();

    return 0;
}

Boost alt_sstream_impl.hpp warning C4819 에러 해결 방법

열심히 작업하고 빌드를 하는데 계속 warning 메시지가 떴다.

내용은

1>C:Libraryboost_1_51_0boost/format/alt_sstream_impl.hpp : warning C4819: 현재 코드 페이지(949)에서 표시할 수 없는 문자가 파일에 들어 있습니다. 데이터가 손실되지 않게 하려면 해당 파일을 유니코드 형식으로 저장하십시오. (..srcbusinessservicepbbmcacheMemberInfoManager.cpp)

빌드가 안되는 것도 아니고 프로그램에 오류가 있는 것도 아니지만 뭔가해서 이 메시지를 찾아보았다.

저 메시지를 더블클릭하면 부스트의 alt_sstream_impl.hpp 파일이 열리면서 파일 인코딩에 문제가 있다고 팝업창이 뜬다. 이 파일을 열고 한참 봤지만 문제가 없어보인다. 그냥 인코딩변환해버리면 저 에러메시지가 사라지겠지만 부스트 파일을 건드리는건 여간 기분이 찜찜한지라 구글에서 검색시작.

StackOverflow에서 다음의 글을 찾았다.

http://stackoverflow.com/questions/10501634/warning-c4819-how-to-find-the-character-that-has-to-be-saved-in-unicode

글 내용을 읽어보니 alt_sstream_impl.hpp 파일에 176번 라인의 주석이 문제였다. 에휴…

해결방법은 Notepad++로 이 파일을 열고 176번 라인의 주석을 모두 지워버리고 다시 빌드해보면 위 오류 메시지가 없어진다.

Zookeeper 설치

zookeeper회사 서버시스템에 적용 할 수 있나 알아보기 위해 Zookeeper를 테스트하기로 한다.

일단 아파치-주키퍼 사이트(http://zookeeper.apache.org/)에 들어가 다운로드 링크를 찾아 wget 으로 다운로드한다. 지금 이 포스팅을 하는 시점에서 가장 최신 버전은 3.4.5 버전이다.

압축을 풀면 나오는 디렉토리가 주키퍼의 프로그램 디렉토리이다.

일단 conf 디렉토리로 가서 zoo_sample.cfg 파일을 zoo.cfg 파일로 복사한다.

그리고 bin 디렉토리로 가서 ./zkServer.sh 명령으로 주키퍼를 실행한다.

실행하면 다음과 같은 화면이 출력된다.

JMX enabled by default
Using config: /backup/program/zookeeper-3.4.5/bin/../conf/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}

CentOS의 service 와 마찬가지로 실행옵션을 주면서 실행할 수 있다.

./zkServer.sh start 를 입력했다.

JMX enabled by default
Using config: /backup/program/zookeeper-3.4.5/bin/../conf/zoo.cfg
Starting zookeeper … STARTED

시작되었다고 나왔지만 실제로 프로세스는 떠있지 않았다.

그래서 뭘까 생각해보다가 bin 디렉토리를 보았더니 zookeeper.out 파일이 생성되어 있었다. 이 파일의 내용에는,

nohup: failed to run command `/usr/share/java/bin/java’: 그런 파일이나 디렉터리가 없습니다

라고 되어있다.

아마 환경설정은 zkServer.sh 파일 안에 있을 것이므로 이 파일을 편집에서 java 라는 단어로 검색했으나 문제가 될만한 부분이 없었다. 하지만 보다보니 zkEnv.sh 를 실행하는 부분이 보인다. 파일명으로 보아 환경설정을 파는 파일이 이 파일 같으므로 다시 이 파일을 vi로 열어본다.

중간쯤 가다보면

if [ “$JAVA_HOME” != “” ]; then
JAVA=”$JAVA_HOME/bin/java”
else
JAVA=java
fi

이런 내용이 있다.

자바를 실행할 홈디렉토리를 설정하는 것 같다.

쉘로 나와서 echo $JAVA_HOME 을 입력해보니 /usr/share/java 이라고 뜬다. 그래서 결국은 zookeeper.out 파일에 /usr/share/java/bin/java 이런 경로가 없다고 나온 것이었다.

CentOS 6.4 에서는 java 명령은 사실 경로 설정이 없어도 상관이 없으며 굳이 경로를 넣고 싶다면 /usr/bin/java 로 실행하면 된다. (이 파일은 /etc/alternatives/java 의 심볼링링크이다.)

if [ “$JAVA_HOME” != “” ]; then
JAVA=”$JAVA_HOME/bin/java
else
JAVA=java
fi

이 부분을

if [ “$JAVA_HOME” != “” ]; then
# JAVA=”$JAVA_HOME/bin/java”
JAVA=/usr/bin/java
else
JAVA=java
fi

처럼 바꾸고 다시 ./zkServer.sh start 를 실행한다. 아무 문제 없이 STARTED 되었다고 나오고, 다시 ./zkServer.sh status 를 입력해보면

JMX enabled by default
Using config: /backup/program/zookeeper-3.4.5/bin/../conf/zoo.cfg
Mode: standalone

라고 나오면 실행 성공.

이제부터는 주키퍼를 실제로 사용해보도록 한다.