scull源码分析 未完待续囧.docx
《scull源码分析 未完待续囧.docx》由会员分享,可在线阅读,更多相关《scull源码分析 未完待续囧.docx(25页珍藏版)》请在冰豆网上搜索。
scull源码分析未完待续囧
scull源码分析未完待续,囧
scull源码分析//未完待续,囧
Makefile
#disable/enabledebugging
#DEBUG=y#当DEBUG变量等于y时。
两个比较变量用括号括起来,逗号分隔。
ifeq和括号中间有一个空格。
ifeq($(DEBUG),y)
#+=追加变量值。
如果该变量之前没有被定义过,+=就自动变成=,变量被定义成递归展开式的变量;如果之前已经定义过,就遵循之前的风格。
#=递归展开式变量:
在定义时,变量中对其它变量的引用不会被替换展开。
变量在引用它的地方被替换展开时,变量中其它变量才被同时替换展开。
#-O程序优化参数;
#-g使生成的debuginfo包额外支持gnu和gdb调试程序,易于使用
#-DSCULL_DEBUG即defineSCULL_DEBUGTODO
DEBFLAGS+=-O-g-DSCULL_DEBUG#-Oisneededtoexpandinlines
else
DEBFLAGS+=-O2
endif#CFLAGS影响编译过程。
应在遵循原设置的基础上添加新的设置,注意+=
CFLAGS+=$(DEBFLAGS)
#-I选项指出头文件位置。
LDDINC是下面定义的一个变量。
CFLAGS+=-I$(LDDINC)#如果KERNELRELEASE不等于空。
ifneq判断参数是否不相等。
ifneq($(KERNELRELEASE),)
#:
=直接展开式变量:
在定义时就展开变量中对其它变量或函数的引用,定以后就成了需要定义的文本串。
不能实现对其后定义变量的引用。
scull-objs:
=main.opipe.oaccess.o
obj-m:
=scull.o
#否则(KERNELRELEASE是空)
else
#?
=条件赋值:
只有在此变量之前没有赋值的情况下才会被赋值。
#shellunamer内核版本号
KERNELDIR?
=/lib/modules/$(shellunamer)/build
#shellpwd当前在文件系统中的路径
PWD:
=$(shellpwd)
modules:
#$(MAKE)TODO
#-C$(KERNELDIR)在读取Makefile之前进入$(KERNELDIR)目录
#M=$(PWD)LDDINC=$(PWD)/../include传递2个变量给Makefile
#modules是$(KERNELDIR)中的Makefile的targetTODO
$(MAKE)-C$(KERNELDIR)M=$(PWD)LDDINC=$(PWD)/../includemodulesendif#清理
clean:
rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versions#TODO
#产生依赖信息文件,如果存在的话则将其包含到Makefile中。
depend.dependdep:
$(CC)$(CFLAGS)-M*.c>.depend
ifeq(.depend,$(wildcard.depend))
include.depend
endif---
参考
1.[GNUmake中文手册]
2.[CFLAGS统一和gcc3.4]http:
//www.magiclinux.org/node/821
3.[LDD3源码学习笔记之scull_main]
4.
scull.h
/*
*scull.h--definitionsforthecharmodule
*
*Copyright(C)2001AlessandroRubiniandJonathanCorbet
*Copyright(C)2001O'Reilly&Associates
*
*Thesourcecodeinthisfilecanbefreelyused,adapted,
*andredistributedinsourceorbinaryform,solongasan
*acknowledgmentappearsinderivedsourcefiles.Thecitation
*shouldlistthatthecodecomesfromthebook"LinuxDevice
*Drivers"byAlessandroRubiniandJonathanCorbet,published
*byO'Reilly&Associates.Nowarrantyisattached;
*wecannottakeresponsibilityforerrorsorfitnessforuse.
*
*$Id:
scull.h,v1.152004/11/0417:
51:
18rubiniExp$
*/#ifndef_SCULL_H_
#define_SCULL_H_#include<linux/ioctl.h>/*neededforthe_IOWetcstuffusedlater*//*
*Macrostohelpdebugging
*///undef取消以前定义的宏
#undefPDEBUG/*undefit,justincase*/
#ifdefSCULL_DEBUG
#ifdef__KERNEL__
//内核空间,printk输出调试信息
/*Thisoneifdebuggingison,andkernelspace*/
#definePDEBUG(fmt,args)printk(KERN_DEBUG"scull:
"fmt,##args)
#else
//用户空间,fprintf输出调试信息
/*Thisoneforuserspace*/
#definePDEBUG(fmt,args)fprintf(stderr,fmt,##args)
#endif
#else
#definePDEBUG(fmt,args)/*notdebugging:
nothing*/
#endif#undefPDEBUGG
#definePDEBUGG(fmt,args)/*nothing:
it'saplaceholder*/#ifndefSCULL_MAJOR
//主设备号指定为0,表示由内核动态分配
#defineSCULL_MAJOR0/*dynamicmajorbydefault*/
#endif//baredevice的数量,也就是要请求的连续设备编号的总数
#ifndefSCULL_NR_DEVS
#defineSCULL_NR_DEVS4/*scull0throughscull3*/
#endif//TODO
#ifndefSCULL_P_NR_DEVS
#defineSCULL_P_NR_DEVS4/*scullpipe0throughscullpipe3*/
#endif/*
*Thebaredeviceisavariable-lengthregionofmemory.
*Usealinkedlistofindirectblocks.
*
*"scull_dev->data"pointstoanarrayofpointers,each
*pointerreferstoamemoryareaofSCULL_QUANTUMbytes.
*
*Thearray(quantum-set)isSCULL_QSETlong.
*/
//每个内存区字节数。
(量子长度)
#ifndefSCULL_QUANTUM
#defineSCULL_QUANTUM4000
#endif//数组长度(量子集长度)
#ifndefSCULL_QSET
#defineSCULL_QSET1000
#endif/*
*Thepipedeviceisasimplecircularbuffer.Hereitsdefaultsize
*/
//管道设备,环形缓冲大小。
#ifndefSCULL_P_BUFFER
#defineSCULL_P_BUFFER4000
#endif/*
*Representationofscullquantumsets.
*/
structscull_qset{
void**data;
structscull_qset*next;
};//使用scull_dev表示每个设备
structscull_dev{
structscull_qset*data;/*Pointertofirstquantumset*/
intquantum;/*thecurrentquantumsize*/
intqset;/*thecurrentarraysize*/
unsignedlongsize;/*amountofdatastoredhere*/
unsignedintaccess_key;/*usedbysculluidandscullpriv*/
structsemaphoresem;/*mutualexclusionsemaphore*/
structcdevcdev;/*Chardevicestructure*/
};//TODO什么用?
/*
*Splitminorsintwoparts
*/
//高四位
#defineTYPE(minor)(((minor)>>4)&0xf)/*highnibble*/
//低四位
#defineNUM(minor)((minor)&0xf)/*lownibble*//*
*Thedifferentconfigurableparameters
*/
externintscull_major;/*main.c*/
externintscull_nr_devs;
externintscull_quantum;
externintscull_qset;externintscull_p_buffer;/*pipe.c*//*
*Prototypesforsharedfunctions
*/intscull_p_init(dev_tdev);
voidscull_p_cleanup(void);
intscull_access_init(dev_tdev);
voidscull_access_cleanup(void);intscull_trim(structscull_dev*dev);ssize_tscull_read(structfile*filp,char__user*buf,size_tcount,
loff_t*f_pos);
ssize_tscull_write(structfile*filp,constchar__user*buf,size_tcount,
loff_t*f_pos);
loff_tscull_llseek(structfile*filp,loff_toff,intwhence);
intscull_ioctl(structinode*inode,structfile*filp,
unsignedintcmd,unsignedlongarg);/*
*Ioctldefinitions
*///TODO魔数什么用?
/*Use'k'asmagicnumber*/
#defineSCULL_IOC_MAGIC'k'
/*Pleaseuseadifferent8-bitnumberinyourcode*/#defineSCULL_IOCRESET_IO(SCULL_IOC_MAGIC,0)/*
*Smeans"Set"throughaptr,
*Tmeans"Tell"directlywiththeargumentvalue
*Gmeans"Get":
replybysettingthroughapointer
*Qmeans"Query":
responseisonthereturnvalue
*Xmeans"eXchange":
switchGandSatomically
*Hmeans"sHift":
switchTandQatomically
*/
#defineSCULL_IOCSQUANTUM_IOW(SCULL_IOC_MAGIC,1,int)
#defineSCULL_IOCSQSET_IOW(SCULL_IOC_MAGIC,2,int)
#defineSCULL_IOCTQUANTUM_IO(SCULL_IOC_MAGIC,3)
#defineSCULL_IOCTQSET_IO(SCULL_IOC_MAGIC,4)
#defineSCULL_IOCGQUANTUM_IOR(SCULL_IOC_MAGIC,5,int)
#defineSCULL_IOCGQSET_IOR(SCULL_IOC_MAGIC,6,int)
#defineSCULL_IOCQQUANTUM_IO(SCULL_IOC_MAGIC,7)
#defineSCULL_IOCQQSET_IO(SCULL_IOC_MAGIC,8)
#defineSCULL_IOCXQUANTUM_IOWR(SCULL_IOC_MAGIC,9,int)
#defineSCULL_IOCXQSET_IOWR(SCULL_IOC_MAGIC,10,int)
#defineSCULL_IOCHQUANTUM_IO(SCULL_IOC_MAGIC,11)
#defineSCULL_IOCHQSET_IO(SCULL_IOC_MAGIC,12)/*
*Theotherentitiesonlyhave"Tell"and"Query",becausethey're
*notprintedinthebook,andthere'snoneedtohaveallsix.
*(Thepreviousstuffwasonlytheretoshowdifferentwaystodoit.
*/
#defineSCULL_P_IOCTSIZE_IO(SCULL_IOC_MAGIC,13)
#defineSCULL_P_IOCQSIZE_IO(SCULL_IOC_MAGIC,14)
/*moretocome*/#defineSCULL_IOC_MAXNR14#endif/*_SCULL_H_*/
main.c
/*
*main.c--thebarescullcharmodule
*
*Copyright(C)2001AlessandroRubiniandJonathanCorbet
*Copyright(C)2001O'Reilly&Associates
*
*Thesourcecodeinthisfilecanbefreelyused,adapted,
*andredistributedinsourceorbinaryform,solongasan
*acknowledgmentappearsinderivedsourcefiles.Thecitation
*shouldlistthatthecodecomesfromthebook"LinuxDevice
*Drivers"byAlessandroRubiniandJonathanCorbet,published
*byO'Reilly&Associates.Nowarrantyisattached;
*wecannottakeresponsibilityforerrorsorfitnessforuse.
*
*/#include<linux/config.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
#include<linux/init.h>#include<linux/kernel.h>/*printk()*/
#include<linux/slab.h>/*kmalloc()*/
#include<linux/fs.h>/*everything*/
#include<linux/errno.h>/*errorcodes*/
#include<linux/types.h>/*size_t*/
#include<linux/proc_fs.h>
#include<linux/fcntl.h>/*O_ACCMODE*/
#include<linux/seq_file.h>
#include<linux/cdev.h>#include<asm/system.h>/*cli(),*_flags*/
#include<asm/uaccess.h>/*copy_*_user*/#include"scull.h"/*localdefinitions*//*
*Ourparameterswhichcanbesetatloadtime.
*/intscull_major=SCULL_MAJOR;//主设备号
intscull_minor=0;//次设备号
intscull_nr_devs=SCULL_NR_DEVS;/*numberofbaresculldevices*/
intscull_quantum=SCULL_QUANTUM;//量子大小(字节)
intscull_qset=SCULL_QSET;//量子集大小//插入模块时指定的参数
module_param(scull_major,int,S_IRUGO);
module_param(scull_minor,int,S_IRUGO);
module_param(scull_nr_devs,int,S_IRUGO);
module_param(scull_quantum,int,S_IRUGO);
module_param(scull_qset,int,S_IRUGO);MODULE_AUTHOR("AlessandroRubini,JonathanCorbet");
MODULE_LICENSE("DualBSD/GPL");structscull_dev*scull_devices;/*allocatedinscull_init_module*///释放整个数据区。
简单遍历列表并且释放它发现的任何量子和量子集。
//在scull_open在文件为写而打开时调用。
//调用这个函数时必须持有信号量。
/*
*Emptyoutthesculldevice;mustbecalledwiththedevice
*semaphoreheld.
*/
intscull_trim(structscull_dev*dev)
{
structscull_qset*next,*dptr;
intqset=dev->qset;/*"dev"isnot-null*///量子集大小
inti;//遍历多个量子集。
dev->data指向第一个量子集。
for(dptr=dev->data;dptr;dptr=next){/*allthelistitems*/
if(dptr->data){//量子集中有数据
for(i=0;i<qset;i++)//遍历释放当前量子集中的每个量子。
量子集大小为qset。
kfree(dptr->data[i]);
kfree(dptr->data);//释放量子指针数组
dptr->data=NULL;
}
//next获取下一个量子集,释放当前量子集。
next=dptr->next;
kfree(dptr);
}
//清理structscull_devdev中变量的值
dev->size=0;
dev->quantum=scull_quantum;
dev->qset=scull_qset;
dev->data=NULL;
return0;
}
#ifdefSCULL_DEBUG/*useproconlyifdebugging*/
/*
*Theprocfilesystem:
functiontoreadandentry
*///在proc里实现文件,在文件被读时产生数据
//当一个进程读/proc文件,内核分配了一页内存,驱动可以写入数据返回用