Linux下QT加载ko驱动示例代码

Linux C/C++ 浅灬笑 3687℃ 0评论

开学了,第一周是各种忙,有好几天没有更新博客了,今天这里分享一个我自己用QT纯C++代码加载驱动的模块儿,当然你也可以使用代码调用shell脚本来完成ko驱动程序的加载,但是作为从Windows下转过来的人,真心不喜欢在程序里面调用明文的shell文件= =。

首先看一下使用Shell脚本加载驱动的做法

在使用sh文件的时候我使用了2个文件,一个是驱动的加载操作,另外一个是驱动的卸载操作。

① install.sh驱动加载:

#! /bin/sh
module=memory
#加载模块
insmod ./$module.ko || exit 1
#获取设备号
major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
#创建设备节点,即创建文件/dev/memory
mknod /dev/$module c $major 0

从代码种可以看出,这里给出的模块儿名称为”memory”,首先是insmod操作,然后通过awk命令获取到设备号,最后创建一个设备节点②remove.sh 移除驱动模块儿的操作。

#! /bin/sh
module=memory
#删除设备文件
rm -f /dev/${module}
#移除模块
rmmod memory

从代码种可以看出,首先是删除对应的设备文件,最后是移除掉对应的模块儿即可。

在QT中通过纯C++代码完成对驱动的加载(C++单例)

在这个模块儿中实际上也是通过执行相应的命令来完成对ko驱动的加载的,在上面的sh文件中的代码,这里全部通过system函数进行完成。

cdriverhelper.h

#pragma once

#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <asm-generic/ioctl.h>

typedef std::string STDString;
/*
 * Class:CDriverHelper
 * Author:QianXiao
 * Desc:
 * This Class is a tookit for kernel driver operation
 * Note:
 * This Class IS A SINGLE CLASS
*/
#define DEF_SINGLE(type) friend class SingleBase<type>;
//Single Base TPL
template<typename T>
class SingleBase
{
public:
 static T* GetSingle()
 {
 static T temp;
 return &temp;
 }
protected:
 SingleBase(){};
public:
 virtual ~SingleBase(){};
};

//CDirverHelper
#define DRVIER_SYMBOLIC_NAME "/dev/memory"
//这是一个相对了路径,相对于可执行文件的路径
//例如我的可执行程序的位置是 /test/exefile
//驱动程序的位置为 /test/MemSys/memory.ko
#define DRIVER_REL_PATH "/MemSys/" //驱动的相对路径
#define DRIVER_NAME "memory.ko" //驱动程序的名称
#define DRIVER_MEM_NAME "memory" //设备名称 dev/XXXX种的XXXX

class CDirverHelper :public SingleBase<CDirverHelper>{
 DEF_SINGLE(CDirverHelper);
protected:
 CDirverHelper();
 virtual ~CDirverHelper();
protected:
 int m_DriverFD;//File Descriptor For Driver
public:
 int GetFD();//Return File Descriptor;
protected:
 STDString GetDriverPath();
 bool LoadDriver();
};

cdriverhelper.cpp

#include "cdriverhelper.h"

CDirverHelper::CDirverHelper()
{
 m_DriverFD = -1;
 if(!LoadDriver ()){
 QMessageBox::about(NULL, "error" , "Load Driver Erro!") ;
 }
}

CDirverHelper::~CDirverHelper()
{
 if(m_DriverFD!=-1){
 close(m_DriverFD);
 //rm device file
 STDString szRmDevFile = "rm -f /dev/";
 szRmDevFile+=DRIVER_MEM_NAME;
 system (szRmDevFile.c_str ());
 //rm mod form kernel
 STDString szRm = "rmmod ";
 szRm+=DRIVER_MEM_NAME;
 system (szRm.c_str ());
 }
}
/*
 * Auto Get the driver's abs path
*/
STDString CDirverHelper::GetDriverPath()
{
 char szCurWorkPath[256];
 memset(szCurWorkPath,'\0',256);
 int nRet = readlink ("/proc/self/exe", szCurWorkPath , 256);
 if(nRet>256||nRet<0){
 QMessageBox::about(NULL, "error" , "Read Exe Path Erro") ;
 return "";
 }
 //Sub String,Delete The File name,only need The floder path
 for(int i=nRet;i>0;i--){
 if(szCurWorkPath[i]=='/' || szCurWorkPath[i]=='\\'){
 szCurWorkPath[i]='\0';
 break;
 }
 }
 STDString szRet = szCurWorkPath;
 szRet+=DRIVER_REL_PATH;
 //folder path + relative path is the driver path
 return szRet;
}
/*
 * Load Driver,true is OK ,false is Erro
 */
bool CDirverHelper::LoadDriver()
{
 STDString szRelFolderPath = this->GetDriverPath ();// /XX/xxs/
 //Empty Path ,return erro
 if(szRelFolderPath.compare ("")==0){
 return false;
 }

 STDString szRelKOPath =szRelFolderPath+DRIVER_NAME; // /XX/xxs/xx.ko
 //Start Loading Driver
 //Try Open it
 this->m_DriverFD = open(DRVIER_SYMBOLIC_NAME,O_RDONLY);
 //Open Success,it said that the driver has been loaded
 if(this->m_DriverFD>=0){
 return true;
 }
 //first load it
 STDString RedirTmpFile = szRelFolderPath+"NoTmp";
 STDString InserKOStr = "insmod "+szRelKOPath;

 int nSystem = system (InserKOStr.c_str ());
 if(nSystem<0){
 //Something Wrong
 QMessageBox::about(NULL, "insmod Erro,Driver Path is Follow" , InserKOStr.c_str ()) ;
 return false;
 }
 //Create Device Node
 STDString szCmd = "awk '$2==\"" ;
 szCmd+=DRIVER_MEM_NAME;
 szCmd+="\" {print $1}' /proc/devices >";
 szCmd+=RedirTmpFile;
 nSystem = system (szCmd.c_str ());
 if(nSystem<0){
 //Something Wrong
 QMessageBox::about(NULL, "awk erro,cmd is Follow" , szCmd.c_str ()) ;
 STDString szRm = "rmmod ";
 szRm+=DRIVER_MEM_NAME;
 system (szRm.c_str ());
 return false;
 }
 //Read Tmp File To Get The Node Number
 int tfd = open(RedirTmpFile.c_str (),O_RDWR);
 char buf[16];
 memset(buf,'\0',16);
 int nRead = read(tfd,buf,16);
 if(nRead<=0){
 QMessageBox::about(NULL, "Read Tmp File Erro!",RedirTmpFile.c_str ()) ;
 STDString szRm = "rmmod ";
 szRm+=DRIVER_MEM_NAME;
 system (szRm.c_str ());
 return false;
 }
 for(int ib=0;ib<16;ib++){
 if(buf[ib]=='\n'){
 buf[ib]='\0';
 break;
 }
 }
 STDString szMkNoCmd ="mknod /dev/";
 szMkNoCmd+=DRIVER_MEM_NAME;
 szMkNoCmd+=" c ";
 szMkNoCmd+=buf;
 szMkNoCmd+=" 0";
 // QMessageBox::about(NULL, "mknod Erro,cmd is Follow" ,szMkNoCmd.c_str ()) ;
 nSystem = system(szMkNoCmd.c_str ());
 if(nSystem<0){
 QMessageBox::about(NULL, "mknod Erro,cmd is Follow" ,szMkNoCmd.c_str ()) ;
 STDString szRm = "rmmod ";
 szRm+=DRIVER_MEM_NAME;
 system (szRm.c_str ());
 return false;
 }
 //Open it
 this->m_DriverFD = open(DRVIER_SYMBOLIC_NAME,O_RDONLY);
 if( this->m_DriverFD<0){
 QMessageBox::about(NULL, "Open Devices Erro" ,"0x00000001") ;
 STDString szRm = "rmmod ";
 szRm+=DRIVER_MEM_NAME;
 system (szRm.c_str ());
 return false;
 }
 return true;
}
int CDirverHelper::GetFD()
{
 return m_DriverFD;
}

在使用的时候无需关心,驱动的加载,直接获取到对应的驱动FileDescriptor即可,例如:

 int fd = CDirverHelper::GetSingle ()->GetFD ();

因为是单例,当程序退出的时候,单例会被释放,析构函数中已经完成了对驱动的关闭。

CDriverHelper下载地址

百度网盘: http://pan.baidu.com/s/1o6y3w86  提取密码 hcnb

转载请注明:悠然品鉴 » Linux下QT加载ko驱动示例代码

喜欢 (1)or分享 (0)
发表我的评论
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址