首页 > 技术相关 > Linux(ubuntu)下开发并添加内核模块

Linux(ubuntu)下开发并添加内核模块

2011年11月15日 sigma 发表评论 阅读评论

首先,大致有以下一些地方需要用到Linux内核编程:

  • 驱动开发,linux下的大部分驱动都是以内核模块的形式执行的。
  • 使用了一些特权指令的程序,比如wrmsr这些指令,这些指令需要在ring0下执行,一般这种程序也是以内核模块的形式执行。

下面简要介绍一下,一个Hello world的内核模块开发并且添加的过程(其实网上很多教程,但是发现都是针对比较老的内核,有些已经不适用了,因此,在此处,我在罗唆一下,也当是个备忘)。

  1. 首先需要安装开发库和头文件。
    $:sudo apt-get install linux-kernel-devel
    $:sudo apt-get install linux-headers-`uname -r`
  2. 写个hello_kernel.c(我保留了我代码中的获取cpuID的代码,所以严格不算helloword了),下面代码中printk是内核中的printf,打印的信息回打到内核log中,可以通过dmesg或者cat /var/log/kern.log查看。module_init以及module_exit分别为内核进入以及退出的函数。
    #include <linux/module.h>
    //#include <linux/config.h>//这个头文件在老的内核中有,新的内核已经没有了,因此注释调
    #include <linux/init.h>
    
    void bcopy(unsigned char *src,unsigned char *des,int count)
    {
    	int i=0;
    	for (i=0;i<count;i++)
    	{
    	  printk("src[%d]=%x\n",i,src[i]);
    	  des[i]=src[count-i];
    	}
    
    }
    
    void get_CPUID()
    {
        // 定义一些变量,用于存储 CPU 的 ID信息
    
        char szCpu[16]={0};
      unsigned int szCpu0,szCpu1,szCpu2;
        unsigned int uCpuID;
      int i = 0;
    
        __asm__ __volatile__(
          "push %%ebx;"
          "push %%ecx;"
          "push %%edx;"
          "mov $0, %%eax;"
          "cpuid;"
          "mov %%ebx, %0;"
          "mov %%edx, %1;"
          "mov %%ecx, %2;"
          "mov $1, %%eax;"
          "cpuid;"
          "mov %%edx, %3;"
          "pop %%ebx;"
          "pop %%ecx;"
          "pop %%edx;"
          :"=r"(szCpu0),"=r"(szCpu1),"=r"(szCpu2),"=r"(uCpuID)
          :
        );
      printk("szCpu0=%x,szCpu1=%x,szCpu2=%x\n",szCpu0, szCpu1, szCpu2);
      bcopy((unsigned char *)&szCpu0,(unsigned char *)szCpu,4);
      bcopy((unsigned char *)&szCpu1,(unsigned char *)(szCpu+4),4);
      bcopy((unsigned char *)&szCpu2,(unsigned char *)(szCpu+8),4);
      for(i = 0; i < 16; i++)
        printk("szCpu[%d]=%c\n",i,szCpu[i]);
    
        printk("cpu id is %u, info is %s\n", uCpuID,szCpu);
    }
    
    static int __init mymodule_init(void)
    {
      printk("Hello Kernel\n");
            get_CPUID();
      return 0;
    }
    
    static void __exit mymodule_exit(void)
    {
       printk ("Unloading my module.\n");
               return;
    }
    
    module_init(mymodule_init);
    module_exit(mymodule_exit);
    
    MODULE_LICENSE("GPL");
  3. 编译:编译的话,首先写哥makefile:
    obj-m += hello_kernel.o
    CUR_PATH := $(shell pwd)
    KERN_VER := $(shell uname -r)
    KERN_PATH := /usr/src/linux-headers-$(KERN_VER)
    all:
    		make -C ${KERN_PATH} M=${CUR_PATH} modules
    clean:
    		make -C ${KERN_PATH} M=${CUR_PATH} clean
  4. make,没有错误的话,可以通过下面命令将模块加载到内核。
    sudo insmod hello_kernel.ko
  5. 可以在dmesg或者cat /var/log/kern.log查看printk打印的信息。需要卸载模块的话,可以:
    sudo rmmod hello_kernel

更多更仔细的介绍的可以参看这篇文章(虽然中间有些说法现在直接用的话会有些问题。)

本文作者: Sigma    在新浪微博关注SigmaSigmaWeibo    RSS订阅本博客
本文链接: http://www.sigma.me/2011/11/15/linux-add-kernel-module.html
本博客采用知识共享署名—非商业性-禁止演绎使用3.0协议进行许可,转载请保留作者和原文链接。

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.

无觅相关文章插件,快速提升流量