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


이직을 한 후 첫 프로젝트에서 데이터 직렬화를 위해 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처럼 데이터 버퍼를 두어 사용하였다.

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

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

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

그럼 이만.... ^^;




1. 하드 디스크 파티션 및 용량 보기 ( h옵션은 표기 단위를 쉽게 보여줌)
df - h

2. 현재 이하 디렉토리 용량 보기 ( h옵션은 표기 단위를 쉽게 보여줌)
du -h

3. Mysql 실행 및 종료
실행 : mysqld_safe &
종료 : mysqladmin -uroot -p shutdown

4. 프로세스 전체 보기 (필요시 grep 이용)
ps -ef
ps -ef | grep mysql

5. 네트웍 상태 보기
netstat -lnp

6. 서버 default 각종 포트 확인(아래의 파일 확인)
/etc/services

7. 로그파일이나 변하는 텍스트 파일의 tail을 보는 방법 (30줄 단위)
tail -30f mylog.txt





C++ 빌더를 사용할때는 ForceDirectory()라는 좋은 함수가 있었다.
말 그대로... 파라미터만 주면 디렉토리를 다 만들어 준다.
리눅스 에서 코딩하는데 해당 기능이 없어서 자료를 찾다가...
지워진 링크에서 자료를 찾았다. ^^

----------------------------------------------------------------------------------------------------------------------------------------

출처 : http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/

Most people are probably familiar with the UNIX utility, mkdir(1). The mkdir utility makes directories (surprise surprise). There is a matching mkdir(2) system call available in the POSIX standard C library. The usage is pretty straightforward - how ever, the command-line executable, mkdir(1), supports a useful option -p to "create intermediate directories as required". Its very convenient to run `mkdir -p' on a long path before copying things or whatever, since you don't have to worry about the directory structure not existing.However, the mkdir(2) library function doesn't support an analogous mode. If you want to recursively create all the intermediate directories in a path in your program, you must implement this yourself. I've used this same function in at least three distinct projects now and so I decided to post the code:

/* Function with behaviour like `mkdir -p'  */intmkpath(const char *s, mode_t mode){        char *q, *r = NULL, *path = NULL, *up = NULL;        int rv;        rv = -1;        if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0)                return (0);        if ((path = strdup(s)) == NULL)                exit(1);             if ((q = strdup(s)) == NULL)                exit(1);        if ((r = dirname(q)) == NULL)                goto out;                if ((up = strdup(r)) == NULL)                exit(1);        if ((mkpath(up, mode) == -1) && (errno != EEXIST))                goto out;        if ((mkdir(path, mode) == -1) && (errno != EEXIST))                rv = -1;        else                rv = 0;out:        if (up != NULL)                free(up);        free(q);        free(path);        return (rv);}


해석하기 귀찮아서... ㅡㅡ;

구글의 index 저장에 남아 있고 본 링크에는 남아 있지 않음...

Make a "C++ Attach to Application" debug configuration. Start your program using
your normal debug configuration. After the fork occurs, select the "Attach to
Application" fro, the debug icon. A dialog box with all of the running processes
should appear. Choose the process you want to debug and it should appear in the
"Debug" control panel.

There is a tutorial that shows a video conference, somewhere, that explains the

process and goes through an example. I was able to get it to work for me.

--------------------------------------------------------------------------------------------

For debugging a child process on Linux, gdb has the ability to step into a child process after fork and exec. This behavior can be enabled with the follow-fork-mode child statement.

Put the statement

set follow-fork-mode child

in the .gdbinit file, located in the project work directory.
Now, setting some breakpoints in the code of the child process will cause gdb to halt execution.

Btw, I’ve looked for a corresponding GUI option in the debug dialog (CDT version 4.0.3), but I found none. So it seems that creating a .gdbinit file is currently the only solution for this.