본문 바로가기
개발/리눅스

드라이버 개발 연습 #2

by -=HaeJuK=- 2024. 5. 21.

2024.05.21 - [개발/리눅스] - 드라이버 개발 연습 #1

LoadDriver, UnLoadDriver 구현하기 

선행 조사 

libudev

libudev는 udev 장치 관리 시스템과 상호 작용하기 위한 라이브러리.
udev는 Linux 커널의 장치 파일 시스템(devfs)와의 인터페이스를 관리하는 시스템입니다.
libudev는 다음과 같은 기능을 제공합니다:

  1. 장치 탐지 및 열거: 시스템에 연결된 장치들을 탐지하고 나열할 수 있습니다.
  2. 장치 속성 조회: 장치의 속성(예: 장치 파일, 속성 값)을 조회할 수 있습니다.
  3. 장치 이벤트 모니터링: 장치 추가, 제거 등의 이벤트를 모니터링할 수 있습니다.

libudev는 주로 사용자 공간에서 하드웨어 장치를 관리하고, 장치 이벤트에 반응하는 데 사용됩니다.

libkmode

libkmode는 특정 드라이버나 모듈 로딩 및 언로딩과 같은 커널 모듈 관련 작업을 수행하기 위한 라이브러리입니다. 그러나 libkmode는 일반적으로 널리 사용되는 라이브러리가 아니며, 표준 Linux 배포판에서는 제공되지 않습니다. 커널 모듈을 로드하고 언로드하는 일반적인 방법은 modprobe 명령을 사용하는 것입니다. 커널 모듈 관리는 주로 다음을 포함합니다:

  1. 모듈 로드: 특정 커널 모듈을 커널에 로드합니다.
  2. 모듈 언로드: 특정 커널 모듈을 커널에서 언로드합니다.
  3. 모듈 정보 조회: 현재 로드된 모듈 목록과 정보를 조회합니다.

커널 모듈 로드와 언로드는 주로 insmod, rmmod, modprobe 명령을 통해 수행됩니다.

주요 차이점

  • 목적:
    • libudev는 주로 장치 관리와 장치 이벤트 처리를 위해 사용됩니다.
    • libkmode는 커널 모듈(드라이버) 로드 및 언로드와 관련된 작업을 수행합니다.
  • 기능:
    • libudev는 장치 탐지, 열거, 속성 조회, 이벤트 모니터링 등 사용자 공간에서 장치와 상호 작용하는 기능을 제공합니다.
    • libkmode는 커널 모듈 로드, 언로드, 모듈 정보 조회 등의 커널 모듈 관리 기능을 제공합니다.
  • 사용 사례:
    • libudev는 데스크탑 환경, udev 규칙 작성, 장치 관리 도구 등에서 널리 사용됩니다.
    • libkmode는 특정 응용 프로그램에서 커널 모듈을 동적으로 관리해야 할 때 사용될 수 있지만, 일반적으로 이러한 작업은 명령줄 도구(modprobe 등)로 수행됩니다.

결론

일반적인 Linux 시스템에서 커널 모듈(드라이버)을 로드하고 언로드하는 작업은 libudev가 아닌 modprobe 명령을 통해 수행하는 것이 표준적입니다. libudev는 장치 관리에 중점을 두고 있으므로 드라이버 로드/언로드 작업보다는 장치 이벤트 처리와 관리에 더 적합합니다.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <stdexcept>
class cDriverManager 
{
public:
    cDriverManager() 
    {
        try
        {
            m_ssDistro = GetDistro();
        }
        catch (const std::runtime_error& e)
        {
            std::cerr << e.what() << std::endl;
            throw; // 재던지기
        }
    }
    void LoadDriver(const std::string& _ssDriverName) 
    {
        std::string command = "sudo modprobe " + _ssDriverName;
        ExecuteCommand(command);
    }
    void LoadDriver(const char* _pszDriverName) 
    {
        std::string command = "sudo modprobe " + std::string(_pszDriverName);
        ExecuteCommand(command);
    }
    void UnloadDriver(const std::string& _ssDriverName) 
    {
        std::string command = "sudo modprobe -r " + _ssDriverName;
        ExecuteCommand(command);
    }
private:
    std::string m_ssDistro;
    std::string GetDistro() 
    {
        std::ifstream file("/etc/os-release");
        if (false == file.is_open()) 
        {
            throw std::runtime_error("Cannot open /etc/os-release");
        }
        std::string line;
        while (std::getline(file, line)) 
        {
            if (0 == line.find("ID=")) 
            {
                return line.substr(3);
            }
        }
        throw std::runtime_error("Cannot determine distribution");
    }
    void ExecuteCommand(const std::string& command) 
    {
        int ret = std::system(command.c_str());
        if (0 != ret) 
        {
            throw std::runtime_error("Failed to execute command: " + command);
        }
    }
};
int main() 
{
    try 
    {
        cDriverManager driverManager;
        driverManager.LoadDriver("dummy_driver");   // Replace "dummy_driver" with the actual driver name
        std::cout << "Driver loaded successfully.\n";
        driverManager.UnloadDriver("dummy_driver"); // Replace "dummy_driver" with the actual driver name
        std::cout << "Driver unloaded successfully.\n";
    } 
    catch (const std::runtime_error& e) 
    {
        std::cerr << e.what() << std::endl;
        return 1;
    }
    catch (const std::exception& e) 
    {
        std::cerr << "An unexpected error occurred: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

 

반응형