Linux字符设备驱动.docx

上传人:b****5 文档编号:11703729 上传时间:2023-03-30 格式:DOCX 页数:6 大小:240.55KB
下载 相关 举报
Linux字符设备驱动.docx_第1页
第1页 / 共6页
Linux字符设备驱动.docx_第2页
第2页 / 共6页
Linux字符设备驱动.docx_第3页
第3页 / 共6页
Linux字符设备驱动.docx_第4页
第4页 / 共6页
Linux字符设备驱动.docx_第5页
第5页 / 共6页
点击查看更多>>
下载资源
资源描述

Linux字符设备驱动.docx

《Linux字符设备驱动.docx》由会员分享,可在线阅读,更多相关《Linux字符设备驱动.docx(6页珍藏版)》请在冰豆网上搜索。

Linux字符设备驱动.docx

Linux字符设备驱动

实验二:

Linux字符设备驱动

一.字符设备驱动实现的方法包括Write,Read,Poll,Icotl,Mmap,Llseek等。

二.字符设备驱动的主要内容:

并发控制,阻塞与非阻塞,异步通知。

三.字符设备驱动的主要文件:

globalfifo.cMakefileglobalfifo_test,globalfifo.c。

四.驱动程序如下:

#include

#include#include#include

#include

#include

#include

#include

#include#include#include

#include#include/*device_create()*/

#defineGLOBALFIFO_SIZE24/*全局fifo最大4K字节*/

#defineFIFO_CLEAR0x1/*清0全局内存的长度*/

#defineGLOBALFIFO_MAJOR249/*预设的globalfifo的主设备号*/staticintglobalfifo_major=GLOBALFIFO_MAJOR;/*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(&dev->sem);/*释放信号量*/

printk(KERN_INFO"globalfifoissettozero\n");

break;default:

return-EINVAL;}return0;}staticunsignedintglobalfifo_poll(structfile*filp,poll_table*wait){

unsignedintmask=0;

structglobalfifo_dev*dev=filp->private_data;/*获得设备结构体指针*/down(&dev->sem);poll_wait(filp,&dev->r_wait,wait);/*把读等待队列添加到poll_table*/poll_wait(filp,&dev->w_wait,wait);/*把写等待队列添加到poll_table*//*fifo非空表示可读*/if(dev->current_len!

=0){mask|=POLLIN|POLLRDNORM;/*标示数据可获得*/}/*fifo非满表示可写*/if(dev->current_len!

=GLOBALFIFO_SIZE){mask|=POLLOUT|POLLWRNORM;/*标示数据可写入*/}

up(&dev->sem);returnmask;}/*globalfifo读函数*/staticssize_tglobalfifo_read(structfile*filp,char__user*buf,size_tcount,loff_t*ppos){intret;

structglobalfifo_dev*dev=filp->private_data;DECLARE_WAITQUEUE(wait,current);down(&dev->sem);/*获得信号量*/add_wait_queue(&dev->r_wait,&wait);/*进入读等待队列头*//*等待FIFO非空*/if(dev->current_len==0){if(filp->f_flags&O_NONBLOCK){

ret=-EAGAIN;

gotoout;}__set_current_state(TASK_INTERRUPTIBLE);/*改变进程状态为睡眠*/

up(&dev->sem);schedule();/*调度其他进程执行*/if(signal_pending(current)){/*如果是因为信号唤醒*/ret=-ERESTARTSYS;gotoout2;}down(&dev->sem);}/*拷贝到用户空间*/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(&dev->w_wait);/*唤醒写等待队列*/ret=count;}out:

up(&dev->sem);/*释放信号量*/out2:

remove_wait_queue(&dev->w_wait,&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->private_data;

intret;DECLARE_WAITQUEUE(wait,current);

down(&dev->sem);add_wait_queue(&dev->w_wait,&wait);/*等待FIFO非满*/if(dev->current_len==GLOBALFIFO_SIZE){

if(filp->f_flags&O_NONBLOCK){ret=-EAGAIN;

gotoout;

}

__set_current_state(TASK_INTERRUPTIBLE);/*改变进程状态为睡眠*/up(&dev->sem);schedule();/*调度其他进程执行*/if(signal_pending(current)){/*如果是因为信号唤醒*/ret=-ERESTARTSYS;gotoout2;}down(&dev->sem);/*获得信号量*/}/*从用户空间拷贝到内核空间*/if(count>GLOBALFIFO_SIZE-dev->current_len)count=GLOBALFIFO_SIZE-dev->current_len;

if(copy_from_user(dev->mem+dev->current_len,buf,count)){ret=-EFAULT;gotoout;}else{dev->current_len+=count;printk(KERN_INFO"written%dbytes(s),current_len:

%d\n",count,dev->current_len);wake_up_interruptible(&dev->r_wait);/*唤醒读等待队列*/ret=count;}

out:

up(&dev->sem);/*释放信号量*/out2:

remove_wait_queue(&dev->w_wait,&wait);/*从附属的等待队列头移除*/set_current_state(TASK_RUNNING);returnret;}staticintmemdev_mmap(structfile*filp,structvm_area_struct*vma){structmem_dev*dev=filp->private_data;/*获得设备结构体指针*/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;

return0;

}

/*文件操作结构体*/

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(&dev->cdev,&globalfifo_fops);

dev->cdev.owner=THIS_MODULE;

err=cdev_add(&dev->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");

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->sem);/*初始化信号量*/init_waitqueue_head(&globalfifo_devp->r_wait);/*初始化读等待队列头*/

init_waitqueue_head(&globalfifo_devp->w_wait);/*初始化写等待队列头*/

return0;

fail_malloc:

unregister_chrdev_region(devno,1);

returnret;

}

/*模块卸载函数*/

voidglobalfifo_exit(void)

{

cdev_del(&globalfifo_devp->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)驱动模块的产生:

 

总结:

通过对字符设备驱动的操作,在实验过程中,遇到了很多困难,感觉有好多知识很生疏,学到的知识也不能很好的运用到实践中,在编写字符设备驱动程序时,比如在测试写阻塞,就会遇见写阻塞通过不了的问题,经过老师的讲解。

才知道对于内存分配不合理,在其他地方也会出现很多错误,但是,经过慢慢摸索,我也学到了很多知道,加强了这方面的一些不足,感觉自己在字符设备驱动方面有了很大提高。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1