分类: 嵌入式
2010-08-10 11:16:41
完成一个简单驱动的实验。
步骤:
1 编辑驱动源文件drv_example.c。编写Makefile文件。编译。
看到make的过程中,出现了两个警告,那是内核升级造成的,可以不管。
2 加载编译好的驱动模块。
命令: insmod drv_example.ko
对比上面两幅截图,可以看出驱动模块已经加载到内核当中了。
3 编译写好的测试文件test.c。并执行
可以看出测试成功!
4 卸载驱动。
命令:rmmod drv_example
注:初次加载需要在/dev目录下创建设备节点
命令:mknod /dev/drv_example c 254 0
c表示字符设备,254为主设备号,0为次设备号。
源代码来自顶嵌:
1 drv_example.c
#include
#include
#include
#include
#include
#include
#include
#include "drv_example.h"
#define DRIVER_NAME "drv_example"
static int device_major_number = 0;
MODULE_LICENSE("GPL");
struct example_device {
int usage;
char *data;
int new_msg;
};
struct example_device exampledev;
/* This function handles open for the character device */
static int example_chrdev_open(struct inode *inode, struct file *file)
{
printk ("example_chrdev_open:OK!\n");
return 0;
}
/* This function handles close for the character device */
static int example_chrdev_release(struct inode *inode, struct file *file)
{
printk ("example_chrdev_release:OK!\n");
return 0;
}
/* This function handles read for the character device */
static ssize_t example_chrdev_read(struct file *f, char __user *buf, size_t size, loff_t* off)
{
int length;
int count=size;
printk ("example_chrdev_read:OK!\n");
if(count<0)
return -EINVAL;
if(exampledev.usage)
return -EBUSY;
exampledev.usage=1;
if(exampledev.data ==0 )
return 0;
length = strlen(exampledev.data);
if(length < count)
count=length;
copy_to_user(buf,exampledev.data,count+1);
exampledev.new_msg = 0;
exampledev.usage = 0;
return count;
}
/* This function handles write for the character device */
static ssize_t example_chrdev_write(struct file *f, const char *buf, size_t size,loff_t* off)
{
int count=size;
printk ("example_chrdev_write:OK!\n");
if(count<0)
return -EINVAL;
if(exampledev.usage|exampledev.new_msg)
return -EBUSY;
exampledev.usage = 1;
kfree(exampledev.data);
exampledev.data = kmalloc(sizeof(char)*(count + 1),GFP_KERNEL);
if(!exampledev.data)
return -ENOMEM;
copy_from_user(exampledev.data, buf, count + 1);
exampledev.usage = 0;
exampledev.new_msg = 1;
return count;
}
/* This function handles ioctl for the character device */
static int example_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
/* See which ioctl we are doing */
switch (cmd) {
case IOCTL_1:
printk(KERN_NOTICE "Do task 1:OK! \n");
break;
case IOCTL_2:
printk(KERN_NOTICE "Do task 2::OK! \n");
break;
default:
printk(KERN_NOTICE "No task \n");
break;
}
return 0;
}
/* File operations struct for character device */
static struct file_operations example_fops = {
.owner = THIS_MODULE,
.open = example_chrdev_open,
.release = example_chrdev_release,
.read = example_chrdev_read,
.write = example_chrdev_write,
.ioctl = example_chrdev_ioctl,
};
static int __init example_init (void)
{
int Rv = 0;
device_major_number = register_chrdev(0, DRIVER_NAME, &example_fops);
printk(KERN_ALERT "example_init:OK! \n");
printk(KERN_ALERT "The example device major number is %d ! \n",device_major_number);
return Rv;
}
static void __exit example_cleanup( void )
{
unregister_chrdev( device_major_number, DRIVER_NAME );
printk(KERN_ALERT "example_cleanup:OK! \n");
}
module_init (example_init);
module_exit (example_cleanup);
2 drv_example.h
#ifndef DRV_EXAMPLE_H
#define DRV_EXAMPLE_H
enum IOCTL_FUNCTIONS
{
IOCTL_1=1,
IOCTL_2,
};
#endif
3 Makefile
#Hello world module example Makefile
ifneq ($(KERNELRELEASE),)
obj-m :=drv_example.o
else
#KERNELDIR ?= /home/mike/linux-
KERNELDIR=/lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c
endif
4 test.c
#include
#include
#include
#include
#define MAX_LENGTH 100
int main( int argc, char *argv[] )
{
int DeviceHandle = -1;
char str[MAX_LENGTH];
char buf[MAX_LENGTH];
char *p;
/*Test open operation*/
if((DeviceHandle=open("/dev/drv_example", O_RDWR )) <= 0 )
{
printf("Open ioctl device is failed! \n");
return 0;
}
printf("please enter the words(max char num:%d):\n", MAX_LENGTH - 1);
p = fgets(str, MAX_LENGTH, stdin);
/*Test write operation*/
write(DeviceHandle, p, strlen(p));
/*Test read operation*/
read(DeviceHandle, buf, MAX_LENGTH - 1);
printf("Get strings from drv_example:\n%s\n", buf);
/*Test ioctl operation*/
ioctl(DeviceHandle, 1, &argv[1], NULL);
ioctl(DeviceHandle, 2, &argv[1], NULL);
/*Test release operation*/
close(DeviceHandle);
return 0;
}