开学了,第一周是各种忙,有好几天没有更新博客了,今天这里分享一个我自己用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驱动示例代码