Linux字符设备驱动Word下载.docx
《Linux字符设备驱动Word下载.docx》由会员分享,可在线阅读,更多相关《Linux字符设备驱动Word下载.docx(6页珍藏版)》请在冰点文库上搜索。
/*globalfifo设备结构体*/structglobalfifo_dev{structcdevcdev;
/*cdev结构体*/unsignedintcurrent_len;
/*fifo有效数据长度*/unsignedcharmem[GLOBALFIFO_SIZE];
/*全局内存*/structsemaphoresem;
/*并发控制用的信号量*/wait_queue_head_tr_wait;
/*阻塞读用的等待队列头*/wait_queue_head_tw_wait;
/*阻塞写用的等待队列头*/};
structglobalfifo_dev*globalfifo_devp;
/*设备结构体指针*//*文件打开函数*/intglobalfifo_open(structinode*inode,structfile*filp){/*将设备结构体指针赋值给文件私有数据指针*/filp->
private_data=globalfifo_devp;
return0;
}/*文件释放函数*/
intglobalfifo_release(structinode*inode,structfile*filp){return0;
}/*ioctl设备控制函数*/staticintglobalfifo_ioctl(structinode*inodep,structfile*filp,unsignedintcmd,unsignedlongarg){structglobalfifo_dev*dev=filp->
private_data;
/*获得设备结构体指针*/
switch(cmd){caseFIFO_CLEAR:
down(&
dev->
sem);
/*获得信号量*/dev->
current_len=0;
memset(dev->
mem,0,GLOBALFIFO_SIZE);
up(&
/*释放信号量*/
printk(KERN_INFO"
globalfifoissettozero\n"
);
break;
default:
return-EINVAL;
}return0;
}staticunsignedintglobalfifo_poll(structfile*filp,poll_table*wait){
unsignedintmask=0;
structglobalfifo_dev*dev=filp->
/*获得设备结构体指针*/down(&
poll_wait(filp,&
r_wait,wait);
/*把读等待队列添加到poll_table*/poll_wait(filp,&
w_wait,wait);
/*把写等待队列添加到poll_table*//*fifo非空表示可读*/if(dev->
current_len!
=0){mask|=POLLIN|POLLRDNORM;
/*标示数据可获得*/}/*fifo非满表示可写*/if(dev->
=GLOBALFIFO_SIZE){mask|=POLLOUT|POLLWRNORM;
/*标示数据可写入*/}
up(&
returnmask;
}/*globalfifo读函数*/staticssize_tglobalfifo_read(structfile*filp,char__user*buf,size_tcount,loff_t*ppos){intret;
DECLARE_WAITQUEUE(wait,current);
down(&
/*获得信号量*/add_wait_queue(&
r_wait,&
wait);
/*进入读等待队列头*//*等待FIFO非空*/if(dev->
current_len==0){if(filp->
f_flags&
O_NONBLOCK){
ret=-EAGAIN;
gotoout;
}__set_current_state(TASK_INTERRUPTIBLE);
/*改变进程状态为睡眠*/
up(&
schedule();
/*调度其他进程执行*/if(signal_pending(current)){/*如果是因为信号唤醒*/ret=-ERESTARTSYS;
gotoout2;
}down(&
}/*拷贝到用户空间*/if(count>
dev->
current_len)
count=dev->
current_len;
if(copy_to_user(buf,dev->
mem,count)){
ret=-EFAULT;
gotoout;
}else{memcpy(dev->
mem,dev->
mem+count,dev->
current_len-count);
/*fifo数据前移*/dev->
current_len-=count;
/*有效数据长度减少*/printk(KERN_INFO"
read%dbytes(s),current_len:
%d\n"
count,dev->
current_len);
wake_up_interruptible(&
w_wait);
/*唤醒写等待队列*/ret=count;
}out:
/*释放信号量*/out2:
remove_wait_queue(&
w_wait,&
/*从附属的等待队列头移除*/set_current_state(TASK_RUNNING);
returnret;
}/*globalfifo写操作*/staticssize_tglobalfifo_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*ppos){structglobalfifo_dev*dev=filp->
intret;
DECLARE_WAITQUEUE(wait,current);
down(&
add_wait_queue(&
/*等待FIFO非满*/if(dev->
current_len==GLOBALFIFO_SIZE){
if(filp->
O_NONBLOCK){ret=-EAGAIN;
gotoout;
}
__set_current_state(TASK_INTERRUPTIBLE);
/*改变进程状态为睡眠*/up(&
schedule();
/*调度其他进程执行*/if(signal_pending(current)){/*如果是因为信号唤醒*/ret=-ERESTARTSYS;
gotoout2;
}down(&
/*获得信号量*/}/*从用户空间拷贝到内核空间*/if(count>
GLOBALFIFO_SIZE-dev->
current_len)count=GLOBALFIFO_SIZE-dev->
if(copy_from_user(dev->
mem+dev->
current_len,buf,count)){ret=-EFAULT;
}else{dev->
current_len+=count;
written%dbytes(s),current_len:
r_wait);
/*唤醒读等待队列*/ret=count;
}
out:
remove_wait_queue(&
/*从附属的等待队列头移除*/set_current_state(TASK_RUNNING);
returnret;
}staticintmemdev_mmap(structfile*filp,structvm_area_struct*vma){structmem_dev*dev=filp->
/*获得设备结构体指针*/vma->
vm_flags|=VM_IO;
vma->
vm_flags|=VM_RESERVED
if(remap_pfn_range(vma,vma->
vm_start,virt_to_phys(dev->
data)>
>
PAGE_SHIFT,vma->
vm_end-vma->
vm_start,vma->
vm_page_prot))
return-EAGAIN;
/*文件操作结构体*/
staticconststructfile_operationsglobalfifo_fops={
.owner=THIS_MODULE,
.read=globalfifo_read,
.write=globalfifo_write,
.ioctl=globalfifo_ioctl,
.poll=globalfifo_poll,
.open=globalfifo_open,
.release=globalfifo_release,
.mmap=memdev_mmap,
};
/*初始化并注册cdev*/
staticvoidglobalfifo_setup_cdev(structglobalfifo_dev*dev,intindex){interr,devno=MKDEV(globalfifo_major,index);
cdev_init(&
cdev,&
globalfifo_fops);
cdev.owner=THIS_MODULE;
err=cdev_add(&
cdev,devno,1);
if(err)
printk(KERN_NOTICE"
Error%daddingLED%d"
err,index);
/*设备驱动模块加载函数*/
intglobalfifo_init(void)
{
structclass*myclass;
intret;
dev_tdevno=MKDEV(globalfifo_major,0);
/*申请设备号*/
if(globalfifo_major)
ret=register_chrdev_region(devno,1,"
globalfifo"
else{/*动态申请设备号*/
ret=alloc_chrdev_region(&
devno,0,1,"
globalfifo_major=MAJOR(devno);
}
if(ret<
0)
returnret;
/*动态申请设备结构体的内存*/
globalfifo_devp=kmalloc(sizeof(structglobalfifo_dev),GFP_KERNEL);
if(!
globalfifo_devp){
ret=-ENOMEM;
gotofail_malloc;
}memset(globalfifo_devp,0,sizeof(structglobalfifo_dev));
globalfifo_setup_cdev(globalfifo_devp,0);
/*自动创建设备文件*/
myclass=class_create(THIS_MODULE,"
test_char"
/*在sys下创建类目录/sys/class/test_char*/
device_create(myclass,NULL,MKDEV(globalfifo_major,0),NULL,"
memdev0"
init_MUTEX(&
globalfifo_devp->
/*初始化信号量*/init_waitqueue_head(&
/*初始化读等待队列头*/
init_waitqueue_head(&
/*初始化写等待队列头*/
fail_malloc:
unregister_chrdev_region(devno,1);
/*模块卸载函数*/
voidglobalfifo_exit(void)
cdev_del(&
cdev);
/*注销cdev*/
kfree(globalfifo_devp);
/*释放设备结构体内存*/
unregister_chrdev_region(MKDEV(globalfifo_major,0),1);
/*释放设备号*/
MODULE_AUTHOR("
SongBaohua"
MODULE_LICENSE("
DualBSD/GPL"
module_param(globalfifo_major,int,S_IRUGO);
module_init(globalfifo_init);
module_exit(globalfifo_exit);
五.
(1)驱动程序的Makefile:
obj-$(CONFIG_GLOBALFIFO)+=GLOBALFIFO.o
(2)驱动程序的Kconfig为:
configGLOBALFIFO
tristate"
zifushebeiqudong"
(3)进入控制界面如图:
(4)驱动模块的产生:
总结:
通过对字符设备驱动的操作,在实验过程中,遇到了很多困难,感觉有好多知识很生疏,学到的知识也不能很好的运用到实践中,在编写字符设备驱动程序时,比如在测试写阻塞,就会遇见写阻塞通过不了的问题,经过老师的讲解。
才知道对于内存分配不合理,在其他地方也会出现很多错误,但是,经过慢慢摸索,我也学到了很多知道,加强了这方面的一些不足,感觉自己在字符设备驱动方面有了很大提高。