본문 바로가기

4. 기술창고, Warehouse

리눅스 프로그래밍 관련 팁들..


======================================================================
 Broken Pipe 방지
======================================================================

시스템에서 보내는 시그널 처리.
보통 Socket 을 사용하는 프로그램에서는 SIGPIPE 를 받게 되는데 이는 비정상적인 socket 에 I/O 를 요청할 때 자주 발생.

이 [SIGPIPE] 시그널을 그냥 반환값을 통한 오류 처리만을 할 경우

signal(SIGPIPE, SIG_IGN);

........을 이용. (SIGPIPE 시그널이 오면 무시)

이와 같은 방법으로 SIGTERM 을 처리하면 더욱 좋음.

프로그램이 실행되고 있는 도중 reboot 을 하게되면 실행중인 모든 Process 에 SIGTERM 이 전달,
이를 받아 처리하는 루틴을 만들면 프로그램을 안전하게 종료할 수 있기 때문.

 


======================================================================
 gdb를 이용한 callstack 출력
======================================================================
 
gdb로 띄워서 bt 입력하면 backtrace (또는 callstack).


프로그램이 언제 죽을지 모른다거나,
gdb를 하루종일 보고 있을 수 없을 때, 혹은 오류난 곳의 callstack 을 남기고 싶을 때


--batch 옵션
+
--command 옵션
+
> 를 통한 파일 저장
= output
 

아래 cmd 파일 내용을 보면
handle SIGPIPE nostop으로 gdb가 [SIGPIPE] (=Broken pipe) 시그널을 무시하게 하고
r(un)명령으로 프로그램을 실행하다가 멈추면
echo 이후 명령이 실행됨.


예시) 실행
gdb --batch --command=cmd ./MyApp > "bt_`date +%y%m%d%k%M%S`.log"


예시) cmd 파일 내용
handle SIGPIPE nostop
r
echo "-------------------------------------------"
echo "error--------------------------------------"
echo "-------------------------------------------"
thread
echo "-------------------------------------------"
echo "thread 1 - Game Thread---------------------"
echo "-------------------------------------------"
thread 1
bt full
echo "-------------------------------------------"
echo "thread 2 - Thread Library------------------"
echo "-------------------------------------------"
thread 2
bt full
echo "-------------------------------------------"
echo "thread 3 - DB Thread ----------------------"
echo "-------------------------------------------"
thread 3
bt full




======================================================================
 gdb 로 실행 중인 프로세스 디버깅
======================================================================

gdb 로 실행 중인 프로세스를 디버깅 가능 (MS VC++ 도 역시 가능)


gdb 로 디버깅 할 때 보통
 $ gdb filename

이렇게 실행하고 gdb 프롬프트에서 run 으로 실행.


여기에서 실제 수행중인 프로세스를 디버깅 하려면

방법1
 $ gdb filename pid


방법2
 $ gdb filename
 gdb> attach pid


이렇게 하면 gdb에 들어가는 순간 break 가 걸림.
이후 원하는 디버깅을 하고 c(continue) 하면 프로그램은 수행을 계속함.

더해서,
프로그램을 계속 실행 상태로 두고 gdb 를 종료할 때는

 gdb> detach
 gdb> quit (or q)

프로세스와 분리, 이후 종료됨.


이것을  batch 모드와 섞어 쓰게 되면...


 $ cat gdbcmd.txt
 b MyApp.cpp:1234
 c
 set flag=true
 detach
 quit

 $ gdb --batch --command gdbcmd.txt MyApp 1234


위와 같이 실행하면,
PID 1234로 실행 중인 MyApp 프로그램이 디버깅이 시작되고
batch 모드를 따라 MyApp.cpp의 1234 라인에 브레이크를 걸고 실행을 계속함.
그리고 break 가 걸리면 flag 변수의 값을 true 로 변경하고
실행을 계속하도록 하면서 gdb 만 종료됨.


이 방법을 응용해 런타임에 원하는 변수 값을 수행 가능.



======================================================================
 리눅스 라이브러리 제작
======================================================================


1. 정적 라이브러리 1

 1) Object 파일 생성
  $ gcc -c test.c

 2) 라이브러리 생성
  $ ar r libtest.a test.o

 3) 인덱스 생성
  $ ranlib libtest.a

 4) extern 형태로 선언된 헤더 파일 만들기

 

2. 정적 라이브러리 2

 1) Object 파일 생성
  $ gcc -c test.c

 2) 라이브러리 생성
  $ ar rs libtest.a test.o

 3) extern 형태로 선언된 헤더 파일 만들기

 

3. 공유 라이브러리

 1) 컴파일
  $ gcc -c -fpic test.c

 2) 라이브러리 생성
  $ gcc -shared -o libtest.so test.o

 3) extern 형태로 선언된 헤더 파일 만들기


간단하지만 조금 더 추가하면 완성.