学驱动从模块开始

通用的Makefile模板

ifeq ($(KERNELRELEASE),)

#KERNELDIR ?= /home/lht/kernel2.6/linux-2.6.14

KERNELDIR ?= /lib/modules/$(shell uname -r)/build  
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else
    obj-m := hello.o
endif

一、简单的模块

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE ("GPL");

int init_module (void)
{
  printk (KERN_INFO "Hello world\n");
  return 0;
}

void cleanup_module (void)
{
  printk (KERN_INFO "Goodbye world\n");

二、标准的模块

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE ("GPL");

static int __init hello_2_init (void)
{
	printk (KERN_INFO "Hello world\n");
	return 0;
}

static void __exit hello_2_exit (void)
{
	printk (KERN_INFO "Goodbye world\n");
}

module_init (hello_2_init);
mo
三、参数的学习

#define DRIVER_AUTHOR "Foobar"
#define DRIVER_DESC   "A sample driver"

MODULE_LICENSE ("GPL");
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_SUPPORTED_DEVICE ("TestDevice");

static short int myshort = 1;
static int myint = 420;
static long int mylong = 9999;
static char *mystring = "blah";
static int array[2]= {-1, -1};
static int arr_argc = 0;

module_param (myshort, short, 0000);
MODULE_PARM_DESC (myshort, "A short integer");

module_param (myint, int, 0000); 
MODULE_PARM_DESC (myint, "An integer");

module_param (mylong, long, 0000); 
MODULE_PARM_DESC (mylong, "A long integer");

module_param (mystring, charp, 0000);
MODULE_PARM_DESC (mystring, "A character string");

module_param_array (array, int, &arr_argc, 0000);
//module_param_array (array, int, arr_argc, 0000); //for kernel<2.6.10
MODULE_PARM_DESC (array, "An array of integers");

static int __init hello_2_init (void)
{
	int i;

	printk (KERN_INFO "myshort is a short integer: %hd\n", myshort);
	printk (KERN_INFO "myint is an integer: %d\n", myint);
	printk (KERN_INFO "mylong is a long integer: %ld\n", mylong);
	printk (KERN_INFO "mystring is a string: %s\n\n", mystring);

	for (i=0; i<arr_argc; i++)
		printk (KERN_INFO "array[%d] = %d\n",i, array[i]);
	printk (KERN_INFO "Got %d arguments in array\n", arr_argc);

	return 0;
}

static void __exit hello_2_exit (void)
{
	printk (KERN_INFO "hello driver cleaned up\n");
}

module_init (hello_2_init);
module_exit (hello_2_exit);
四、proc的操作

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>

MODULE_LICENSE ("GPL");

int hello_read_procmem (char *buf, char **start, off_t offset, int count, int *eof, void *data)
{
  int len = 0;
  len = sprintf (buf, "Hey, there! hello from hello_read_procmem\n");
  *eof = 1;
  return len;
}

static void hello_create_proc (void)
五、ioctl
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>

#include "hello.h"

MODULE_LICENSE ("GPL");

int hello_major = 250;
int hello_minor = 0;
int number_of_devices = 1;
char data[128]="\0";

struct cdev cdev;
dev_t dev = 0;

static int hello_open (struct inode *inode, struct file *file)
{
  printk (KERN_INFO "Hey! device opened\n");
  return 0;
}

static int hello_release (struct inode *inode, struct file *file)
{
  printk (KERN_INFO "Hmmm! device closed\n");
  return 0;
}

int hello_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
  int ret=0;

  switch (cmd) {
    
  case HELLO_ONE:
    printk (KERN_INFO "HELLO_ONE called\n");
    break;

  case HELLO_TWO:
    printk (KERN_INFO "HELLO_TWO called\n");
    break;

  default:
    break;
  
  }

  return ret;
}


struct file_operations hello_fops = {
  .owner = THIS_MODULE,
  .open  = hello_open,
  .release = hello_release,
  .ioctl = hello_ioctl,
};

static void char_reg_setup_cdev (void)
{
  int error, devno = MKDEV (hello_major, hello_minor);
  cdev_init (&cdev, &hello_fops);
  cdev.owner = THIS_MODULE;
  cdev.ops = &hello_fops;
  error = cdev_add (&cdev, devno , 1);
  if (error)
    printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);

}

static int __init hello_2_init (void)
{
  int result;

  dev = MKDEV (hello_major, hello_minor);
  result = register_chrdev_region (dev, number_of_devices, "hello");
  if (result<0) {
    printk (KERN_WARNING "hello: can't get major number %d\n", hello_major);
    return result;
  }

  char_reg_setup_cdev ();
  printk (KERN_INFO "hello_ioctl driver done\n");
  return 0;
}

static void __exit hello_2_exit (void)
{
  dev_t devno = MKDEV (hello_major, hello_minor);
  
  cdev_del (&cdev);

  unregister_chrdev_region (devno, number_of_devices);

  printk (KERN_INFO "hello_ioctl cleaned up\n");
}

module_init (hello_2_init);
module_exit (hello_2_exit);

测试程序:

int main (void) 
{
	int fd;
	fd = open ("/dev/hello",O_RDWR);
	if (fd < 0) {
	  printf ("fd open failed\n");
	  exit(0);
	}
	printf ("\n/dev/hello opened, fd=%d\n",fd);
	ioctl (fd, HELLO_ONE);
	ioctl (fd, HELLO_TWO);
	close (fd);
	printf ("/dev/hello closed :)\n");
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值