linux内核与驱动-驱动程序范例

来源:互联网 发布:lvm安装linux 编辑:程序博客网 时间:2024/05/17 08:03

范例中以一个经典的hello驱动程序为例

 

$vim hello.c创建源码文件

程序有几个重要的部分

a. 引用两个基本的头文件linux/init.hlinux/module.h;

b. MODULE_LICENSE("Dual BSD/GPL")

  此申明是告诉内核,该模块采用自由许可证,没此申明则内核在装载该模块时会产生抱怨,就好像内核在说,你(此模块)遵循GNU GPL规定,有问题的话后果自负;

c. module_init(func_init)insmod加载内核时,会调用func_init初始化函数

  module_exit(func_exit)rmmod卸载内核时,会调用func_exit退出函数

程序代码如下

///////////////////////////////////////////////START/////////////////////////////////////////////

#ifndef __KERNEL__

#  define __KERNEL__

#endif

#ifndef MODULE

#  define MODULE

#endif

 

#include <linux/init.h>

#include <linux/module.h>

#include <linux/sched.h>

#include <linux/kdev_t.h>

#include <linux/fs.h>

#include <linux/cdev.h>

 

//定义模块的版本

#define MODULEVERSION "1:1.0"

 

MODULE_LICENSE("Dual BSD/GPL");//申明此模块遵循GPL规定

MODULE_AUTHOR("jayson_jang");//申明此模块的作者

MODULE_DESCRIPTION("hello test");//申明对此模块的描述

MODULE_VERSION(MODULEVERSION);//申明此模块的版本

MODULE_ALIAS("hello_test.ko");//申明此模块的别名

//MODULE_DEVICE_TABLE("ALL", "bycle");

 

/*

模块支持一下数据类型

bool invbool charp int long short uint ulong ushort

*/

//变量申明

static char *whom = "world";

static int howmany = 1;

static bool boolflag=1;

static char name[2][16]={"name1", "name2"};

static int num = 2;

static int major=0, minor=0;

//static invbool invboolflag=1;

//将申明的变量传入到此模块,S_IRUGO代表所有人可读此变量

module_param(howmany, int, S_IRUGO);

module_param(whom, charp, S_IRUGO);//charp代表是char指针类型

module_param(boolflag, bool, S_IRUGO);

module_param_array(name, charp, &num, S_IRUGO);

module_param(major, int, S_IRUGO);

module_param(minor, int, S_IRUGO);

 

void func1(void)

{

        printk("func1\r\n");

}

EXPORT_SYMBOL_GPL(func1);//导出func1,遵循GPL的其他模块可调用此函数

 

//模块初始化函数,__init代表此模块初始化完后,此函数将被简单的丢弃

static int __init hello_init(void) 

 

{

  int err=0, i=0;

  dev_t devid=0;

 

  //printk打印字符,KERN_ALERT代表将打印输出到控制台和日志文件中

  printk(KERN_ALERT "Hello,world\n");

 

  //current->comm代表此进程名,current->pid代表此进行id

  //current定义在linux/sched.h头文件中,可直接使用

  printk(KERN_ALERT "The process is \"%s\", pid is %d\n", current->comm, current->pid);

  //根据输入的howmany变量打印howmanywhom

  for(i=0; i<howmany; i++)

printk(KERN_ALERT "are you ok,%s\n", whom);

 

  printk(KERN_ALERT "boolflag = %d\n", boolflag);

  //printk(KERN_ALERT "invboolflag = %d\n", invbool(boolflag));

  //打印输入的二维字符数组

  for(i=0; i<2; i++)

    printk(KERN_ALERT "age[%d]:%s\n", i, name[i]);

  if(err)

    goto err_exit;

 

  if(major)  //如果定义了主设备号

  {

    devid = MKDEV(major, minor); //MKDEV生成设备号

    register_chrdev_region(devid, 1, "hello");//注册设备号,并命名为hello

  }

  else

  {

    alloc_chrdev_region(&devid, minor, 1, "hello");//动态分配设备号

    printk(KERN_ALERT "minor:%d\r\n", minor);

    major = MAJOR(devid);//MAJOR获取主设备号,MINOR获取次设备号

    printk(KERN_ALERT "major:%d\r\n", major);

  }

  return 0;

err_exit:

  return EBADTYPE;

}

 

//模块卸载函数,__exit代表此函数仅仅用于模块卸载,如此模块不允许卸载则丢弃

static void __exit hello_exit(void)

{

  dev_t devid=0;

 

  printk(KERN_ALERT "Goodbye,cruel world\n");

  printk(KERN_ALERT "The process is \"%s\", pid is %d\n", current->comm, current->pid);

  //printk(KERN_ALERT "UTS_RELEASE: %s \n", UTS_RELEASE);

 

  printk("printk1\n");//没有KERN_ALERT则为默认级别,结尾有加\n,则会打印

  printk("printk2");//没有KERN_ALERT则为默认级别,结尾没有加\n,则不会打印

 

  devid = MKDEV(major, minor);

  unregister_chrdev_region(devid, 1);//释放设备号

}

 

module_init(hello_init); //模块初始化函数入口

module_exit(hello_exit);//模块卸载函数入口

///////////////////////////////////////////////END/////////////////////////////////////////////

 

$vim Makefile创建Makefile编译文件,源码如下

///////////////////////////////////////////////START/////////////////////////////////////////////

#Makefile 2.6

objs = hello.o

ifneq ($(KERNELRELEASE),)

        mymodule-objs:=${objs}

        obj-m:=${objs}

else

        PWD:=$(shell pwd)

        KVER?=$(shell uname -r)

        KDIR:=/usr/src/linux-${KVER}  //安装的内核源码树的位置

        #KDIR:=/usr/src/linux-headers-2.6.32-21-generic/

all:

        $(MAKE) -C $(KDIR) M=$(PWD) modules

clean:

        @rm -rf *.com *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers

endif

///////////////////////////////////////////////END/////////////////////////////////////////////

 

$make 

  生成hello.mod.c hello.o Module.symvers hello.ko hello.mod.o modules.order

$tail -f /var/log/message //新打开一个字符终端输入此命令用于查看模块加载、卸载打印

$sudo insmod hello.ko   //加载内核,会看到如下打印

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208007] Hello,world

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208021] The process is "insmod", pid is 2357

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208022] are you ok,world

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208024] boolflag = 1

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208025] age[0]:name1

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208026] age[1]:name2

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208029] minor:0

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.208030] major:249

$sudo rmmod hello.ko   //卸载内核,会看到如下打印

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236285] Goodbye,cruel world

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236303] The process is "rmmod", pid is 2358

Apr 15 23:27:16 jayson-desktop kernel: [ 4322.236308] printk

0 0
原创粉丝点击