C/코딩

스트리밍 데이터 처리

동바리 2022. 1. 1. 17:16

 저는 회사에서 mbed 또는 yocto linux를 이용하여 펌웨어를 작성하는 업무를 진행합니다. 업무를 진행하던 중 gps를 처리해야하는 일이 생겼었는데, 인터넷의 예제를 이용해 코딩을 진행하다가 꽤 큰 곤란을 겪었습니다. 그래서 어떤식으로 처리를 해야하는지 많은 고민을 했었는데, 그 해결법을 이번 글에 포스팅하겠습니다.

 

 gps 모듈은 전원을 공급하면, 곧바로 gps 메시지를 출력합니다. 이는 Tera Term같은 에뮬레이터를 이용하여 확인할 수 있습니다. 그리고 전원 공급을 멈출때까지 계속 출력을 진행합니다. 일종의 스트리밍 데이터인것이죠. 앞으로는 이러한 스트리밍 데이터를 아래와 같은 코딩 방법으로 처리하려고 합니다.

 

1. blocking I/O 기법 이용

 

이렇게 처리해야겠다 생각이 든것은 can-utils에 포함된 candump 툴의 코드를 봤기 때문입니다

https://github.com/linux-can/can-utils 

 

GitHub - linux-can/can-utils: Linux-CAN / SocketCAN user space applications

Linux-CAN / SocketCAN user space applications. Contribute to linux-can/can-utils development by creating an account on GitHub.

github.com

 candump는 can 데이터를 처리할 때 이용합니다. 예시로 can 시뮬레이터와 리눅스 디바이스를 연결하고 시뮬레이션할 때 "candump can0"와 같은 명령어를 이용합니다. can0 채널로 올라오는 can 데이터를 터미널에 출력합니다.

 

 그럼 candump는 연속적으로 들어오는 데이터, 즉 스트리밍 데이터를 어떻게 처리하느냐... 아래와 같습니다.

candump.c

 

while (running) {
        num_events = epoll_wait(fd_epoll, events_pending, currmax, timeout_ms);
        if (num_events == -1) {
            if (errno != EINTR)
                running = 0;
            continue;
        }
        
        ......

 실제 코드는 훨씬 깁니다만, candump가 I/O를 처리하는 방식은 epoll_wait 펑션을 이용합니다. 더 자세히 알려면 epoll_wait의 디스크립션을 봐야겠죠.

  The epoll_wait() system call waits for events on the epoll(7)
       instance referred to by the file descriptor epfd.  The buffer
       pointed to by events is used to return information from the ready
       list about file descriptors in the interest list that have some
       events available.  Up to maxevents are returned by epoll_wait().
       The maxevents argument must be greater than zero.

       The timeout argument specifies the number of milliseconds that
       epoll_wait() will block.  Time is measured against the
       CLOCK_MONOTONIC clock.

       A call to epoll_wait() will block until either:

       • a file descriptor delivers an event;

       • the call is interrupted by a signal handler; or

       • the timeout expires.

       Note that the timeout interval will be rounded up to the system
       clock granularity, and kernel scheduling delays mean that the
       blocking interval may overrun by a small amount.  Specifying a
       timeout of -1 causes epoll_wait() to block indefinitely, while
       specifying a timeout equal to zero cause epoll_wait() to return
       immediately, even if no events are available.

       The struct epoll_event is defined as:

           typedef union epoll_data {
               void    *ptr;
               int      fd;
               uint32_t u32;
               uint64_t u64;
           } epoll_data_t;

           struct epoll_event {
               uint32_t     events;    /* Epoll events */
               epoll_data_t data;      /* User data variable */
           };

       The data field of each returned epoll_event structure contains
       the same data as was specified in the most recent call to
       epoll_ctl(2) (EPOLL_CTL_ADD, EPOLL_CTL_MOD) for the corresponding
       open file descriptor.

       The events field is a bit mask that indicates the events that
       have occurred for the corresponding open file description.  See
       epoll_ctl(2) for a list of the bits that may appear in this mask.

candump.c에서의 epoll_wait의 timeout은 -1로 설정되어 있습니다.

 int timeout_ms = -1; /* default to no timeout */

timeout이 없다는것입니다. 즉, timeout이 없는 blocking인것을 확인할 수 있습니다.

 

candump 명령어는 회사에서 테스트해본 결과 ns 단위의 I/O도 정상적으로 처리하는 것으로 확인했습니다. 실제로 시뮬레이터 동작과도 일치하고요.

 

스트리밍 데이터를 어떻게 처리해야 고민이 많았었는데, 괜찮은 가이드를 찾은것 같습니다.