高级字符驱动llseek以及ioctl函数Word文档下载推荐.docx
- 文档编号:5791470
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:23
- 大小:24.54KB
高级字符驱动llseek以及ioctl函数Word文档下载推荐.docx
《高级字符驱动llseek以及ioctl函数Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《高级字符驱动llseek以及ioctl函数Word文档下载推荐.docx(23页珍藏版)》请在冰点文库上搜索。
#include"
scull01.h"
#defineSCULL2_SIZE0x1000/*定义全局内存最大4K字节*/#defineMEM_CLEAR0X1/*清0全局内存*/
#defineSCULL2_MAJOR0/*定义为动态分配主设备号*/
staticintscull2_major=SCULL2_MAJOR;
intscull2_minor=0;
intscull2_nr_devs=SCULL_NR_DEVS;
//设备数量intscull2_quantum=SCULL_QUANTUM;
intscull2_qset=SCULL_QSET;
/*scull2结构体定义*/structscull2_qset{void**data;
structscull2_qset*next;
};
structscull2_dev{structscull2_qset*data;
/*指向quantumset*/intquantum;
/*当前quantum大小*/intqset;
/*当前结构中数组大小*/unsignedlongsize;
/*存储数据量大小*/unsignedintaccess_key;
/*被sculluid和scullpriv调用*/structsemaphoresem;
/*信号量声明*/structcdevcdev;
/*字符设备结构体*/};
/*
structsemaphore{
spinlock_tlock;
//自旋锁类型
unsignedintcount;
//信号量计数
structlist_headwait_list;
//双向链表结构等待队列,即当需要等待信号量时,调用进程把自己加入到等待队列中,然后进入睡眠状态.
};
*/
structscull2_dev*scull2_devices;
//设备结构体指针
//清空scull2设备内容;
必须调用与信号设备。
intscull2_trim(structscull2_dev*dev){
structscull2_qset*next,*dptr;
//声明两个指针指向下一个和前一个字符设备结构
intqset=dev->
qset;
//dev不为null
inti;
//采用循环结构清空结构体中原有数据内容
for(dptr=dev->
data;
dptr;
dptr=next){
if(dptr->
data){
for(i=0;
i<
qset;
i++)
kfree(dptr->
data[i]);
//依次对结构体中每个段清空
data);
//最后清除设备信息
dptr->
data=NULL;
}
next=dptr->
next;
//指向设备中下一个字符设备
kfree(dptr);
//释放当前设备
}
//运用默认数据,初始化结构体中内容
dev->
size=0;
quantum=scull2_quantum;
qset=scull2_qset;
return0;
#ifdefSCULL_DEBUG//提供调试用的相关接口,仅需要在进行调试时被执行内容相关函数
//对于/proc文件系统,该函数的功能是读取入口,提供相关调试信息
intscull2_read_procmem(char*buf,char**start,off_toffset,intcount,int*eof,void*data){
inti,j,len=0;
intlimit=count-80;
//设备打印长度不超过80
//scull2_nr_devs为设备数量
for(i=0;
i<
scull2_nr_devs&
&
len<
=limit;
i++){
structscull2_dev*d=&
scull2_devices[i];
structscull2_qset*qs=d->
if(down_interruptible(&
d->
sem))
return-ERESTARTSYS;
len+=sprintf(buf+len,"
\nDevice%i:
qset%i,q%i,sz%li\n"
i,d->
qset,d->
quantum,d->
size);
for(;
qs&
len<
=limit;
qs=qs->
next){
len+=sprintf(buf+len,"
itemat%p,qsetat%p\n"
qs,qs->
if(qs->
data&
!
qs->
next)
for(j=0;
j<
j++){
data[j])
%4i:
%8p\n"
j,qs->
data[j];
up(&
scull2_devices[i].sem);
*eof=1;
returnlen;
//通过以上函数,实现了文件队列(seq_file)的同时存在,而以前的read_procmem函数也同样可以执行
//下面是进行顺序迭代,根据设备的设备号进行简单的迭代
staticvoid*scull2_seq_start(structseq_file*s,loff_t*pos){
if(*pos>
=scull2_nr_devs)
returnNULL;
//如果偏移位大于设备总数,返回空。
returnscull2_devices+*pos;
staticvoid*scull2_seq_next(structseq_file*s,void*v,loff_t*pos){
(*pos)++;
returnscull2_devices+*pos;
staticvoidscull2_seq_stop(structseq_file*s,void*v){//什么事也不用做}
//显示结构中相关信息。
staticintscull2_seq_show(structseq_file*s,void*v){structscull2_dev*dev=(structscull2_dev*)v;
structscull2_qset*d;
inti;
if(down_interruptible(&
sem))
return-ERESTRATSYS;
seq_printf(s,"
\nDevice%i:
qest%i,q%i,sz%li\n"
(int)(dev-scull2_devices),dev->
qset,dev->
quantum,dev->
for(d=dev->
d;
d=d->
next){
d,d->
if(d->
next)
for(i=0;
i++){
data[i])
i,d->
}}up(&
sem);
return0;
//构建队列执行对应的结构体
staticstructseq_operationsscull2_seq_ops={
.start=scull2_seq_start,.next=sucll2_seq_next,.stop=scull2_seq_stop,.show=scull2_seq_show,};
//现在可以执行在/proc文件,我们只需要open,建立执行队列
staticintscull2_proc_open(structinode*inode,structfile*file){
returnseq_open(file,&
scull2_seq_ops);
//为/proc建立相关文件结构
staticstructfile_operationssucll_proc_ops={
.owner=THIS_MODULE,
.open=scull2_proc_open,
.read=seq_read,
.llseek=seq_lseek,
.release=seq_release,
//建立/proc执行的create及remove对应函数
staticvoidscull2_create_proc(void){
structproc_dir_entry*entry;
//create_proc_read_entry(名字,defaultmode,parentdir,调用函数,clientdata)
create_proc_read_entry("
scullmem"
0,NULL,scull2_read_procmem,NULL);
entry=create_proc_entry("
scullseq"
0,NULL);
if(entry)
entry->
proc_fops=&
scull2_proc_ops;
staticvoidscull2_remove_proc(void){
/*noproblemifitwasnotregistered*/
remove_proc_entry("
NULL/*parentdir*/);
NULL);
#endif//SCULL_DEBUG结束
//文件打开函数
intscull2_open(structinode*inode,structfile*filp){
structscull2_dev*dev;
//设备相关信息
dev=container_of(inode->
i_cdev,structscull2_dev,cdev);
//为其它方法forothermethods
filp->
private_data=dev;
//修改设备打开时为只写nowtrimto0thelengthofthedeviceifopenwaswrite-only
if(((filp->
f_flags&
O_ACCMODE)&
O_WRONLY)){
scull2_trim(dev);
//忽略errors
//文件释放函数
intscull2_release(structinode*inode,structfile*filp){
//顺序链表Followthelist
structscull2_qset*scull2_follow(structscull2_dev*dev,intn){
structscull2_qset*qs=dev->
//在首次调用或需要,为qset分配空间.Allocatefirstqsetexplicitlyifneedbe
if(!
qs){
qs=dev->
data=kmalloc(sizeof(structscull2_qset),GFP_KERNEL);
if(qs==NULL)
memset(qs,0,sizeof(structscull2_qset));
//顺序链表Thenfollowthelist
while(n--){
if(!
qs->
next=kmalloc(sizeof(structscull2_qset),GFP_KERNEL);
next==NULL)
memset(qs->
next,0,sizeof(structscull2_qset));
continue;
returnqs;
//ioctl设备控制函数
staticintscull2_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg){
interr=0,tmp;
intretval=0;
//从传递的cmd中提取出type和nr并作判断,但不执行解码
//如果不是定义的格式,则返回-ENOTTY
if(_IOC_TYPE(cmd)!
=SCULL_IOC_MAGIC)
return-ENOTTY;
if(_IOC_NR(cmd)>
SCULL_IOC_MAXNR)
//
if(_IOC_DIR(cmd)&
_IOC_READ)
err=!
access_ok(VERIFY_WRITE,(void__user*)arg,_IOC_SIZE(cmd));
elseif(_IOC_DIR(cmd)&
_IOC_WRITE)
access_ok(VERIFY_READ,(void__user*)arg,_IOC_SIZE(cmd));
if(err)
return-EFAULT;
switch(cmd){
caseSCULL_IOCRESET:
//设置为初始值
scull2_quantum=SCULL_QUANTUM;
scull2_qset=SCULL_QSET;
break;
caseSCULL_IOCSQUANTUM:
//传递arg值至scull2_quantum
capable(CAP_SYS_ADMIN))
return-EPERM;
retval=__get_user(scull2_quantum,(int__user*)arg);
caseSCULL_IOCTQUANTUM:
/*Tell:
argisthevalue*/
scull2_quantum=arg;
caseSCULL_IOCGQUANTUM:
//返回当前值Get:
argispointertoresult
retval=__put_user(scull2_quantum,(int__user*)arg);
caseSCULL_IOCQQUANTUM:
//返回positive
returnscull2_quantum;
caseSCULL_IOCXQUANTUM:
//交换,将传递的arg作为指针
tmp=scull2_quantum;
if(retval==0)
retval=__put_user(tmp,(int__user*)arg);
caseSCULL_IOCHQUANTUM:
/*shift:
likeTell+Query*/
returntmp;
caseSCULL_IOCSQSET:
retval=__get_user(scull2_qset,(int__user*)arg);
caseSCULL_IOCTQSET:
scull2_qset=arg;
caseSCULL_IOCGQSET:
retval=__put_user(scull2_qset,(int__user*)arg);
caseSCULL_IOCQQSET:
returnscull2_qset;
caseSCULL_IOCXQSET:
tmp=scull2_qset;
retval=put_user(tmp,(int__user*)arg);
caseSCULL_IOCHQSET:
/*
*Thefollowingtwochangethebuffersizeforscullpipe.
*Thescullpipedeviceusesthissameioctlmethod,justto
*writelesscode.Actually,it'
sthesamedriver,isn'
tit?
*/
#if0
caseSCULL_P_IOCTSIZE:
scull2_p_buffer=arg;
caseSCULL_P_IOCQSIZE:
returnscull2_p_buffer;
#endif
default:
}returnretval;
//seek文件定位函数
staticloff_tscull2_llseek(structfile*filp,loff_toff,intwhence){structscull2_dev*dev=filp->
private_data;
loff_tnewpos;
switch(whence){
case0:
//SEEK_SET
newpos=off;
case1:
//SEEK_CUR
ne
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 高级 字符 驱动 llseek 以及 ioctl 函数
![提示](https://static.bingdoc.com/images/bang_tan.gif)