Linux驱动
文章平均质量分 85
庾志辉
这个作者很懒,什么都没留下…
展开
-
s3c2440系统自带的管脚宏和函数
S3C2410_GPF(4) #define S3C2410_GPF(_nr) (S3C2410_GPIO_F_START + (_nr)) ==》变成:S3C2410_GPIO_F_START+4S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E) ==》变成:S3C2410_GPIO_NEXT(S3C241原创 2015-04-17 13:53:34 · 1735 阅读 · 0 评论 -
linux驱动之时间管理
系统的时钟频率 时钟频率详解和编程 ,一般系统都会有个默认的时钟频率HZ,其实就是1秒内系统时钟发生多少次中断。假如:系统的HZ为1000,则表示1秒内系统会产生1000次时钟中断; 滴答数: 系统内核会有个统计时钟中断发生的次数的计数器,该计数器从系统启动引导被初始化为0后,只要发生一次时钟中断,该计数器就自增1;所以该计数器就是表示从开机起发生多少次中断。该计数器是个64位的变量(不管你系统或者cpu架构 是32位还是64位,该变量都是64位的),称为 jiffies_64。但原创 2015-09-24 11:23:51 · 766 阅读 · 0 评论 -
netconsole简单配置
驱动开发的一个难点就是调试,因为应用程序不管怎么弄都不会怎么样,最多不过是段错误。可是驱动程序如果出问题,那么整个系统可能就会崩溃掉。如果有个驱动程序调试时,总是崩溃,那么这时候就应该使用netconsole了。netconsole是把远程服务器上内核打印的log通过网络传递到本地输出,实时传输过来本地。所以就算驱动使系统崩溃了,本地也会保留一些log,这样就可以方便调试了。本地操作:nc -dul 6699服务器操作:rmmod netconsole;modprobe netconsole netc原创 2015-07-14 15:21:16 · 6710 阅读 · 0 评论 -
linux内核内存的详细分配
我们知道CPU所访问的都是虚拟内存地址。那么平时我们自己在编写的内核模块时,linux到底分配的是什么样的内存空间呢?要解答这个问题,首先就要看看内核非连续内存。在linux的内存管理中,用户使用0~3GB的地址空间,而内核只是用了3GB~4GB区间的地址空间,共1GB;非连续空间的物理映射就位于3GB~4GB之间,如下图示0GB转载 2015-08-04 22:23:40 · 11687 阅读 · 1 评论 -
访问I/O内存和I/O端口设备
前面为了写pwm驱动,仔细研究了下I/O内存和I/O端口设备的区别,以及访问方式。不过,其实也没必要纠结这个了,因为现在绝大部分设备都使用I/O内存映射的。I/O独立编址和I/O统一编址 首先有两个概念:I/O独立编址和I/O统一编址;记住这两种编址方式都是由CPU架构决定的。 I/O独立编址:应该只有X86处理器才是I/O独立编址,其他的处理器原创 2015-08-04 22:25:50 · 1717 阅读 · 0 评论 -
linux设备驱动程序之并发和竞态(一)
信号量的头文件在<asm/semaphore.h>,所以要使用信号量就必须包含这个头文件。 声明:struct semaphore sem; 初始化: 1、静态初始化: DECLARE_MUTEX(&sem); //这个信号量初始化为1,可以马上使用; DECLARE_MUTEX_LOCKED(&sem); //这个信号量初始化为0,如果要使用要先解锁,打开信号量原创 2015-06-28 12:59:33 · 1098 阅读 · 0 评论 -
linux设备驱动程序之并发和竞态(二)
所谓的锁陷阱就是防止死锁。 不明确的规则: 1、不论是信号量还是 自旋锁,都不允许锁拥有者第二次获得这个锁(会死锁)。 2、系统直接调用的那些函数要获得信号量,保护要访问的设备结构。而内部函数的访问则可以根据需要上锁。 锁顺序规则: 1、如果都要获取一系列锁的话,那么可以按照一定顺序规则来获取锁,即:获取多个锁时,锁的顺序一直; 2、如果要获取自己的局部锁和系统的中心锁,则先获取自己的局部锁,然后再去获取中心锁原创 2015-07-05 13:16:28 · 1095 阅读 · 0 评论 -
linux内核内存分配(二、struct slab和struct kmem_cache)
前一篇blog linux内核内存分配(一、基本概念)主要是分析linux内核内存的分配和物理页分配函数接口。但是在实际的操作中,不一定所有内存申请都需要一个物理页,很多只是需要分配几K大小的内存就可以。所以就需要更小的内存分配函数。刚开始看这个有点不懂,不过懂了就很简单了。哈哈。 摘抄《深入linux设备驱动程序内核机制》的一段话:slab分配器的基本思想是,先利用页面分配原创 2015-08-10 21:04:46 · 7315 阅读 · 2 评论 -
linux内核内存分配(一、基本概念)
首先大概的可以看出左边的mem_map数组中存放的是page结构体元素,中间的是实际的物理内存,右边的是虚拟的地址范围; 他们之间的关系大概是这样的,mem_map数组中的元素和物理内存页联系,page指针指向中间的物理内存中的某个物理页,这个关系是为了系统方便管理内存; 而物理内存页和右边的虚拟地址范围映射,这个是为了操作物理内存,一般右边的虚拟地址由cpu使用(软件上使用的也是虚拟地址,不过该地址最终还是CPU使用)。CPU和MMU之间使用的都是虚拟地址,出了MMU后原创 2015-08-05 22:12:37 · 3032 阅读 · 0 评论 -
linux内核定时器
如果我们需要设定内核在某个时间后执行某个动作,并且在该时间到达之前不会阻塞当前进程,则可以使用内核定时器了。也就是:在未来的某个时间点执行某个函数,完成某个任务;比如周期的轮询设备的状态; 一般来说当某个进程注册了定时器和定时器执行函数后,这些函数都不会在该进程还在运行时就执行。反而是当该进程退出运行后(或者休眠,或者在其他cpu上执行),这些定时器函数才会执行,也就是说这些定时原创 2015-09-24 11:26:01 · 1599 阅读 · 0 评论 -
linux内核源码分析(内存管理)--之数据结构
#define PGDIR_SHIFT 22 虚拟地址address >> PGDIR_SHIFT就可以得到PGD的下标,然后根据 (PGD + address>> PGDIR_SHIFT) 得到PGD的指针;#define PGDIR_SIZE (1UL #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET);#define原创 2016-04-27 22:24:14 · 1835 阅读 · 0 评论 -
linux内存管理--慢速分配内存页 __alloc_pages_slowpath
page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype);static inline struct page *__alloc_pages_slowpath(g原创 2016-04-27 22:27:56 · 4208 阅读 · 0 评论 -
linux中页缓冲和块缓冲之概念
页缓冲在《linux内核情景分析》一书的第5.6节文件的写与读一章中说明的很详细,这里摘抄下来;在文件系统层中有三隔主要的数据结构,file结构、dentry结构和inode结构;file结构:代表目标文件的一个上下文,不同进程可以在同一文件上建立不同的上下文,而且同一进程也可以通过打开一个文件多次而建立起多个上下文。因此不能在file结构上设置缓冲区队列,因为这些file结构体之间都不共原创 2016-04-27 22:41:01 · 6544 阅读 · 0 评论 -
linux内存管理--实际分配函数 buffered_rmqueue
不管是快速分配还是慢速分配,实际分配内存的都是 buffered_rmqueue()函数,其他的都是在选择从哪个地方来分配比较合适;还是先来说说各个参数:struct zone *preferred_zone 表示分配所能接受的最大zone类型struct zone *zone 表示就在该zone上分配内存;int order 表示分配页的阶数gfp_t gfp_flag原创 2016-04-27 22:39:41 · 5870 阅读 · 0 评论 -
linux内存管理--slab
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { return kmem_cache_create_memcg(NULL, name, size, align, f原创 2016-04-27 22:38:26 · 4309 阅读 · 0 评论 -
linux内存管理--高端内存映射
void *kmap(struct page *page){ might_sleep(); if (!PageHighMem(page)) return page_address(page); return kmap_high(page);}/** * page_address - get the mapped virtual ad原创 2016-04-27 22:30:03 · 1124 阅读 · 0 评论 -
linux内存管理--vmalloc
/** * vmalloc - allocate virtually contiguous memory * @size: allocation size * Allocate enough pages to cover @size from the page level * allocator and map them into contiguous kernel原创 2016-04-27 22:29:10 · 4399 阅读 · 0 评论 -
linux内存管理--伙伴系统分配内存准备工作
linux内核内存管理的代码改变的有点大,主要是细节方面;首先从 __get_free_pages()开始总结起:unsigned long __get_free_pages(grp_t gfp_mask, unsigned int order)/* * Common helper functions. */ unsigne原创 2016-04-27 22:26:07 · 1723 阅读 · 0 评论 -
__get_free_pages
说下分配策略,这个分配策略主要是获取到节点的编号(也就是得到 pgdat 结构体);下面是分配策略的结构体static inline struct page *__alloc_pages(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist){原创 2016-04-27 22:24:51 · 2043 阅读 · 0 评论 -
PCIe 配置空间读写内核实现
1 PCI及PCI-E配置空间介绍 PCI-E是用来互联如计算和通信平台应用中外围设备的第三代高性能I/O总线。PCI-E采用了与PCI相同的使用模型和读写(load-store)通信模型,支持各种常见的事务,如存储器读/写、IO读/写和配置读/写事务。其存储器、IO和配置地址空间与PCI的地址空间相同。PCI Express与PCI系统是软件向后兼容的。PCI-E的配置空间大转载 2015-08-04 22:28:50 · 12374 阅读 · 1 评论 -
kthread_run函数
最近发现在内核创建线程的时候经常会用到kthread_run()这样的一个调用。于是准备拿出来学习一下。首先看看它的定义之处才发现它是一个宏函数,而不是一个真正意义上的函数。在include/linux/Kthread.h里有/*** kthread_run - create and wake a thread.* @threadfn: the function to run un转载 2015-08-04 22:27:44 · 1259 阅读 · 0 评论 -
PCIe总线学习笔记(一、PCI基础知识简介)
PCIe总线是继承了PCI总线而设计而来的,所以理解PCIe总线先熟悉PCI总线会有很大帮助;我写的blog是根据《PCI Express 体系结构导读》作者:王齐,这本书学习后的整理笔记,都是自己理解后用自己的意思表达的,如果理解上有什么出入希望大家可以指出,请以作者原书为准,谢谢; 在看这个书时我规规矩矩的从前往后看,其实有些内容在后面会有很多理解和答案;先看下下面的图示,会原创 2015-05-01 09:28:17 · 27007 阅读 · 0 评论 -
ioctl中cmd格式
在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域:bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。bit29~bit16 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内转载 2015-05-11 14:59:11 · 1694 阅读 · 0 评论 -
下降沿触发与电平触发的区别
下降沿触发下降沿检测的是电平变化,高电平转低电平时,触发一次中断。下降沿触发是锁存中断信号的,由D触发器记忆,意即:即使当时CPU来不及响应中断,外部中断信号撤消后,由于D触发器的记忆作用,消失的中断信号仍然有效,直到中断被响应并进入中断ISR,记忆的中断信号才会由硬件清除。电平触发电平触发是一个时间段,需要一直触发中断的,就用电平触发。比如低电平触发,只要检测到是转载 2015-04-20 12:20:50 · 6952 阅读 · 0 评论 -
s3c2440 LED驱动分析
这个开发板已经很久没有动了,这一次辞职后想来想去还是选择去做驱动吧。以前写的那些驱动代码早就不知道哪里去了,当然更不记得了。所以现在从头开始学习,也顺便记录下笔记;原理 首先看看LED的电路图: 不难看出,LED1==GPB5 LED2==GPB6 LED3==GPB7 LED4==GPB8 然原创 2015-04-18 20:36:10 · 2286 阅读 · 0 评论 -
s3c2440 杂项驱动实现蜂鸣器
这个驱动本来是非常简单的,但是我就是想做个杂项驱动。Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述)。miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同。其实从上面的结构体可以知道,杂项设备驱动只能驱动一个设备,因为杂项驱动主设备号固定为10(不同杂项设备通过次设备号来区分),而结构体中只有一个次设备号,所以可以看出杂项驱动只能驱动一个设备;如果要驱动多个设备,则不能用杂项驱动;(同类设备要靠次设备来区分)原创 2015-04-19 19:14:31 · 2426 阅读 · 0 评论 -
驱动的两种编译方法
静态编译 就是直接把驱动放到内核中,成为内核中的一部分。把写好的驱动源代码(led.c文件)放到,内核的字符驱动中(路径为:linux-2.6.32.2/drivers/char ),然后修改下配置; 第一部分要修改的是:Kconfig(vim linux-2.6.32.2/drivers/char/Kconfig) 往里面添加: config MY原创 2015-04-16 23:50:49 · 5571 阅读 · 0 评论 -
如何把自己的驱动编译进内核或模块(Kconfig和Makefile)
2.6内核的源码树目录下一般都会有两个文文:Kconfig和Makefile。分布在各目录下的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文件相关的内核配置菜单。在内核配置make menuconfig(或xconfig等)时,从Kconfig中读出配置菜单,用户配置完后保存到.config(在顶层目录下生成)中。在内核编译时,主Makefile调用这个.转载 2015-04-16 19:19:48 · 2974 阅读 · 0 评论 -
为什么在Kconfig添加了MODULE,然后在make menu
原文地址:menuconfig中找不到选项" style="text-decoration:none; color:rgb(33,128,36)">为什么在Kconfig添加了MODULE,然后在make menuconfig中找不到选项作者:Fisher在kernel-2.6.13driverscharKconfig中添 加了一个MODULE,config QQ2440_HE转载 2015-04-16 19:45:45 · 1079 阅读 · 0 评论 -
kzalloc和kmalloc函数详解
用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0.view plain/** * kzalloc - allocate memory. The memory is set to zero. * @size: how many bytes转载 2015-05-06 16:09:56 · 2801 阅读 · 0 评论 -
linux块设备驱动之相关结构体
我做的主要是ssd驱动,ssd驱动通过FTL转换成对一个磁盘的操作,也就相当于一个磁盘的块设备驱动。块设备驱动程序主要通过传输固定大小的随机数据来访问设备。注册块设备 和字符设备驱动一样,都必须先到内核注册下,才能操作设备;在头文件中 注册函数: int register_blkdev(unsigned int major, const char原创 2015-07-05 16:18:31 · 2450 阅读 · 0 评论 -
Linux伙伴系统
(一)--伙伴系统的概述 Linux内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下,避免碎片的产生。Linux采用伙伴系统解决外部碎片的问题,采用slab解决内部碎片的问题,在这里我们先讨论外部碎片问题。避免外部碎片的方法有两种:一种是之前介绍过的利用非连续内存的分配;另外一种则是用一种有效的方法来监视内存,保证在内核只要申请一小块内存的情况下,不会从大块的连续空闲内存中截取一段转载 2015-08-04 22:27:07 · 944 阅读 · 0 评论 -
Linux内存管理--伙伴系统和内存分配器
Linux内核使用伙伴系统来解决内存分配引起的外部碎片问题。伙伴系统分配器大体上分为两类。__get_free_pages()类函数返回分配的第一个页面的线性地址;alloc_pages()类函数返回页面描述符地址。不管以哪种函数进行分配,最终会调用alloc_pages()进行分配页面。为清楚了解其分配制度,先给个伙伴系统数据的存储框图。也就是每个order对应一个free_area转载 2015-08-04 22:26:36 · 2500 阅读 · 0 评论 -
pwm的工作原理
s3c2440芯片中一共有5个16位的定时器,其中有4个定时器(定时器0~定时器3)具有脉宽调制功能,即他们都有个输出引脚,可以通过定时器来控制引脚周期性的高低电平变化,定时器4没有输出引脚。上次脱机运行PWM测试程序实验的时候就用到了这块,所以这次将PWM和定时器放在一起来学习。 定时器部件的时钟源为PCLK,首先通过两个8位预分频器降低频率,定时器0和1共用第一个预分频器,2,3转载 2015-07-22 23:43:00 · 6367 阅读 · 0 评论 -
pwm驱动原理和代码实现
第一个知识点:I/O映射和内存映射所牵扯到的知识点,包括统一编址和独立编址,以及linux下怎么对这两种方式编程,以及这两种方式下怎么访问外设。 第二个知识点:映射到内存哪里?怎么映射?所以就涉及到linux内核的内存分布问题,顺便也分析了几个内核内存分配函数的区别。 我最开始有写个简单的峰鸣器驱动,不能调频率的: s3c2440 杂项驱动实现蜂鸣器 里面用杂项设备驱动使峰鸣器工作,当然里面都是调用了s3c2440下提供的读写函数。这个对移植来说不是很好,我这篇blog是用通用的函数从底层一步步使pwm原创 2015-07-22 23:43:22 · 9753 阅读 · 0 评论 -
linux内核内存分配(三、虚拟内存管理)
vmalloc函数是驱动模块经常使用的内存分配函数,该函数返回的虚拟地址连续的(其实这也有疑问,因为上面vmalloc的虚拟地址区有4k分割地址,如果vmalloc分配的虚拟地址很大,那么中间是否有4kb的分割地址?),但是不保证所映射的物理地址也是连续的。它主要对上面的vmalloc_start到vmalloc_end这段内存操作,返回的虚拟地址就是这一部分的。 在大多数情况下,不鼓励使用vmalloc来申请内存,原因: 1、通过vmalloc函数获取的内存使用效率不高(因为要自己做映射,要原创 2015-08-14 00:14:10 · 4392 阅读 · 0 评论 -
linux块设备驱动之实例
前两篇blog已经基本熟悉了块设备的相关结构,这里来总结下ldd3中提到的一些块设备驱动例题;注册: sbull_major = register_blkdev(sbull_major, "sbull"); if (0 >= sbull_major){ printk(KERN_WARNING "sbull: u原创 2015-07-13 00:39:18 · 3251 阅读 · 0 评论 -
linux块设备驱动之请求过程剖析
当设备完成在一个I/O请求的部分或者全部的扇区时,必须调用下面的函数通知块设备子系统:int end_that_request_first(struct request *req, int success, int count);该函数告诉块设备代码:驱动程序从前一次结束的地方开始,完成了规定数目的扇区的传输。请注意必须报告从第一个扇区到最后一个扇区的完成情况; end_that_request_first 的返回值表明该请求中的所有扇区是否被传输。返回0表示把count个扇区已经原创 2015-07-12 21:31:37 · 1630 阅读 · 0 评论 -
linux块设备驱动之相关结构体间的关系
前一篇blog中已经贴出这些相关的结构体,但是其中关系还是没有说的很清楚。现在来理一理它们之间的关系,首先是struct gendisk 和 struct block_device 以及struct hd_struct;其中struct gendisk 表示的是一个块设备,而struct block_device表示是一个分区设备(也可以表示块设备),struct hd_struct表示的是一个分区信息;它们的关系如下面。原创 2015-07-08 21:29:47 · 1551 阅读 · 0 评论 -
linux内存管理--分配内存页(快速) get_page_from_freelist
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, zonelist, high_zoneidx, alloc_flags, preferred_zone, migratetype);static struct page *get_page_fr原创 2016-04-27 22:26:58 · 5036 阅读 · 0 评论