//这是一个最简单的字符设备驱动,入门专用.//scull1.h#ifndef _SCULL1_H#define_SCULL1_H#include#include#include#include#include#include#include#include#include#include#defineSCULL_MAJOR 0#defineSCULL_SIZE 0x1000#defineSCULL_CMD_CLEAR 0x01structscull_dev{structcdev cDev;charmem[SCULL_SIZE];
};intscull_open(structinode*inode,structfile*filp);
ssize_t scull_read(structfile*filp,char__user*buf, size_t count,loff_t*f_pos);
ssize_t scull_write(structfile*filp,constchar__user*buf, size_t count,loff_t*f_pos);intscull_release(structinode*inode,structfile*filp);#endif//scull1.c#include"scull1.h"MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Aaron.xu");
MODULE_DESCRIPTION("hello driver test");
MODULE_VERSION("0.1");staticintscull_major=SCULL_MAJOR;structscull_dev mydev;structfile_operations scull_fops={
.owner=THIS_MODULE,
.open=scull_open,
.release=scull_release,
.read=scull_read,
.write=scull_write,
};staticvoidscull_setup_cdev(void)
{interr;
dev_t devid=MKDEV(scull_major,0);
cdev_init(&mydev.cDev,&scull_fops);
printk(KERN_INFO"&mydev.cDev.ops:%p \n",&mydev.cDev.ops);
mydev.cDev.owner=THIS_MODULE;
mydev.cDev.ops=&scull_fops;
printk(KERN_INFO"&mydev.cDev.ops:%p \n",&mydev.cDev.ops);
err=cdev_add(&mydev.cDev,devid,1);if(err!=0)
{
printk(KERN_ERR"cdev_add Error,err:%d \n",err);
}
}staticintscull_init(void)
{interr;
dev_t devid=MKDEV(scull_major,0);if(scull_major)
{
err=register_chrdev_region(devid,1,"scull1");
}else{
err=alloc_chrdev_region(&devid,0,1,"scull1");
scull_major=MAJOR(devid);
}if(err!=0)
{
printk(KERN_ERR"register chrdev region error,err:%d \n",err);returnerr;
}
scull_setup_cdev();return0;
}staticvoidscull_exit(void)
{
cdev_del(&mydev.cDev);
unregister_chrdev_region(MKDEV(scull_major,0),1);
}intscull_open(structinode*inode,structfile*filp)
{
filp->private_data=&mydev;return0;
}
ssize_t scull_read(structfile*filp,char__user*buf, size_t count,loff_t*f_pos)
{
unsignedlongpos=*f_pos;interr=0;intret=0;structscull_dev*p_mydev=filp->private_data;if(pos>=SCULL_SIZE)
{return0;
}if(count>(SCULL_SIZE-pos) )
{
count=SCULL_SIZE-pos;
}
err=copy_to_user(buf,p_mydev->mem+pos,count);if(err!=0)
{
ret=-EFAULT;
}else{*f_pos+=count;
ret=count;
printk(KERN_INFO"read %d byte(s) from %lu \n",ret,pos);
}returnret;
}
ssize_t scull_write(structfile*filp,constchar__user*buf, size_t count,loff_t*f_pos)
{
unsignedlongpos=*f_pos;interr=0;intret=0;structscull_dev*p_mydev=filp->private_data;if(pos>=SCULL_SIZE)
{return0;
}if(count>(SCULL_SIZE-pos) )
{
count=SCULL_SIZE-pos;
}
err=copy_from_user(p_mydev->mem+pos,buf,count);if(err!=0)
{
ret=-EFAULT;
}else{*f_pos+=count;
ret=count;
printk(KERN_INFO"write %d byte(s) from %lu \n",ret,pos);
}returnret;
}intscull_release(structinode*inode,structfile*filp)
{return0;
}
module_init(scull_init);
module_exit(scull_exit);//Makefileobj-m+=scull1.o
KERNELDIR :=/usr/src/linux-headers-2.6.32-5-686PWD :=$(shell pwd)
.PHONY: test clean all
all:
$(MAKE)-C $(KERNELDIR) M=$(PWD) modules
clean:
rm-rf*.o*~core .depend .*.cmd*.ko*.mod.c .tmp_versionsm*.order*.symvers .tmp_versions
test:
insmod ./scull1.ko
rmmod scull1
dmesg-c//创建设备节点make_dev_node
#!/bin/bash
DEVICE="scull1"MAJOR=`awk"\\$2==\"$DEVICE\"{print \\$1}"/proc/devices`
cmd="mknod /dev/$DEVICE c $MAJOR 0"echo $cmd
`$cmd`