《TQ2440的简单内存数据读写驱动程序》

Linux下的设备驱动程序被组织为一组完成不同任务的函数的集合,通过这些函数使得设备操作犹如文件一般。在应用程序看来,硬件设备只 是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作,如open ()、close ()、read ()、write () 等

该程序主要是在TQ2440开发板上完成对一段内存的读写,驱动程序中实现了简单的read、write、open、release等功能。

以下是fs.c的驱动程序代码

该程序主要是在TQ2440开发板上完成对一段内存的读写,驱动程序代码如下

#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/kernel.h>
#include<linux/device.h>
#include<asm/uaccess.h>
#include<linux/errno.h>
#include"../fs/ntfs/malloc.h"  //该头文件为kfree和malloc函数所在位置
#define DEVICE_NAME "FS"   //定义设备名称
unsigned int fs_major=0;
static char *data;

static int test_open(struct inode *inode,struct file *file)
{
//	MOD_INC_USE_COUNT;
	printk("this is open\n");
	return 0;
}

static int test_release(struct inode *inode,struct file *file)
{
//	MOD_DEC_USE_COUNT;
	printk("this is released\n");
	return 0;
}

static ssize_t test_read(struct file *file,char *buf,size_t count,loff_t *f_pos)
{
	int len;
	if(count<0)
	{
		return -EINVAL;
	}
	len=strlen(data);
	if(len<count)
	{
		count=len;
	}
	copy_to_user(buf,data,count+1);
	return count;
}
//loff_t *f_pos 为当前的文件指针位置,即文件的读写位置
static ssize_t test_write(struct file *file,const char *buffer,size_t count,loff_t *f_pos)
{
	if(count<0)
	{
		return -EINVAL;
	}
	kfree(data);
	data=(char*)kmalloc(sizeof(char)*(count+1),GFP_KERNEL);
	if(!data)
	{
		return -ENOMEM;
	}
	copy_from_user(data,buffer,count+1);
	return count;
}

static struct file_operations chr_fops={ //基本函数入口点的结构体
	.owner=THIS_MODULE,
	.read=test_read,
	.write=test_write,
	.open=test_open,
	.release=test_release,
};

static struct class *fs_class;//创建一个
static int __init test_init(void)
{
	int res;
	printk("this is skull device\n");
	res=register_chrdev(fs_major,DEVICE_NAME,&chr_fops); //其中fs_major为主设备号,chr_fops  为基本函数入口
	if(res<0)
	{
		printk("can't get major name!\n");
		return res;
	}
	if(fs_major == 0)//如果主设备号初始化是0,则为其自动分配主设备号。
	{
		fs_major=res;
	}
	fs_class=class_create(THIS_MODULE,DEVICE_NAME);           //THIS_MODULE,它的定义如下是#define THIS_MODULE (&__this_module),
	device_create(fs_class,NULL,MKDEV(fs_major,0),NULL,DEVICE_NAME);             //__this_module是一个struct module变量,代表当前模块
	printk("initialized\n");	
	return 0;
}

static void __exit test_exit(void)
{
	unregister_chrdev(fs_major,DEVICE_NAME);
	device_destroy(fs_class,MKDEV(fs_major,0));//删除节点设备;MKDEV(fs_major,0)为通过主从设备号得到dev_t 
	class_destroy(fs_class);//注销类
	printk("it's over now\n");
}

module_init(test_init);//调用rmmod fs.ko 卸载时会调用该接口
module_exit(test_exit);//调用insmod fs.ko 进行驱动模块加载时会调用该接口

//以下信息不是必需的
MODULE_AUTHOR("czn911");//作者信息
MODULE_DESCRIPTION("TQ2440 SKULL");//相关描述
MODULE_LICENSE("GPL");//遵守的协议

THIS_MODULE,它的定义如下是#define THIS_MODULE (&__this_module),__this_module是一个struct module变量,代表当前模块

错误列举:
error: implicit declaration of function 'class_device_create'
error: implicit declaration of function 'class_device_destroy'
原因:
class_device_create 和 class_device_destroy 是最期版本的API
现在已经改成device_create 和 device_destroy表当前模块,


编译错误:error: expected '=', ',', ';', 'asm' or '__attribute__' before...        error: expected declaration specifiers or '...' before xxx

原因:有可能是你头文件的包含的顺序需要调换一下,具体参考:http://blog.csdn.net/xuyunzhang/article/details/6286873


Makefile程序

KERNELDIR=/opt/EmbedSky/linux-2.6.30.4/
PWD:=$(shell pwd)
INSTALLDIR=$(PWD)
CC=arm-linux-gcc
obj-m:=fs.o
modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	rm -rf *.o *.ko *.mod.c *.markers *.order *.symvers
.PHONY:modules clean


testing.c测试程序

#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<linux/ioctl.h>
int main()
{
	int fd,i,nwrite,nread;
	char *buf="hello\n";
	char read_buf[6]={0};
	fd=open("/dev/FS",O_RDWR);
	if(fd<0)
	{
		perror("open");
		exit(1);
	}
	else
	{
		printf("open success\n");
	}
	nwrite=write(fd,buf,strlen(buf));
	printf("the num write_to_kernel is: %d\n",nwrite);
	if(nwrite<0)
	{
		perror("write");
		exit(1);
	}
	nread=read(fd,read_buf,6);
	printf("the num read_from_kernel is: %d\n",nread);
	if(nread<0)
	{
		perror("read");
		exit(1);
	}
	else
	{
		printf("read is %s\n",read_buf);
	}
	close(fd);
	exit(0);
}

make后将会由fs.c 生成fs.ko文件

在用过arm-linux-gcc testint.c -o testing 生成testing可执行文件,注意这里要将testing的权限修改成777

然后通过tftp或者其他方式正这两个文件传输至开发板上

在执行insmod fs.ko 后,将会在/dev/ 目录下看到 设备文件FS ,这说明设备驱动已经加载好了,并且分配了设备号

执行./testing 就可以看到内存读写结果啦。


以上是我作为一个菜鸟对我目前所学习的一些理解,欢迎大家指正。


以下是我参考的一些资料链接,感谢他们的无私分享

http://blog.163.com/njut_wangjian/blog/static/16579642520121022112940349/

http://blog.csdn.net/xuyunzhang/article/details/6286873

http://blog.csdn.net/wzws45/article/details/5948308

http://www.embedu.org/Column/Column476.htm




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值