Practice/Emacs

CentOS 7 emacs-25.1 64bits RPM

GUI 환경에서 GNU Emacs


터미널 환경에서 GNU Emacs


  1. cat emacs-common-25.1-3.el7.centos.x86_64.rpm-a* > emacs-common-25.1-3.el7.centos.x86_64.rpm
저작자 표시 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Practice/C & C++

C언어에서 struct 정의 그대로 이진 데이터로 만들기

C의 struct를 이진 데이터로 저장하고 불러오는데 원하는대로 되지 않을 때가 있다.
예를 들어, 2 바이트 이후에 적혀야 하는데 4바이트 뒤에 위치하는 경우이다.


예상한 이진 데이터의 구조:


실제 이진 데이터의 구조 (목표 머신-target machine-을 64 bits로 컴파일한 경우):


이는 데이터 구조체 정렬(data structure alignment) 때문에 발생한다.
데이타 구조체 정렬이란 해당 머신의 읽고 쓰는 단위 크기의 배수로 데이타를 할당하는 것을 말한다.
데이터가 이 배수값보다 작으면 데이터 구조체 패딩(data structure padding)을 해준다.


현대의 컴퓨터는 성능을 높이기 위해서 이런 방식을 기본으로 사용한다.
따라서, 프로그래머가 정확한 이진 데이터를 생성하려면 이 기능을 꺼야 한다.


GCC에서는 __attribute__((packed)) 키워드를 사용하여 가장 작은 데이타를 만든다.
즉, padding이 들어가지 않도록 한다.

typedef struct __attribute__((__packed__)) seg_info_s {
    uint64_t stt;
    uint32_t seq;
    uint64_t dur;
    uint8_t  flags;
    uint64_t offset;
    uint32_t size;
    uint8_t  key_id[16];
    char     path[PATH_MAX+1];
} seg_info_t;


Visual C에서는 #pragma pack(1) 지시어를 사용하여 1 바이트 경계에 정렬하도록 명시한다.

#pragma pack(1)

typedef struct seg_info_s {
    uint64_t stt;
    uint32_t seq;
    uint64_t dur;
    uint8_t  flags;
    uint64_t offset;
    uint32_t size;
    uint8_t  key_id[16];
    char     path[PATH_MAX+1];
} seg_info_t;


저작자 표시 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Practice > C & C++' 카테고리의 다른 글

C언어에서 struct 정의 그대로 이진 데이터로 만들기  (0) 2017.01.13
strspn/strcspn  (0) 2013.07.09
Practice/Debugging

교착상태(deadlock)를 프로세스 상태와 디버거를 사용해서 찾아내기

멀티미디어(multimedia) 소스를 입력을 받아서 가공하여 출력하는 프로그램을 개발하고 있었다.
얼마간 동작하다가 아무것도 출력하지 못하는 문제를 일으켰다.
로그를 살펴보니 입력 모듈이 돌아가는 쓰레드(thread)에서 데이타를 읽지 않고 있었다.


무한 루프에 빠져서 기능이 중단되었을 수 있다.
이는 프로세스가 CPU를 과도하게 점유하는지를 살펴보면 알 수 있다.
top 유틸리티로 확인해보니 오히려 CPU 점유율이 정상보다 더 낮았다.


다음으로 교착상태(deadlock)를 의심할 수 있다.
프로세스 상태를 보면 더 의심이 간다.


문제의 상태에 진입한 프로세스를 gdb에 붙여서 상태를 확인했다.

$ gdb -p <PID>

쓰레드 목록을 얻고, 각 쓰레드의 콜스택(call stack)을 살펴봤다.

- 쓰레드 목록 얻기 :

(gdb) info thread

- 쓰레드 이동 하기 :

(gdb) thread <THREAD-ID>

- 콜스택 보기 :

(gdb) bt


문제의 모듈이 속한 쓰레드를 발견하였다.
예상대로 잠그려고 대기중인 상태를 보여주었다.
더불어, 잠금을 획득하고 멈춰있는 다른 쓰레드-이후 잠금 요청을 대기하게 만든 쓰레드-까지 발견했다.


잠금을 획득하고 멈춰있는 쓰레드의 콜스택과 코드를 자세히 분석했다.
잠금을 걸고 네트워크를 통해서 요청을 보낸 후에 응답을 받는 부분에서 멈추었다.


멈춘 싯점에서 로그를 역순을 분석하였다.
문제와 연관된 네트워크 세션의 로그와 관련 코드를 중점적으로 살펴봤다.
네트워크 세션을 잠금을 사용하지 않고 접근하여 오염시키는 코드를 찾았다.
이 코드를 수정하여 문제를 해결하였다.

저작자 표시 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
  1. M/D Reply

    비밀댓글입니다

Practice/Debugging

버젼 관리 시스템을 사용하여 문제를 해결하기

초반에는 문제의 원인을 충분히 넓게 잡아라."에서 중요한 디버깅 기법 하나를 간단하게 언급하고 넘어갔다.

분석의 과정이 없이 추론에 근거하여 새로 추가된 원격 기능과 캐싱 알고리즘만을 의심했다.
코드를 수정해도 상태가 개선되지 않았다.
... 중략 ...
이전 버젼과 차이점을 면밀하게 비교하면서 비로서 문제의 원인을 발견했다.
같은 환경과 같은 기능(즉, 로컬 파일 읽기)에서도 새 버젼에서 동일한 문제가 일어났다.
즉, 새로운 기능이 동작할 때 발생하는 것이 아니란 의미이다.
로깅 시스템을 리펙토링을 했는데, 이와 연관이 깊을 것으로 추정했고 다양한 테스트로 이를 검증했다.

- 2014/07/15 - [Practice/Debugging] - 초반에는 문제의 원인을 충분히 넓게 잡아라.


이것이 버젼 관리 시스템을 사용하는 이유이다.
간결하고 의미있고 커밋 로그를 추가하면 문제를 찾아내는데 더 수월하다.

저작자 표시 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Practice/VLC

VLC 미디어 재생의 데이타 흐름 다이어그램

아래는 VLC로 미디어 파일을 재생할 경우 구성되는 요소와 데이터의 흐름을 나타낸 다이어그램이다.
read는 받는 쪽에서 데이터를 가져오는 방식이고
send/play는 보내는 쪽에서 밀어내는 방식이다.
thread간에는 fifo(queue)로 이용하는 데이터를 전달한다.



VLC의 객체 간의 구성을 데이타 흐름과 같이 구성해보면 다음과 같다.
실선은 객체의 부모/자식의 관계,
두꺼운 점선(···)은 데이타의 흐름과 관련된 구성(연결관계),
점선(---)은 객체의 일부 구성(포함관계)을 나타낸다.



2013/06/17 - [Practice/FFmpeg] - FFmpeg 데이타 흐름 다이어그램


저작자 표시 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Practice > VLC' 카테고리의 다른 글

VLC 미디어 재생의 데이타 흐름 다이어그램  (0) 2016.12.16

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

카운터

Today : 14
Yesterday : 105
Total : 158,502

티스토리 툴바