2014년 11월 14일 금요일

QNX Neutrino APS 사용하기

항상 네트워크 throughput이 10MB/s 이상을 유지해야 하는 장치를 만든다고 가정하자. 테스트 결과 선택된 시스템의 최고 네트워크 throughput은 60MB/s다. 사용자가 네트워크 기능만 사용한다면 througput이 충분하여 별 문제가 없을 것이다.  하지만 시스템이 다른 작업을 동시에  수행하게 되면 네트워크 througput이 10MB/s 이하로 떨어지는 상황이 발생할 수 있다. 이를 해결하기 위한 간단한 방법은 네트워크 througput 관련된 프로그램의 우선 순위를 높이는 것이다. 하지만 이렇게 할 경우 단지 10MB/s 정도만 유지해도 별 문제가 없는 네트워킹 기능에 필요이상의 CPU가 할당되면서 다른 기능이 원활하게 동작하지 못하는 상황이 발생할 수도 있다. 즉  10MB/s 정도의 througput이면 충분한데 네트워킹 쪽 우선순위가 높아 항상 60MB/s의 성능을 내도록 시스템이 동작할 것이다.

위와 같은 경우 10MB/s 정도의 througput을 처리할 수있는 별도의 전용 CPU가 있으면 어떨까?  QNX의 APS(Adaptive Partitioning Scheduler) 는 한개의 CPU를 논리적으로 여러개의 파티션으로 나누어 위와 같이 특정 프로그램를 위한 전용 CPU로 사용할 수 있도록 해준다(Partitioning).

예를들어 CPU의 총 성능 중 20%만 사용하면 네트워크 througput 10MB/s가 달성된다면 CPU를 80:20로 나누어 네트워크 관련 프로그램을 20% 영역에서 실행시키는 것인다.  이 경우 나머지 프로그램은 80%영역에서 실행되며 사용자가 느끼기에는 마치 서로 영역별로 별개의 CPU를 사용하는 것처럼 스케쥴링이 이루어진다.

이 기능이 제공하는 더 좋은 점은, CPU가 100% 풀 로드가 아닌 상황에서는 파티션이 가변적(Adaptive)으로 동작한다는 점이다. 즉 시스템에 네트워크 기능이 동작하지 않을때는 80%영역에 있던 프로그램이 20%영역의 CPU를 사용할 수 있으며, 반대로 80% 영역에 여유가 많을 때에는 네트워크 관련 프로그램이 80%쪽 CPU를 끌어다 사용할 수 있다.

APS 기능을 사용하려면 IFS 이미지 빌드 스크립트에 아래와 같이 [module=aps]를 추가하여 IFS를 빌드하여야 한다.
[module=aps] PATH=/proc/boot:/bin:/usr/bin:/opt/bin  LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/opt/lib procnto-instr
즉, 만일 현재 사용중인 IFS가 [module=aps]가 없이 빌드된 것이라면 IFS를 바꿔야 한다.

APS 기능은 아래와 같이 실행시킬 수 있다.



위 예제에서는 inetd에 20%의 CPU가 할당되었다. QNX에서 실제로 네트워킹은 io-pkt가 담당하게 되는데, 이 경우에 io-pkt는 서버, inetd는 클라이언트가 된다.  위 예에서 io-pkt가 System쪽에서 실행되었다고 가정하면 inetd의 요청을 받은 io-pkt 서버는 비록 시스템 파티션에서 실행 되었지만 Network partition에서 CPU를 사용하고 inetd 이외의 프로그램이 요청한 네트워크 요청만 System partition에서 수행이 된다.

2014년 11월 13일 목요일

QNX Neutrino에서 램 디스크를 생성하는 여러 가지 방법 (v6.6기준)

1. devb-ram을 사용한 램 디스크 만들기.

1.1 기본값으로 생성하기 
devb-ram을 사용하면 QNX 4 타입의 파일 시스템을 가지는 램 디스크를 메모리에 생성할 수 있다. 아래 그림에서 기본 2MB 용량을 가지는 QNX 4 타입의 램 디스크가 생성 되었음을 확인할 수 있다. 


hd0는 type179 형식(QNX 6 파일 시스템 형식)으로 시스템 메인 하드 디스크이며, 생성된 램 디스크는 hd1로 type 77 형식(QNX 4 파일 시스템 형식)으로 생성되었다. devb-ram이 지원하는 램디스크의 파일 시스템은 QNX 4 파일 시스템이다. 하지만 뒤에서 다른 형식의 파일 시스템을 사용하여 램 디스크를 만드는 방법도 살펴볼 것이다.  

아래 표는 파일시스템 형식별 type번호 표이다.



1.2 장치 이름 바꾸기
기본 생성 시 /dev/아래 hd* 로 생성되는 장치 이름을 disk 옵션 중 name으로 바꿀 수 있다. disk 옵션은 devb-ram이 cam-disk.so 라이브러리로 전달하는 옵션이다. 



1.3  cache 크기 설정
일반적으로 입출력이 느린 블럭 장치는 램 메모리를 cache로 사용하는데, 램 디스크일 경우 cache는 램이 램을 cache하는 것이라 불필요한 성능 저하를 발생시키므로 최소 크기(512k)로 설정하는 것이 좋다. 아쉽게도 최소 크기는 0 바이트가 아니라 512KB 이다. 하지만 설정 시 0으로 설정해도 에러가 나지는 않는다.  cache 설정을 위해서는 blk옵션 중 cache를 사용한다. blk옵션은 devb-ram에서 사용하는 io-blk.so 라이브러로 전달되는 옵션이다. 


Q.) 실제 설정된 cache의 크기는 어떻게 확인할 수 있을까 ? 0으로 설정시 최소 크기인 512k로 설정되는지 확인하는 방법은 ? 

A) blk에 verbose옵션을 추가한다. 서브옵션이 여러가지 일 경우 ,(콤마)를 사용하여 나열하면 된다.
devb-ram disk name=rdsk blk cache=0,verbose
verbose옵션으로 추가된 로그는 sloginfo 명령으로 확인할 수 있다.


1.4 용량 변경
기본으로 생성되는 ramdisk는 512Byte의 blksize와 4096Byte의 capacity를 가진다. 실제 용량은 이 두 값의 곱으로 결정된다. (512 x 4096 = 2MB). 이 두 값은 ram 옵션을 사용하여 변경 가능하다.  아래와 같이 설정시 10MB(10240 x 1024)크기의 ramdisk가 생성된다. 



2. io-blk 내장 기능을 사용하여 램 디스크 만들기 

2.1 기본 사용 방법
devb-ram을 사용할 경우 기본적으로 cache를 사용하게 되므로 램 디스크에서는 불필요한 메모리 복사가 발생하게 된다. 이를 해결하기 위해서 io-blk.so에 내장된 ramdisk 기능을 사용할 수 있다. (이 ramdisk는 cache를 사용하지 않는다.)  io-blk.so는 어떤 블럭 장치 드라이버(devb-xxx)와도 함께 사용이 가능하므로 devb-ram이 아닌 다른 devb-xxxx를 사용하고 있다면, 굳이 devb-ram을 사용할 필요는 없다. 

아래 예에서는 devb-ram과 함께 사용하였는데, 이때 기본적으로 devb-ram이 생성하는 ramdisk를 사용하지 않을 것이므로 이름을 notuse로, 용량은 최소 용량(1 x 512 = 512 byte)으로 설정하였다. 또한 ram 옵션 중 nodinit을 설정하여 생성한 램 디스크를 파티션 및 포맷하지 않도록 한다.  이런한 설정들은 devb-ram이 아닌 다른 블럭 장치 드라이버를 사용할 경우에는 필요가 없다.  ( 여기서는 io-blk.so의 램 디스크 기능을 사용하는 경우이기 때문에 devb-ram의 램 디스크 기능을 최소화 하기 위해서 필요한 설정임) 이번 예에서도 io-blk가 생성하는 램 디스크 용량은 10MB로 하였다.  io-blk.so가 제공하는 램 디스크 기능을 사용 시에는 램 디스크 장치 이름은 변경할 수 없으며 항상 /dev/ram* 로 고정된다. 



- dinit는 생성 된 램 디스크를 파티션하고 QNX 4 타입의 파일 시스템으로 포맷하여 준다.
- cache=0으로 설정 되었지만 512KB가 최소 값이므로 512KB로 설정된다.  이는 램 디스크가 사용하는 것이 아닌, devb-ram이 사용하는 것이다. 위 예에서는 devb-ram이 제공하는 램 디스크를 사용하지 않으므로 이 cache는 그냥 낭비되는 공간이 된다. 하지만 다른 devb-xxx 드라이버를 사용하여 io-blk.so의 램 디스크 기능을 사용한다면, 이 캐시는 해당 블럭 장치가 사용하게 될 것이다. 

This approach has superior performance because it eliminates the memory-to-memory copies of devb-ram, it bypasses cache lookups, and the 4 KB sectors have smaller overheads.


2.2 다른 type의 파일 시스템 사용하기
devb-ram가 제공하는 램 디스크는 QNX 4 형식의 파일 시스템만 사용이 가능하지만, io-blk.so의 내장 램 디스크는 qnx4 파일 시스템 이외에 다른 파일 시스템을 사용할 수 있다. 그러기 위해서는 dinit대신 fdisk를 사용하여 파티션을 수행한 후 원하는 파일 시스템으로 포맷하면 된다. 아래는 dos 파일 시스템을 사용한 예이다. 


By default in QNX Neutrino 6.5 and later, io-blk.so allocates the filesystem buffer cache (blk cache=) on affected ARM platforms from a global memory region (SHMCTL_ANON | SHMCTL_GLOBAL) to avoid the per-process 32 MB limitation. To override this and make the allocation from the normal devb-* process heap, specify blk memory=sysram.
In QNX Neutrino 6.5 and later, io-blk.so by default allocates the filesystem buffer cache (blk cache=) on affected ARM platforms from a global memory region (SHMCTL_ANON | SHMCTL_GLOBAL) to avoid the per-process 32 MB limitation. To override this and make the allocation from the normaldevb-* process heap, specify blk memory=sysram.
 
3. devf-ram을 사용한 램 디스크
devf-ram은 ram상에 QNX의 NOR flash용 파일 시스템인 ffs3를 만들어 준다. 아래와 같이 /dev/fs* 가 생성되며, flashctl 유틸리티를 사용하여 파티션, 포맷 및 파일 시스템에 mount할 수 있다. devf 파일 시스템은 mount 명령은 지원하지 않는다. 
flashcltl에서 -p 옵션으로 마운트할 장치를 선택하고, -e -f 는 각각  erase및 format을 뜻한다. -n으로 mount할 위치를 정하며, -m이 mount 옵션이다. 




주의: 디스크의 크기는 실제 NOR flash의 크기와 마찬가지로 2의 n제곱 단위로 설정해야 한다. (1MB, 2MB,4MB,8MB ...)  예를들어 10MB로 2의 n제곱이 아닌 값으로 설정할 경우에는 10MB가 할당되지 않는다.

4. io-fs-media
io-fs-media를 사용하면 아래와 같이 사용이 가능하다. 

io-fs-media -d tmp,mount=/full_path_to/your_desired_mountpoint

5. /dev/shmem
기본적으로 QNX Netrion는  /dev/shmem에 RAM-based filesystem을 제공한다. 하지만 이는 완전한 파일 시스템이 아니며, 100% POSIX 호환이 되지는 않는다. 따라서 몇몇 utility사용에 제약이 있으며, sub-directory도 지원하지 않는다.  일반적으로 아래와 같이 /dev/shmem을 /tmp에 링크시켜 사용한다. 
ln -sP /dev/shmem /tmp