Linux26内核驱动移植参考.docx
《Linux26内核驱动移植参考.docx》由会员分享,可在线阅读,更多相关《Linux26内核驱动移植参考.docx(12页珍藏版)》请在冰豆网上搜索。
Linux26内核驱动移植参考
随着Linux2.6的发布,由于2.6内核做了教的改动,各个设备的驱动程序在不同程度上要
进行改写。
为了方便各位Linux爱好者我把自己整理的这分文档share出来。
该文当列举
了2.6内核同以前版本的绝大多数变化,可惜的是由于时间和精力有限没有详细列出各个
函数的用法。
特别声明:
该文档中的内容来自http:
/,该网也上也有各个函数的较为详细的
说明可供各位参考。
如果需要该文档的word版的朋友,请mail到weiriver@索
取。
1、使用新的入口
必须包含
module_init(your_init_func);
module_exit(your_exit_func);
老版本:
intinit_module(void);
voidcleanup_module(voi);
2.4中两种都可以用,对如后面的入口函数不必要显示包含任何头文件。
2、GPL
MODULE_LICENSE("DualBSD/GPL");
老版本:
MODULE_LICENSE("GPL");
3、模块参数
必须显式包含
module_param(name,type,perm);
module_param_named(name,value,type,perm);
参数定义
module_param_string(name,string,len,perm);
module_param_array(name,type,num,perm);
老版本:
MODULE_PARM(variable,type);
MODULE_PARM_DESC(variable,type);
4、模块别名
MODULE_ALIAS("alias-name");
这是新增的,在老版本中需在/etc/modules.conf配置,现在在代码中就可以实现。
5、模块计数
inttry_module_get(&module);
module_put();
老版本:
MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT
6、符号导出
只有显示的导出符号才能被其他模块使用,默认不导出所有的符号,不必使用EXPORT_NO
_SYMBOLS
老板本:
默认导出所有的符号,除非使用EXPORT_NO_SYMBOLS
7、内核版本检查
需要在多个文件中包含时,不必定义__NO_VERSION__
老版本:
在多个文件中包含时,除在主文件外的其他文件中必须定义_
_NO_VERSION__,防止版本重复定义。
8、设备号
kdev_t被废除不可用,新的dev_t拓展到了32位,12位主设备号,20位次设备号。
unsignedintiminor(structinode*inode);
unsignedintimajor(structinode*inode);
老版本:
8位主设备号,8位次设备号
intMAJOR(kdev_tdev);
intMINOR(kdev_tdev);
9、内存分配头文件变更
所有的内存分配函数包含在头文件,而原来的不存在
老版本:
内存分配函数包含在头文件
10、结构体的初试化
gcc开始采用ANSIC的struct结构体的初始化形式:
staticstructsome_structure={
.field1=value,
.field2=value,
..
};
老版本:
非标准的初试化形式
staticstructsome_structure={
field1:
value,
field2:
value,
..
};
11、用户模式帮助器
intcall_usermodehelper(char*path,char**argv,char**envp,
intwait);
新增wait参数
12、request_module()
request_module("foo-device-%d",number);
老版本:
charmodule_name[32];
printf(module_name,"foo-device-%d",number);
request_module(module_name);
13、dev_t引发的字符设备的变化
1、取主次设备号为
unsignediminor(structinode*inode);
unsignedimajor(structinode*inode);
2、老的register_chrdev()用法没变,保持向后兼容,但不能访问设备号大于256的设备
。
3、新的接口为
a)注册字符设备范围
intregister_chrdev_region(dev_tfrom,unsignedcount,char*name);
b)动态申请主设备号
intalloc_chrdev_region(dev_t*dev,unsignedbaseminor,unsignedcount,char
*name);
看了这两个函数郁闷吧^_^!
怎么和file_operations结构联系起来啊?
别急!
c)包含,利用structcdev和file_operations连接
structcdev*cdev_alloc(void);
voidcdev_init(structcdev*cdev,structfile_operations*fops);
intcdev_add(structcdev*cdev,dev_tdev,unsignedcount);
(分别为,申请cdev结构,和fops连接,将设备加入到系统中!
好复杂啊!
)
d)voidcdev_del(structcdev*cdev);
只有在cdev_add执行成功才可运行。
e)辅助函数
kobject_put(&cdev->kobj);
structkobject*cdev_get(structcdev*cdev);
voidcdev_put(structcdev*cdev);
这一部分变化和新增的/sys/dev有一定的关联。
14、新增对/proc的访问操作
以前的/proc中只能得到string,seq_file操作能得到如long等多种数据。
相关函数:
staticstructseq_operations必须实现这个类似file_operations得数据中得各个成
员函数。
seq_printf();
intseq_putc(structseq_file*m,charc);
intseq_puts(structseq_file*m,constchar*s);
intseq_escape(structseq_file*m,constchar*s,constchar*esc);
intseq_path(structseq_file*m,structvfsmount*mnt,
structdentry*dentry,char*esc);
seq_open(file,&ct_seq_ops);
等等
15、底层内存分配
1、头文件改为
2、分配标志GFP_BUFFER被取消,取而代之的是GFP_NOIO和GFP_NOFS
3、新增__GFP_REPEAT,__GFP_NOFAIL,__GFP_NORETRY分配标志
4、页面分配函数alloc_pages(),get_free_page()被包含在中
5、对NUMA系统新增了几个函数:
a)structpage*alloc_pages_node(intnode_id,
unsignedintgfp_mask,
unsignedintorder);
b)voidfree_hot_page(structpage*page);
c)voidfree_cold_page(structpage*page);
6、新增Memorypools
mempool_t*mempool_create(intmin_nr,
mempool_alloc_t*alloc_fn,
mempool_free_t*free_fn,
void*pool_data);
void*mempool_alloc(mempool_t*pool,intgfp_mask);
voidmempool_free(void*element,mempool_t*pool);
intmempool_resize(mempool_t*pool,intnew_min_nr,intgfp_mask);
16、per-CPU变量
get_cpu_var();
put_cpu_var();
void*alloc_percpu(type);
voidfree_percpu(constvoid*);
per_cpu_ptr(void*ptr,intcpu)
get_cpu_ptr(ptr)
put_cpu_ptr(ptr)
老版本使用
DEFINE_PER_CPU(type,name);
EXPORT_PER_CPU_SYMBOL(name);
EXPORT_PER_CPU_SYMBOL_GPL(name);
DECLARE_PER_CPU(type,name);
DEFINE_PER_CPU(int,mypcint);
2.6内核采用了可剥夺得调度方式这些宏都不安全。
17、内核时间变化
1、现在的各个平台的HZ为
Alpha:
1024/1200;ARM:
100/128/200/1000;CRIS:
100;i386:
1000;IA-64:
1024;M68K:
100;M68K-nommu:
50-1000;MIPS:
100/128/1000;MIPS64:
100;
PA-RISC:
100/1000;PowerPC32:
100;PowerPC64:
1000;S/390:
100;SPARC32:
100;SPARC64:
100;SuperH:
100/1000;UML:
100;v850:
24-100;x86-64:
1000.
2、由于HZ的变化,原来的jiffies计数器很快就溢出了,引入了新的计数器jiffies_64
3、#include
u64my_time=get_jiffies_64();
4、新的时间结构增加了纳秒成员变量
structtimespeccurrent_kernel_time(void);
5、他的timer函数没变,新增
voidadd_timer_on(structtimer_list*timer,intcpu);
6、新增纳秒级延时函数
ndelay();
7、POSIXclocks参考kernel/posix-timers.c
18、工作队列(workqueue)
1、任务队列(taskqueue)接口函数都被取消,新增了workqueue接口函数
structworkqueue_struct*create_workqueue(constchar*name);
DECLARE_WORK(name,void(*function)(void*),void*data);
INIT_WORK(structwork_struct*work,
void(*function)(void*),void*data);
PREPARE_WORK(structwork_struct*work,
void(*function)(void*),void*data);
2、申明structwork_struct结构
intqueue_work(structworkqueue_struct*queue,
structwork_struct*work);
intqueue_delayed_work(structworkqueue_struct*queue,
structwork_struct*work,
unsignedlongdelay);
intcancel_delayed_work(structwork_struct*work);
voidflush_workqueue(structworkqueue_struct*queue);
voiddestroy_workqueue(structworkqueue_struct*queue);
intschedule_work(structwork_struct*work);
intschedule_delayed_work(structwork_struct*work,unsignedlong
delay);
19、新增创建VFS的"libfs"
libfs给创建一个新的文件系统提供了大量的API.
主要是对structfile_system_type的实现。
参考源代码:
drivers/hotplug/pci_hotplug_core.c
drivers/usb/core/inode.c
drivers/oprofile/oprofilefs.c
fs/ramfs/inode.c
fs/nfsd/nfsctl.c(simple_fill_super()example)
20、DMA的变化
未变化的有:
void*pci_alloc_consistent(structpci_dev*dev,size_tsize,
dma_addr_t*dma_handle);
voidpci_free_consistent(structpci_dev*dev,size_tsize,
void*cpu_addr,dma_addr_tdma_handle);
变化的有:
1、void*dma_alloc_coherent(structdevice*dev,size_tsize,
dma_addr_t*dma_handle,intflag);
voiddma_free_coherent(structdevice*dev,size_tsize,
void*cpu_addr,dma_addr_tdma_handle);
2、列举了映射方向:
enumdma_data_direction{
DMA_BIDIRECTIONAL=0,
DMA_TO_DEVICE=1,
DMA_FROM_DEVICE=2,
DMA_NONE=3,
};
3、单映射
dma_addr_tdma_map_single(structdevice*dev,void*addr,
size_tsize,
enumdma_data_directiondirection);
voiddma_unmap_single(structdevice*dev,dma_addr_tdma_addr,
size_tsize,
enumdma_data_directiondirection);
4、页面映射
dma_addr_tdma_map_page(structdevice*dev,structpage*page,
unsignedlongoffset,size_tsize,
enumdma_data_directiondirection);
voiddma_unmap_page(structdevice*dev,dma_addr_tdma_addr,
size_tsize,
enumdma_data_directiondirection);
5、有关scatter/gather的函数:
intdma_map_sg(structdevice*dev,structscatterlist*sg,
intnents,enumdma_data_directiondirection);
voiddma_unmap_sg(structdevice*dev,structscatterlist*sg,
intnhwentries,enumdma_data_directiondirection);
6、非一致性映射(NoncoherentDMAmappings)
void*dma_alloc_noncoherent(structdevice*dev,size_tsize,
dma_addr_t*dma_handle,intflag);
voiddma_sync_single_range(structdevice*dev,dma_addr_tdma_handle,
unsignedlongoffset,size_tsize,
enumdma_data_directiondirection);
voiddma_free_noncoherent(structdevice*dev,size_tsize,
void*cpu_addr,dma_addr_tdma_handle);
7、DAC(doubleaddresscycle)
intpci_dac_set_dma_mask(structpci_dev*dev,u64mask);
voidpci_dac_dma_sync_single(structpci_dev*dev,
dma64_addr_tdma_addr,
size_tlen,intdirection);
21、互斥
新增seqlock主要用于:
1、少量的数据保护
2、数据比较简单(没有指针),并且使用频率很高
3、对不产生任何副作用的数据的访问
4、访问时写者不被饿死
初始化
seqlock_tlock1=SEQLOCK_UNLOCKED;
或seqlock_tlock2;seqlock_init(&lock2);
voidwrite_seqlock(seqlock_t*sl);
voidwrite_sequnlock(seqlock_t*sl);
intwrite_tryseqlock(seqlock_t*sl);
voidwrite_seqlock_irqsave(seqlock_t*sl,longflags);
voidwrite_sequnlock_irqrestore(seqlock_t*sl,longflags);
voidwrite_seqlock_irq(seqlock_t*sl);
voidwrite_sequnlock_irq(seqlock_t*sl);
voidwrite_seqlock_bh(seqlock_t*sl);
voidwrite_sequnlock_bh(seqlock_t*sl);
unsignedintread_seqbegin(seqlock_t*sl);
intread_seqretry(seqlock_t*sl,unsignedintiv);
unsignedintread_seqbegin_irqsave(seqlock_t*sl,longflags);
intread_seqretry_irqrestore(seqlock_t*sl,unsignedintiv,long
flags);
22、内核可剥夺
preempt_disable();
preempt_enable_no_resched();
preempt_enable_noresched();
preempt_check_resched();
23、眠和唤醒
1、原来的函数可用,新增下列函数:
prepare_to_wait_exclusive();
prepare_to_wait();
2、等待队列的变化
typedefint(*wait_queue_func_t)(wait_queue_t*wait,
unsignedmode,intsync);
voidinit_waitqueue_func_entry(wait_queue_t*queue,
wait_queue_func_tfunc);
24、新增完成事件(completionevents)
init_completion(&my_comp);
voidwait_for_completion(structcompletion*comp);
voidcomplete(structcompletion*comp);
voidcomplete_all(structcompletion*comp);
25、RCU(Read-copy-update)
rcu_read_lock();
voidcall_rcu(structrcu_head*head,void(*func)(void*arg),
void*arg);
26、中断处理
1、中断处理有返回值了。
IRQ_RETVAL(handled);
2、cli(),sti(),save_flags(),和restore_flags()不再有效,应该使用local_save
_flags()或local_irq_disable()。
3、synchronize