흐르는 시간의 블로그...


이직을 한 후 첫 프로젝트에서 데이터 직렬화를 위해 FIFO를 사용하고자 했다.

IPC를 사용할 경우 해제 문제라든지 경험이 부족한 나에게는 문제 해결능력이 부족하므로 최대한

단순하게 FIFO를 사용하고자 했다.

그러나, 결국 엄청난 문제를 야기하고 말았으니... ㅠ.ㅠ

초기 테스트 시에는 동시에 다중으로 입력되는 데이터에 대해 정상적으로 처리가 되었다.

그러나 테스트가 본격적으로 시작한 후 10초 대에 4197byte 패킷이 2~6개씩 들어오면서 문제가 바로 발생했다.

FIFO를 읽는 측에서 데이터를 찍어보니...
첫번째 패킷이 4096 바이트까지만 찍히는 것이다.
그 직후 다른 패킷이 저장되었다. 전체 데이터 길이에는 이상이 없었다.

처음에는 FIFO에 write 하는 프로세스들이 데이터를 쓰면서 엉키는것이라 생각해서 세마포를 걸었다.

이게 더 큰 문제를 야기했다.

FIFO는 write를 해야 해당 프로세스가 종료한다.
따라서, write의 안정성을 위해 write를 세마포 안쪽에 넣어두면...
내 처리 프로세스에서 하나씩 밖에 데이터 처리를 할 수 밖에 없었다.

따라서, 수신 프로세스들이 기하급수적으로 fork되면서 삭제 되지 않고 세마포를 대기 했다.

아래의 그림은 참조하면 이해에 도움이 될것이다.

Listener Proc A : Listen --> Accept --> Read Data --> 세마포 wait --> data write --> 세마포 post
Listener Proc B : Listen --> Accept --> Read Data --> 세마포 wait
Listener Proc C : Listen --> Accept --> Read Data --> 세마포 wait


Gather Proc Z : trigger --> data read --> send...

위에서 보면... Proc A에서 FIFO에 data write를 하려고 하면 data write 상태로 대기하게 된다.
따라서 B와 C는 FIFO에 write를 못하게 된다.

결국 Z는 한번에 하나씩의 데이터만 처리 가능하다.


또한 앞에서 문제가 된 4096바이트의 문제는 각 OS의 커널에서 정의된 파이프의 크기에 의해 결정된다.

http://wiki.kldp.org/wiki.php/%B8%AE%B4%AA%BD%BA%C7%C1%B7%CE%B1%D7%B7%A1%B8%D3%B8%A6%C0%A7%C7%D1%B0%A1%C0%CC%B5%E5

위 링크의 "6.2.4 파이프의 Atomic 동작 (Atomic Operations with Pipes)"를 보면 FIFO는 PIPE_BUF 크기 내에서는 원자성을 보장한다.

따라서, FIFO 사용시 OS에서 제공하는 PIPE_BUF값을 넘지 않는 데이터의 write는 동기화 오브젝트를 사용할 필요가 없다.


결국, 위의 내용들에 따라 FIFO와 Semaphore를 사용한 코딩은 실패했다.


대안으로 찾은 방안으로 Shared Memory와 Semaphore를 사용한 방식이다.

Shared Memory는 앞쪽에 인덱스 영역을 두고 그 뒷쪽에 Queue처럼 데이터 버퍼를 두어 사용하였다.

예상외로 쉬운 접근 방식으로 코딩이 가능하였다.

기회가 되면 코드와 함께 적어보도록 하겠다.

조금이라도 도움이 되었길 빌며...

그럼 이만.... ^^;