ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 커널 모듈 개발의 기초 - Linux 커널 모듈 프로그래밍 가이드(5.x) 참고
    Linux Kernel 2024. 7. 2. 18:15

    5장 - 커널 모듈 개발의 기초

    5-1. 모듈 시작 & 종료

    프로그램 : main()함수로 시작. ( 진입함수가 main()이다.)

    커널 모듈 : “init_module” 또는 “module_init 호출로 지정한 함수”로 시작 ( 모듈 진입 함수 )

    모듈 진입 함수가 실행되면,

    • 모듈이 제공하는 기능을 커널에 알리고, 필요할 때 모듈의 기능을 실행하게끔 커널 설정.

    이후, 진입함수가 리턴된다.

    모든 모듈은 “cleanup_module” 또는 “module_exit 호출로 지정한 함수”를 호출하며 종료한다.

    모든 모듈은 진입 함수와 퇴출 함수가 있어야 한다.


    5-2. 모듈에서 사용가능한 함수

    pr_info() 함수의 경우 : 표준 입출력 라이브러리 포함 x.

    모듈이 “insmod” 또는 “modprobe”를 실행하면 symbol이 확인되는 object 파일이기 때문.

    기호에 대한 정의는 커널 자체에서 비롯되며,

    사용가능한 외부 함수는 커널에서 제공하는 함수뿐.

     

    라이브러리 함수는 사용자 공간에서 실행되며,

    실제 작업을 수행하는 system call을 위한 인터페이스를 제공하는 용도임.

    라이브러리 함수 printf()는 결국에는 write() system call을 이용한 것뿐임.

     

    이를 확인하려면 strace 명령어를 이용하면 됨.

     

    정리하면, 라이브러리 함수 안씀.


    5-3. user space & kernel space

    일반적으로 user mode에서 라이브러리 함수를 사용함.

    라이브러리 함수는 하나 이상의 system call을 함.

     

    이때 system call은 커널 모드에서 실행되고, system call 작업이 끝나면,

    user mode로 다시 돌아옴.


    5-4. namespace

    프로그램에 의미없는 전역 변수가 많으면 namespace 오염이 발생함.

    되도록 모든 변수를 정적으로 선언하고, symbol에 대해 잘 정의된 접두사(prefix)를 사용해야 함.

    (symbol이 무엇인지 아직은 정확히 모르겠다. )

     

    symbol table을 선언하고 커널에 등록하는 방법도 있음. (정적 선언 방법은 아님 )

    /proc/kallsyms 파일에는 커널이 알고 있는 모든 symbol이 담겨 있으며,

     

    모듈은 커널의 code 영역을 공유하므로 해당 파일에 접근할 수 있다.


    5-5. code space

    ( OS 의 메모리 관리 기법을 알면 쉽게 이해가 된다. )

    ( virtual memory를 이용해 분산 적재, 부분 적재를 할 수 있게 되면서

    실제 메모리보다 더 큰 프로그램을 실행할 수 있게 되었다. )

     

    코드에서 포인터의 주소가 가리키는 공간은 실제 메모리 위치를 가리키지 않는다!

    프로세스가 접근하는 가상 주소는 메모리 영역에서의 offset을 가리킨다.

     

    커널은 자체 메모리 공간을 갖는다.

     

    모듈은 커널에 동적으로 삽입 및 제거할 수 있는 코드이다.

    모듈은 자체 코드 공간을 갖지 않고, 커널 코드 공간을 공유한다.

    모듈에 segfault가 나면, 커널에도 segfault가 발생하므로 주의해야 한다.

     

    물론, 각 모듈이 자체 코드 공간을 갖는 마이크로커널이라는 것도 있다.


    5-6. 장치 드라이버

    unix에서 각 하드웨어는 /dev에 있는 device 파일로 매핑된다.

    여기에서 하드웨어와 통신하는 방법을 제공해준다.

     

    user space 프로그램은 /dev/sound에 어떤 종류의 사운드카드가 설치되어 있는지 몰라도,

    /dev/sound를 사용할 수 있는데,

    별도의 사운드카드 device 드라이버가 device 파일을 사운드 카드에 연결해주기 때문이다.

     

    device 파일에는 주 번호와 부 번호가 있다.

     

    주 번호는 하드웨어에 접근하는 데 사용되는 드라이버를 알려준다.

    부 번호는 드라이버 입장에서 제어하는 하드웨어들을 구분하는 데 사용된다.

     

    아래 사진을 보면,

     

    vcs 의 경우 같은 드라이버를 사용하지만, (주 번호 동일)

    드라이버 입장에서는 이들을 별개로 보면서 서로 다른 하드웨어로 구분해 처리하는 것을 알 수 있다.

     

     

    디바이스는 블록 장치와 캐릭터 장치로 나뉜다.

    블록 장치는 버퍼가 있어서 request를 처리할 최적의 순서를 선택 가능하다.

    블록 장치는 입력을 블록 단위로만 받고 출력을 반환할 수 있다. ( 버퍼링 기능 )

    캐릭터 장치는 원하는 만큼의 바이트를 사용할 수 있다.

     

    대부분의 디바이스는 버퍼링이 필요없고, 고정 블록 크기로 동작하지 않으므로,

    캐릭터 장치이다.

     

    위에 사진에서 보면 시작 영어가 ‘c’이면 캐릭터 장치, ‘b’이면 블록 장치이다.

     

    주, 부 번호가 12, 2인 새로운 캐릭터 장치를 만들고 싶으면

    mknod 명령어를 이용해

    mknod /dev/[new_device] c 12 2 라고 하면 된다.

     

    중요한 점은,

    커널은 device 파일에 대한 접근이 있을 때, 주 번호를 사용해 어느 드라이버를 사용할지 결정할 뿐이고,

    (커널은 부번호를 사용하지 않는다. )

    드라이버는 부 번호를 사용해 하드웨어를 구분한다.

Designed by Tistory.