- 博客(54)
- 资源 (80)
- 收藏
- 关注
转载 Linux驱动调试
驱动程序开发的一个重大难点就是不易调试。本文目的就是介绍驱动开发中常用的几种直接和间接的调试手段,它们是:利用printk查看OOP消息利用strace利用内核内置的hacking选项利用ioctl方法利用/proc 文件系统使用kgdb一、利用printk这是驱动开发中最朴实无华,同时也是最常用和有效的手段。scull驱动的main.c第338行如下,就是使用printk
2016-09-28 17:13:03 2535
转载 C语言中冒泡法、选择法、插入法三种常见排序算法
一、冒泡法 算法要求:用起泡法对10个整数按升序排序。 算法分析:如果有n个数,则要进行n-1趟比较。在第1趟比较中要进行n-1次相邻元素的两两比较,在第j趟比较中要进行n-j次两两比较。比较的顺序从前往后,经过一趟比较后,将最值沉底(换到最后一个元素位置),最大值沉底为升序,最小值沉底为降序。 算法源代码:# include main()
2016-09-23 21:26:08 9591 3
原创 (十一)1 简单的看门狗驱动
来个简单的看门狗驱动——静态平台类的杂设备看门狗驱动,有定时和重启两个基本功能。一、S3C2440中的看门狗——具体请看s3c2440文档看门狗应该可以算是S3C2440中最简单的一个设备的,仅仅只有三个寄存器需要配置。S3C2440中的看门狗有两种功能(只能二选一):1、复位功能,在指定时间内,如果没有执行喂狗操作。指定时间到达后会执行系统重启操作
2016-09-21 11:32:21 972
原创 (十)1 udev&misc
一、动态创建设备节点——udev之前加载字符型设备后是通过命令mknod来创建设备节点的。在2.6内核中,有一个名叫udev的后台程序,它通过读取/sys/class的信息,一旦添加的新的设备,该后台程序就会自动创建设备节点。一、要使用动态创建设备节点,首先要运行udev后台程序。在嵌入式下有两种方法:1、移植udev到嵌入式系统
2016-09-21 11:28:26 263
原创 (九)1 platform设备驱动
一、什么是paltform总线一个现实的linux设备和驱动通常都需要挂接在一种总线上,比较常见的总线有USB、PCI总线等。但是,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。基于这样的背景下,2.6内核加入了platform虚拟总线。platform机制将设备本身的资源注册进内核,有内核统一管理,在驱动程序使用这些资源时
2016-09-21 11:26:37 262
原创 (八)4.总线热插拔
一、热插拔的实现我不知道在这里用热插拔这样的名字是否合适,在之前的代码,需要我自己手动去加载驱动和设备的模块,但在现实的情况下,一般是当设备一被插入,系统自己会注册设备,并调用合适的驱动。所以,接下来我要实现的是,在加载了usb总线和usb鼠标驱动的前提下,当有usb鼠标插入,系统自己进行设备的操作。当然,上面的usb鼠标是我自己想象出来的,当我一按下按键(对应中断E_
2016-09-21 11:24:25 9238
原创 (八) 3 设备模型的分层与面向对象
一、设备管理的分层回想一下之前的设备和驱动函数注册时,它们是自己指定所属的总线。但是,内核开发人员觉得,这样的方法不好,应该由总线来提供设备和驱动的注册函数。当设备和驱动需要注册到指定总线时,那就必须使用该总线为设备和驱动提供的注册函数。所以,将上一节的bus.c修改如下:/*8th_devModule_3/1st/bus.c*/21 /*总
2016-09-21 11:22:46 249
原创 (八)2 match.probe.remove
一、总线、设备和驱动函数在/sys/中的框架首先要写三个函数,bus.c、device.c和driver.c。这几个函数其实就是上一节函数的精简版,去掉属性文件的创建,仅仅保留创建和注销操作。第一个函数是bus.c,加载模块会创建了一条名叫usb的总线,总线目录放在/sys/bus/目录下:/*8th_devModule_2/1st/bus.c*/6 s
2016-09-21 11:20:56 291
原创 (八)1 总线、设备和驱动
一、sysfs文件系统设备模型是2.6内核新引入的特征。设备模型提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构。在2.4内核中,设备的信息放在/proc中。而在2.6内核,内核把设备相关的信息归类在新增加sysfs文件系统,并将它挂载到/sys目录中,把设备信息归类的同时,让用户可以通过用户空间访问。接下来简单介绍一些sys中
2016-09-21 11:18:44 267
原创 (七)2 内核定时器
一、定时器之前说过两类跟时间相关的内核结构。1、延时:通过忙等待或者睡眠机制实现延时。2、tasklet和工作队列,通过某种机制使工作推后执行,但不知道执行的具体时间。接下来要介绍的定时器,能够使工作在指定的时间点上执行,而且不需要使用忙等待这类的延时方法。通过定义一个定时器,告之内核在哪个时间需要执行什么函数就可以了,等时间一到,内核会就执行指定的函数
2016-09-21 11:16:01 154
原创 (七)1 时间管理与内核延时
一、内核时间的相关概念墙上时钟:也就是实际时间。系统时间:自系统启动开始所经过的时间。时钟中断:内核会周期性的产生时钟中断,在中断处理函数中执行一些与时间相关的操作,如更新时间,进程调度,检查时间片等。节拍率:在linux内核中,通过编程定义节拍率,也就是HZ。每1/HZ秒发生一次时钟中断。在ARM中,节拍率被定义为1
2016-09-21 11:12:59 267
原创 (六)3中断下半部之工作队列
1、工作队列的使用按惯例,在介绍工作队列如何实现之前,先说说如何使用工作队列实现下半部。步骤一、定义并初始化工作队列:创建工作队列函数:struct workqueue_struct *create_workqueue(const char *name)函数传参是内核中工作队列的名称,返回值是workqueue_struc
2016-09-21 11:10:49 245
原创 (六)3中断下半部之tasklet
一、什么是下半部中断是一个很霸道的东西,处理器一旦接收到中断,就会打断正在执行的代码,调用中断处理函数。如果在中断处理函数中没有禁止中断,该中断处理函数执行过程中仍有可能被其他中断打断。出于这样的原因,大家都希望中断处理函数执行得越快越好。另外,中断上下文中不能阻塞,这也限制了中断上下文中能干的事。基于上面的原因,内核将整个的中断处理流程分为了上半部和下半部。上
2016-09-21 11:08:23 241
原创 (六)2 分享中断号
上一节介绍的内容是,调用接口request_irq(),使中断号与中断处理函数对应。但是,有时候会有这样的情况,如果开发板上按键的中断已经被另外的驱动程序注册中断了,而我现在又想再注册一次这个中断,这就出现了一个中断号不止对应一个中断函数的情况。注意,这里与硬件上的共享中断不一样,这里是指,当一个中断信号来了,基于操作系统,一个中断的到来可以调用多个中断处理程序,与硬件无关。接下来从错误的
2016-09-20 19:50:16 287
原创 (六)1 中断的实现
一、什么是中断中断分两种:1)中断,又叫外部中断或异步中断,它的产生是由于外设向处理器发出中断请求。其中外部中断也有两种,这是由配置寄存器设定的:普通中断请求(IRQ)和快速中断请求(FIQ)。一般地,linux下很少使用快速中断请求。2)异常,又叫内部中断或同步中断,它的产生是由于处理器执行指令出错。在以下的内容我是要介绍由于外部设备产生的中断。
2016-09-20 19:46:17 717
原创 (五)4 写个简单的LED驱动
一、实现硬件操作函数一般的,我写驱动的时候,我会先确定一些基本的硬件操作函数能够使用。如LED驱动我要实现三个操作:配置、开灯和关灯,所以我先要实现这几个硬件操作函数。其实这些在我介绍IO内存时已经实现了(5th_mm_2/3rd/test.c),我只是稍作了一点修改,改了一下内存的数据类型,其实没什么大出入。/*5th_mm_4/1st/test.c*/
2016-09-20 19:43:59 1150
原创 (五)3 IO静态映射
一、静态IO是怎么建立的Io静态映射发生在内核启动的时候,接下来通过内核源代码来分析,如果你的开发板是mini2440或者时候mini2440的内核配置文件,可以跟着我同样修改。注意:我的开发板只是使用mini2440的配置文件,外围电路跟mini2440不一样。注:以下代码在内核目录linux-2.6.29/arch/arm/mach-s3c2440/ma
2016-09-20 19:41:40 410
原创 (五)2 操作硬件——IO内存
一、IO端口与IO内存介绍之前可以看看以下的博客:http://blogold.chinaunix.net/u2/66435/showart_2137870.htmlx86体系和ARM体系的寻址方式是有差别的:在x86下,为了能够满足CPU高速地运行,内存与CPU之间通过北桥相连并通过地址方式访问,而外设通过南桥与CPU相连并通过端口访问。在
2016-09-20 19:39:40 285
原创 (五)1在内核空间分配内存
一、内核空间和用户空间有什么不同学c语言的时候应该学过,从用户空间看,每个进程都傻乎乎的以为自己有4G的内存空间,其中位于高地址(3G-4G)的1G空间给内核用,另外的3G(0-3G)都是它一个人独占的。所以用户空间很慷慨的把3G的空间分了好几个区域,如堆、栈、代码段等。其中,malloc()分配的空间位于堆,而程序中的自动变量,如你在函数内定义的“int i”,它是放在栈
2016-09-20 19:37:26 485
原创 (四)5多处理器下的竞态和并发
一、多处理器抢占式内核的内核同步需要防什么1)防内核抢占。2)防中断打断。3)防其他处理器也来插一脚。所以,在上一节讲的防抢占和防中断,接下来的内容实在这两个的基础上说一下如何防其他处理器。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2016-09-20 19:34:01 383
原创 (四)4单CPU下竞态和并发
一、什么是并发所谓并发,就是多个进程同时、并行执行。在单处理器的情况下,并发只是宏观上的,用户会感觉多个程序共同执行,其实只不过是多个进程轮流占用处理器运行,只有在多处理器的情况下才会实现真正的同时执行。但是,不管单处理器还是多处理器,内核中的并发都会引起共享资源的并发访问。举个简单的例子,有两个相同代码的进程并发执行,它们都是要修改存在与内核中个一个数据data。
2016-09-20 19:30:46 655
原创 (四)3抢占和上下文切换
一、什么是上下文切换上下文切换,是指从一个可执行的进程切换到另外一个可执行的进程。在linux内核中,上下文的切换有两种方式:第一种是进程主动让出CPU,这样的操作成为“让步”。第二种是由内核调度程序决定进程运行时间,在在运行时间结束(如时间片耗尽)或者需要切换高优先级进程时强制挂起进程,这样的操作叫“抢占”。抢占是我一直误解的概念,我一直以为抢占是一个进程强制切换到另
2016-09-20 19:28:51 563
原创 (四)2进程调度的相关概念
一、I/O消耗型进程和处理器消耗型的进程进程分为I/O消耗型和处理器消耗型两种。I/O消耗型,是指进程大部分时间用来提交I/O请求或者等待I/O请求的进程。这类进程的特征是,经常需要运行,但执行一次需要的时间不长。如文字编辑。处理器消耗型,是指进程大部分时间用来执行代码的进程。这类进程对系统的响应时间要求比较少,像看个视频,慢个半秒人是察觉不出来的。
2016-09-20 19:27:14 257
原创 (四)1进程管理的相关概念
一、什么是进程简单的说,进程就是正在运行的程序,一个程序可以同时有多个进程。学过C语言都知道,程序运行时并不是只有代码,还包含其他的资源,如打开的文件,信号,全局变量等等。我在《操作系统原理》中看过一个很生动很深刻的例子:一个人对照着菜谱做菜。在这例子中,人就是内核,菜谱就是程序,做菜的过程就是进程,而菜、锅就是这个进程的资源。内核为线程提供了两种技术:虚拟处理器和虚拟
2016-09-20 19:25:53 229
原创 (三)7异步通知fasync
一、什么是异步通知个人认为,异步通知类似于中断的机制,如下面的将要举例的程序,当设备可写时,设备驱动函数发送一个信号给内核,告知内核有数据可读,在条件不满足之前,并不会造成阻塞。而不像之前学的阻塞型IO和poll,它们是调用函数进去检查,条件不满足时还会造成阻塞。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2016-09-20 19:23:51 257
原创 (三)6 poll和sellct
一、系统调用select的简介简单来说,select这个系统调用的作用就是在应用层调用驱动函数中的poll来检测指定的文件的状态(读、写和异常)。如果某个状态满足,select函数调用成功后返回,应用程序就可以通过指定的函数来判断现在的文件状态。注意的是:select可以指定判断的时间,指定时间内,应用程序会阻塞在select函数,直到状态满足或者超时。xx
2016-09-20 19:22:03 368
原创 (三)5阻塞型IO实现
一、休眠简介进程休眠,简单的说就是正在运行的进程让出CPU。休眠的进程会被内核搁置在在一边,只有当内核再次把休眠的进程唤醒,进程才会会重新在CPU运行。这是内核中的进程调度,以后的章节会介绍。现在应该先知道这样的一个概念,一个CPU在同一时间只能有一个进程在运行,在宏观上,我们觉得是所有进程同时进行的。实际上并不是这样,内核给每个进程分配了4G的虚拟内存,并且让每个进程
2016-09-20 19:19:39 431
原创 (三)4.ioctl的实现
一、ioctl的简介: 虽然在文件操作结构体"struct file_operations"中有很多对应的设备操作函数,但是有些命令是实在找不到对应的操作函数。如CD-ROM的驱动,想要一个弹出光驱的操作,这种操作并不是所有的字符设备都需要的,所以文件操作结构体也不会有对应的函数操作。出于这样的原因,ioctl就有它的用处了————一些没办法归类的函数就统一放在io
2016-09-20 19:17:47 348
原创 (三)3面向对象思想和lseek
一、结构体struct file和struct inode在之前写的函数,全部是定义了一些零散的全局变量。有没有办法整合成到一个结构体当中?这样的话,看起来和用起来都比较方便。接下来就要说这方面的问题。不过先要介绍一下除了fops以外的两个比较重要的结构体:1)struct file在内核中,file结构体是用来维护打开的文件的。
2016-09-20 19:14:51 322
原创 (三)2.字符型设备的操作open、close、read、write
一、文件操作结构体file_operations继续上次没讲完的问题,文件操作结构体到底是什么东西,为什么我注册了设备之后什么现象都没有?可以验证文件操作结构体的内容。file_operations是一个函数指针的集合,用于存放我们定义的用于操作设备的函数的指针,如果我们不定义,它默认保留为NULL。来个文件操作结构体的定义:/*includ
2016-09-20 19:10:30 670
原创 (三)1字符型设备之设备申请
一、驱动的分类:内核驱动大致分为三类:1)字符设备:在今后的接触的大多数都是字符设备,我也只学过这个。2)块设备 :与硬盘相关的设备。3)网络设备:与网络相关的设备。上面的三种设备,我也只是学习过字符设备,所以对后面的两种也没有太多的归纳。稍稍说一下字符设备与块设备之间的区别:1)传输数据大小:字符设备以字节方式进行存
2016-09-20 19:08:34 808
原创 (二):模块相关的基础概念
一、初探linux内核模块内核模块:内核本身是很庞大的一个结构,需要的组件很多。编译内核时,用户 可以把所有的代码编译进内核,但是这样会引起两个问题:一是内核过大;二是 当需要添加或者删除内核时,需要重新再编译内核。所以有了内核模块的概念。 模块并不编译到内核中,编译后存放在指定的目录,当需要使用时动态加载。1.1下面是一个非常经典的hello world代码:
2016-09-20 19:05:14 342
原创 (一)内核相关的基础概念
一.linux设备驱动的作用内核:用于管理软硬件资源,并提供运行环境。如分配4G虚拟空间等。linux设备驱动:是连接硬件和内核之间的桥梁。linux系统按个人理解可按下划分:应用层:包括POSIX接口,LIBC,图形库等,用于给用户提供访问 内核的接口。属于用户态,ARM运行在用户模式(usr)或 者系统模式(sys)下。内核层:应用程序调
2016-09-20 18:57:01 643
转载 linux驱动中platform设备驱动模型
platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver。Linux 2.6的设备驱动模型中,把I2C、RTC、LCD等都归纳为platform_device。总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。Linux2.6
2016-09-14 11:16:59 352 1
转载 MISC混杂设备 struct miscdevice /misc_register()/misc_deregister()
在Linux系统中,存在一类字符设备,他们共享一个主设备号(10),但此设备号不同,我们称这类设备为混杂设备(miscdeivce),查看/proc/device中可以看到一个名为misc的主设备号为10.所有的混杂设备形成一个链表,对设备访问时内核根据次设备号找到对应的miscdevice设备。相对于普通字符设备驱动,它不需要自己去生成设备文件。Linux内核使用struct miscd
2016-09-13 16:28:47 170
原创 PV原语
在计算机操作系统中,PV操作是进程管理中的难点。首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下: P(S):①将信号量S的值减1,即S=S-1; ②如果S³0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。 V(S):①将信号量S的值加1,即S=S+1;
2016-09-12 19:52:16 1106
原创 linux中直接内存访问(DMA)
1. 什么是DMA直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的I/O数据,而不需要系统处理器的参与。使用这种机制可以大大提高与设备通信的吞吐量。 2. DMA数据传输有两种方式引发数据传输:第一种情况:软件对数据的请求1. 当进程调用read,驱动程序函数分配一个DMA缓冲区,并让硬件将数据传输到这个缓冲区中。进程处于睡眠状态。2. 硬件将数据写
2016-09-11 20:54:30 2196
原创 linux中的物理地址,虚拟地址,总线地址的区别
1 逻辑地址《understanding the linux kernel》上的解释是与虚拟地址相关,基于硬件MMU与软件内存管理的一个概念,具体可以看UTLK的第二章内存寻址,有很详细的解释。但是工作中之前用到的MIPS架构的处理器的解释却有出入,在《MIPS体系架构透视》一书中,逻辑地址是跟MMU无关的,MIPS地址空间划分中,Kseg0 Kseg1地址空间与真实的
2016-09-11 09:59:31 3654 1
转载 Linux设备模型firmware(固件)
硬件越来越复杂,硬件的许多功能使用了程序实现,与直接硬件实现相比,固件拥有处理复杂事物的灵活性和便于升级、维护等优点。固件(firmware)就是这样的一段在设备硬件自身中执行的程序,通过固件标准驱动程序才能实现特定机器的操作,如:光驱、刻录机等都有内部的固件。固件一般存放在设备上的flash存储器中,但出于成本和灵活性考虑,许多设备都将固件的映像(image)以文件的形式存放在硬盘中,设备驱
2016-09-10 19:46:35 4971
Detection and Identification of Cyclostationary Signals
2016-03-30
糗百桌面版
2016-05-11
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人