第二个驱动程序(简易字符驱动程序
1、编写驱动程序
///char.c
# ifndef __KERNEL__
# define __KERNEL__
# endif
# ifndef MODULE
# define MODULE
# endif
# include <linux/mm.h>
#include <linux/module.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <asm/switch_to.h> //3.3 之后替换了 #include <asm/system.h>
#define DEVICE_NAME "demodrv"
#define demo_MAJOR 267
#define demo_MINOR 0
static int MAX_BUF_LEN = 1024;
static char drv_buf[1024];
static int WRI_LENGTH =0;
static ssize_t demo_write(struct file *,const char *,size_t,loff_t *);
static ssize_t demo_read(struct file *,char *,size_t,loff_t *);
static struct file_operations demo_fops=
{
owner:THIS_MODULE,
//open:demo_open
read:demo_read,
write:demo_write,
//llseek:demo_llseek(),
//ioctl:demo_ioctl,
//release:demo_release,
};
static void do_write(void)
{
int i;
int len = WRI_LENGTH;
char tmp;
for(i = 0;i<(len>>1);i++,len--)
{
tmp = drv_buf[len--];
drv_buf[len-1] = drv_buf[i];
drv_buf[i] = tmp;
}
}
static ssize_t demo_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
{
if(count>MAX_BUF_LEN)
count = MAX_BUF_LEN;
//copy_to_user(buffer,drv_buf,count);
printk("user read data from driver\n");
return (ssize_t)count;
}
static ssize_t demo_write(struct file *filp,const char *buffer,size_t count,loff_t *ppos)
{
if(count>MAX_BUF_LEN)
count = MAX_BUF_LEN;
WRI_LENGTH = count;
printk("user write data to driver\n");
do_write();
return (ssize_t)count;
}
static int __init demo_init(void)
{
int result;
result = register_chrdev(demo_MAJOR,"char",&demo_fops);
if(result<0)
{
printk(DEVICE_NAME"initialized failure\n");
return result;
}
else
{
printk(DEVICE_NAME"initialized!\n");
return 0;
}
}
static void __exit demo_exit(void)
{
//unregister_chrdev(demo_MAJOR,"demodrv");
kfree(demo_devices);
printk(DEVICE_NAME"unloaded\n");
}
2、编写Makefile
ifneq ($(KERNELRELEASE),)
#MODULE_NAME= demodrv
#$(MODULE_NAME)-objs:= char.o
obj-m:= char.o
else
KERNEL_DIR = /lib/modules/$(shell uname -r)/build
MODULEDIR:= $(shell pwd)
.PHONY: modules
default: modules
modules:
make -C $(KERNEL_DIR) M=$(MODULEDIR) modules
clean distclean:
rm -f *.o *.mod.c .*.*.cmd * .ko.Mod*.* mo*.*
rm-f .tmp_versions
endif
3、测设驱动模块的应用程序
//test_demo.c
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/ioctl.h>
void showbuf(char *buf);
int MAX_LEN = 32;
int main()
{
int fd;
int i;
char buf[255];
for(i=0;i<MAX_LEN;i++)
{
buf[i]=i;
}
fd = open("/dev/chardrv",O_RDWR);
if(fd<0)
{
printf("# # # DEMO device open fail####\n");
return (-1);
}
printf("write %d bytes date to /dev/demo\n",MAX_LEN);
showbuf(buf);
write(fd,buf,MAX_LEN);
printf("Read %d bytes date from /dev/demo \n",MAX_LEN);
read(fd,buf,MAX_LEN);
showbuf(buf);
ioctl(fd,1,NULL);
ioctl(fd,4,NULL);
close(fd);
return 0;
}
void showbuf(char * buf)
{
int i,j=0;
for(i=0;i<MAX_LEN;i++)
{
if(i%4==0)
{
printf("\n%4d:",j++);
printf("%4d",buf[i]);
}
printf("\n#############################\n");
}
}
4、使用make编译驱动和测试文件&&生成.ko和test_demo可执行文件
成功生成.ko。
nice!!!
--------------------------------------------------------------------------
5、创建设备节点使用mknod命令
mknod /dev/chardrv c 277 0
- cat /proc/devices 命令。查看主设备号,看是否已经存在自己想创建的设备号(demo_MAJOR)。
- 删除节点 rm -f /dev/chardrv
6、插入驱动模块 insmod char.ko
lsmod
查看
7、测试 ./test_demo
8、问题
碰到一个解决一个,这个过程才是收获最大的。老师说,这可比你做题有益多的多。
continuing