리눅스 드라이버의 물리주소와 가상 주소

출처: http://chammoru.egloos.com/v/4168312

다른 프로세스의 메모리 공간 접근
프로세스가 시스템 호출을 통해 커널 모드로 진입하면 프로세스 메모리 공간은 커널의 메모리 공간으로 바뀐다. 커널 모드 상태의 프로세스는 수퍼바이저 권한을 갖기 때문에 시스템 내의 모든 메모리 공간에 접근할 수 있다. 그래서 이 경우에는 다른 프로세스의 메모리 공간에 접근할 수 있는데, 이때 직접 접근은 안 되고, VM에서 제공하는 특정 함수를 통해 접근할 수 있다.

리눅스 메모리 관리
. PGD (Page Directory) : pgt_t
. PMD (Page Mid level Directory) : pmd_t
. PTE (Page Table Entry) : pte_t
* 참고 : PMD는 대부분의 리눅스 시스템에 형식적으로만 존재.

물리 주소 공간을 커널 주소 공간으로 매핑
Memory Mapped I/O 방식의 물리적 주소 공간을 커널에서 사용 가능한 가상 주소로 매핑하거나 해제할 때는 다음과 같은 함수 사용한다.

// 아래 두 함수가 성공적으로 mapping되면 가상 주소의 선두 주소가 반환
void * ioremap(unsigned long offset, unsigned long size); // offset이 물리주소, size는 PAGE_SIZE의 배수
void * ioremap_nocache(unsigned long offset, unsigned long size); // offset이 물리주소, size는 PAGE_SIZE의 배수
void iounmap(void * addr); // addr은 가상주소

I/O 물리 주소와 가상 주소간의 변환 함수
리눅스 커널은 부팅 단계에서 시스템을 제어하기 위해 사용하는 시스템의 모든 I/O 제어 물리 주소나 램 영역의 물리 주소를 MMU 테이블로 미리 작성한다. 이렇게 부팅 단계에서 고정되어 할당된 메모리 주소 영역을 예약 영역(reserved area)이라고 한다. 예약된 물리 주소 영역은 PAGE_OFFSET 매크로 상수값을 이용해 물리 주소와 가상 주소간에 변환을 한다. 상수 연산만으로 물리 주소를 가상 주소로 만들기 위해 사용하는 상수와 매크로는 #include 에 정의된다.

부팅 시 예약된 주소 공간 이외에 ioremap(), kmalloc() 함수에서 반환하는 가상 주소도 PAGE_OFFSET을 이용해 물리 주소와 가상 주소로 변한된다. 이 매크로 상수를 이용하여 주소 변환을 하는 함수들은 다음과 같다.

unsigned long virt_to_phys(volatile void * address);
void * phys_to_virt(unsigned long address);
unsigned long virt_to_bus(volatile void * address);
void * bus_to_virt(unsigned long address);

virt_to_phys(), phys_to_virt()
virt_to_phys() 함수는 가상 주소를 물리 주소로 바꾸고, phys_to_virt() 함수는 물리 주소를 가상 주소로 바꾼다. 그러나 phys_to_virt() 함수는 ioremap()함수와 같은 기능을 수행하지 않는다. ioremap()함수는 요구된 물리 주소로 시작하는 영역을 커널 모드에서 사용할 수 있도록 가상 주소 공간으로 등록하지만, phys_to_virt()함수는 PAGE_OFFSET과 같은 값을 이용하여 변환 처리만 하기 때문이다. 그래서 virt_to_phys()와 phys_to_virt()함수는 커널에서 사용할 수 있도록 등록된 가상 주소와 물리 주소에 대해 사용해야 한다.

virt_to_phys(), phys_to_virt()
virt_to_phys()와 virt_to_bus() 함수는 대부분의 커널이 동작하는 시스템에 대해 동일한 기능을 수행한다. phys_to_virt()와 bus_to_virt()함수 역시 같은 기능을 수행한다. 그러나 시스템에 따라 두 함수를 구별하여 사용하는 경우는 극히 드물지만 존재한다. 그래서 리눅스에서는 이 두 종류의 함수를 구별하여 사용해야 한다. DMA와 관련된 루틴에서는 virt_to_bus()와 bus_to_virt()함수를 사용하기를 권장하고, 램이나 비디오와 같은 메모리 관련 주소 공간에는 virt_to_phys()와 phys_to_virt() 함수를 사용하기를 권장한다. 가급적 이 규칙을 지켜야 여러 시스템과 호환되는 디바이스 드라이버로 포팅할 수 있다.

libroxml

홈페이지: http://www.libroxml.net/

roxml

C로 제작된 xml 파서이며 사용하기 아주 쉽고.. 속도도 빠르다.
스크립트 언어로 바인딩하기 좋을것 같다.
아래는 특징.

– load / unload XML document from buffers or files.
– navigate throughout an XML tree using simple getter API.
– handle namespace.
– use xpath syntax to access some nodes in the XML tree.
– read nodes contents (text, attributes, comments …)
– create/modify XML trees and save them to a file or buffer.

다운로드: libroxml-2.3.0.tar.gz

Bohem Garbage Collector

그니까.. C나 C++로 프로그램을 작성하다보면..
메모리 누수가 종종 일어나고.. 잡기 힘들때가 있는데..

이럴땐.. Garbage Collector를 사용하면 됨.
물론 성능 저하가 일어나긴 하겠지만.. 메모리 해제를 신경 쓰지 않아도 되는 큰 장점이…
(GC에 대한 장/단점은 오른쪽의 pdf 문서를 보면 될 것 같고.. 할당한 것은 무조건 해제해야 한다? )

그중.. Boehm GC 는 다음과 같이 define만 해주고 재 컴파일하면 됨.

#define malloc(x) GC_malloc(x)
#define calloc(n,x) GC_malloc((n)*(x))
#define realloc(p,x) GC_realloc((p),(x))
#define free(x) (x) = NULL

MinGW 에서 테스트된 Bohem GC는 아래에서 받았음.

https://gitorious.org/w64/bohem-gc/source/cc848d064720e7dac418fae81a706bbfb2afa019: