Chinaunix首页 | 论坛 | 博客
  • 博客访问: 504807
  • 博文数量: 68
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 806
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-30 22:06
文章分类
文章存档

2011年(1)

2009年(8)

2008年(59)

我的朋友

分类: LINUX

2008-09-06 10:51:01

#include
#include /*for file-f_op*/
#include
#include /*for copy_to_user()*/
#include /*for cdev ,cdev_init,cdev_add....*/

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Helight");

#define DP_MAJOR 252 /*the major number of the chardev*/
#define DP_MINOR 0 /*the minor number of the chardev*/
static int char_read(struct file *filp,char __user *buffer,size_t,loff_t
*); /*the read operation of the chardev----read the data from kernel*/
static int char_open(struct inode *,struct file *); /*open the chardev*/
static int char_write(struct file *filp,const char __user *buffer,size_t
,loff_t*); /*write data to kernel*/
static int char_release(struct inode *,struct file *); /*release the
chardev*/
static char *arr,*p;
static int chropen; /*the chardev open or not*/
struct cdev *chardev; /*define a char device*/
static int len;

struct file_operations char_ops = {
.read = char_read,
.write = char_write,
.open = char_open,
.release = char_release,
};



static int __init char_init(void)
{
dev_t dev;
printk(KERN_ALERT"Initing......\n");
dev=MKDEV(DP_MAJOR,DP_MINOR);
chardev = cdev_alloc( );
if(chardev==NULL){
return -1;
}
if(register_chrdev_region(dev,10,"chardev")<0){
printk(KERN_ALERT"Register char dev error\n");
return -1;
}
chropen=0;
len=0;

cdev_init(chardev,&char_ops);
if(cdev_add(chardev,dev,1)<0)
{
printk(KERN_ALERT"Add char dev error\n");
}

return 0;
}

static int char_open(struct inode *inode,struct file *file)
{
if(chropen==0)
chropen++;
else{
printk(KERN_ALERT"Another process open the char device\n");
return -1;
}

try_module_get(THIS_MODULE);
return 0;
}



功能: 当一个进程试图关闭这个设备特殊文件的时候调用这个函数。
static int char_release(struct inode *inode,struct file *file)
{
chropen--;
module_put(THIS_MODULE);
return 0;
}

功能:当一个进程已经打开此设备文件以后并且试图去读它的时候调用这个函数。
static int char_read(struct file *filp,char __user *buffer,size_t
length,loff_t *offset)
{


if(copy_to_user(buffer,"hello world!",length))
{
return 0;
}

return 0;
}

static int char_write(struct file *filp,const char __user *buffer,size_t
length,loff_t *offset)
{

return 0;
}

功能:当试图将数据写入这个设备文件的时侯,这个函数被调用
static void __exit module_close(void)
{
len=0;
printk(KERN_ALERT"Unloading..........\n");
unregister_chrdev_region(MKDEV(DP_MAJOR,DP_MINOR),10);
cdev_del(chardev);
}

module_init(char_init);
module_exit(module_close);

用户程序
/*main.c*/
#include
#include
#include
#include
#include
#include
#include


int main(void)
{
int testdev;
int i;
char buf[15];

testdev = open("/dev/chardev0",O_RDWR);
if ( testdev == -1 )
{
printf("Cann't open file \n");
exit(0);
}
memset(buf, 0, sizeof(buf));
read(testdev,buf,12);

printf("%s\n",buf);
close(testdev);

return 0;
}

Makefile文件:

ifneq ($(KERNELRELEASE),)
obj-m := chardev.o
else
PWD  := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
    $(MAKE) -C $(KDIR) M=$(PWD)
endif


gcc -o main main.c

使用步骤:
1。make模块
2。insmod模块
3。mknod结点,具体命令如下:
mknod /dev/chardev0 c 250 0
命令解释:
mknod是建立节点的命令;
/dev/chardev0:在/dev/目录下建立chardev0这样一个节点,
c:这个节点是指向一个字符设备的节点
250:这个设备的主设备号;
0:次设备号
4。chmod 666 /dev/chardev0 使其他用户也可以对这个设备进行读写操作,否则
只有root用户可以对他进行读写
5。编译用户程序
6,运行用户程序./main
7.如果没有什么问题的话应该要输出
hello world!


以上是我摘录学长写的字符驱动程序,应该没问题,我改了下Makefile(2.6内核)。
这种程序其实不难, 我曾经也写了一些。
阅读(1930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~