内核
文章平均质量分 62
android linux内核笔记
杨斌并
这个作者很懒,什么都没留下…
展开
-
linux中的等待队列-51
linux中的等待队列等待队列的原理和运行过程休眠和唤醒的基本原理是当驱动程序等待某种事件发生时会进入休眠状态,当该事件发生后,就会唤醒休眠状态的驱动代码。这就相当于A和B两台电子设备在做两种不同的工作,但必须B做完后A才能做。最好的方法是A先关机或进入低功耗状态,等B做完后再打开或唤醒A。这样A不仅避免消耗不必要的电能,而且又保证了工作的时序性,否则A就得在B工作时一直运转,而且帮不了B任何忙,只能在那消耗不必要的能量。等待队列工作的过程就是休眠和唤醒的过程。当系统检测到某件事还没做完,就会原创 2021-07-19 11:30:17 · 197 阅读 · 2 评论 -
linux驱动程序中的并发控制-8(完成量(completion))-50
完成量(completion)完成量用于一个执行单元等待另一个执行单元执行完成某项工作。也就是说,如果在执行某段代码之前必须要执行另一段代码,就要使用完成量。完成量(completion)使用定义完成量结构体(#include <linux/completion.h>)static struct completion my_completion;struct completion { unsigned int done; wait_queue_head_t wai原创 2021-07-15 11:47:05 · 324 阅读 · 1 评论 -
linux驱动程序中的并发控制-7(互斥体(mutex))-49
互斥体(mutex)互斥体(mutex)使用定义互斥体(#include <linux/mutex.h>)结构体struct mutex { /* 1: unlocked, 0: locked, negative: locked, possible waiters */ atomic_t count; spinlock_t wait_lock; struct list_head wait_list;#if defined(CONFIG_DEBUG_MUTEXES)原创 2021-07-15 11:14:36 · 429 阅读 · 0 评论 -
linux驱动程序中的并发控制-6(读写信号量)-48
读写信号量读写信号量和信号量的关系与读写自旋锁和自旋锁的关系类似。读信号量和写信号量是互斥的,但允许N个读执行单元同时访问共享资源(同时获取读信号量),而最多只允许有一个写单元获取写信号量。读写信号量相对于信号量更宽松,对于读多写少的情况会明显提高程序的执行效率。读写信号量的使用定义和初始化读写信号量rw_semaphore 结构体(#include <linux/rwsem.h>)struct rw_semaphore { long count; struc原创 2021-07-15 10:38:18 · 236 阅读 · 0 评论 -
linux驱动程序中的并发控制-5(信号量(semaphore))-47
信号量(semaphore)信号量是用于保护临界区的一种常用方法,它的使用方式与自旋锁类似。与自旋锁相同,只有得到信号量的进程才能执行临界区代码。但与自旋锁不同的是,在未获取信号量时,进程不会像自旋锁-样原地打转,而是进入休眠等待状态。因此当信号量阻塞时消耗的系统资源(主要是CPU资源)并不多,也不会出现死机的现象。信号量的使用定义信号量(#include <linux/semaphore.h>)struct semaphore sem;初始化信号量sema_i原创 2021-07-14 19:57:16 · 273 阅读 · 0 评论 -
linux驱动程序中的并发控制-4(顺序自旋锁)-46
顺序自旋锁顺序锁与读写自旋锁类似,只是为写锁赋予了更高的权限。在读写自旋锁中,读锁和写锁的优先级是相同的。当读锁获取读自旋锁时,写锁必须等待,直到临界区的代码执行完成,并释放读自旋锁为止,反之亦然。顺序锁在获取读锁的时候,仍然可以获取写锁,并继续执行写临界区中的代码。也就是说,写锁永远不会被读锁阻塞(当然,写锁仍然可以被写锁阻塞)。顺序锁需要定义seqlock_ t 变量。seqlock t结构体的代码如下(从seqlock_ _t 结构体的代码可以看出,顺序锁是通过自旋锁扩展而来的):#原创 2021-07-13 20:13:28 · 211 阅读 · 1 评论 -
linux驱动程序中的并发控制-3(读写自旋锁)-45
读写自旋锁自旋锁不管读写,都只允许同时只有一个执行单元可以获取自旋锁,即便有多个单元同时读取临界区资源也会被锁住。读写自旋锁,将临界区的读写操作分开,多个执行单元可以同时获取一个读自旋锁,但是只能获取一个写自旋锁如果某个执行单元已经获取了一个读自旋锁,那么在获取写自旋锁时就是自旋等待读自旋锁的释放,读写不能同时进行读写自旋锁的使用定义读写自旋锁rwlock_t lock;rwlock_t 结构体 在头文件 #include<linux/rwlock.h>中typ原创 2021-07-12 16:12:31 · 286 阅读 · 1 评论 -
linux驱动程序中的并发控制-2(自旋锁)-44
自旋锁(spin lock)简介原子锁和自旋锁的使用范围原子操作是一种很好的避免竞态的方式,使用非常简单。但在某些方面却显得过于简单。例如,有很多数据需要被格式化,被添加到某些数据结构中,然后被分析处理。而这些操作又都要求是原子的。这种情况使用控制原子操作的原则变量很难处理或根本无法处理。因此,处理更复杂的并发和竞态就要使用自旋锁。自旋锁特点自旋锁从本质上讲就是保证代码段(也称为临界区)的操作是原子的。也就是说,如果要保证某段代码在执行期间不会被打断(原子操作),就要在代码段执行之前申请自旋锁原创 2021-07-08 16:18:34 · 239 阅读 · 0 评论 -
linux驱动程序中的并发控制-1(原子操作)-43
原子操作整型的原子操作使对整型的int 的操作变成原子操作,要依靠一个数据类型:atomic_t。此结构体定义在 include/linux/types.h 文件中,定义如下:typedef struct { int counter;} atomic_t;相关的api#include<asm/atomic.h>函数描述ATOMIC_INIT(int i)定义原子变量的时候初始化int atomic_read(atomic_t *v)读取原子原创 2021-07-07 15:48:11 · 135 阅读 · 0 评论 -
app,控制led 代码-42
在内核中可以找到led的设备树 /* itop_led { compatible = "itop_led"; pinctrl-names = "default"; pinctrl-0 = <&led1_ctl>; gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; status = "okay"; };*/将上面的代码注释掉,添加自.原创 2021-06-16 14:16:54 · 294 阅读 · 1 评论 -
tslib触摸校准实验-41
tslib触摸校准实验 ft5x06触摸驱动添加成功后,发现触摸可能不太准确,这时可以使用一个第三方开源库tslib来调试触摸屏。下面来看一下 tslib源码如何移植。tslib源码可以从官方地址获取: https://github.com/libts/tslib ,打开网址可以看到最新的版本是1.21。可以从官网获取,也可以从网盘资料中获取获取到 tslib源码后,拷贝到Ubuntu系统下并解压,得到 tslib-1.21文件夹。编译tslibl获取到tslib源码后,可以编译tslib源原创 2021-06-16 14:16:07 · 334 阅读 · 0 评论 -
2021-06-16FT5X06触摸实验-40
FT5X06触摸实验安装完以下ft5x06触摸驱动会打印一下内容,说明驱动编写成功[12727.015690] ft5x06_driver_init[12727.015821] this is ft5x06_probe ft5x06_device_node is ft5x06[12727.015963] ft5x06_irp_gpio is 52[12727.015973] ft5x06_reset_gpio is 41[12727.027780] input: ft5x06_input原创 2021-06-16 14:15:34 · 265 阅读 · 0 评论 -
驱动程序实现i2c通讯-39
驱动程序实现i2c通讯i2c对寄存器的读写 在 I2C 设备驱动中首先要完成 i2c_driver 结构体的创建、初始化和注册,当设备和驱动匹配成功后,就会执行 probe 函数,probe 函数中就是执行字符设备驱动的一套流程。 一般需要在 probe 函数里面初始化 I2C 设备,要初始化 I2C 设备就必须能够对 I2C 设备寄存器进行读写操作,这里就要用到 i2c_transfer 函数了。i2c_transfer 函数最终会调用 I2C 适配器中 i2c_algorithm 里面的原创 2021-06-16 14:14:46 · 820 阅读 · 0 评论 -
i2c总线实现driver驱动-38
i2c总线实现driver驱动然后我们再来看driver部分。不管是使用设备树还是非设备树,driver部分就比较复杂了。和注册一个杂项设备或者是字符设备的套路一样,我们也是要先定一个一个i2c_driver的结构体,然后在对他进行初始化,我们来看一下这个结构体的定义,如下图所示:;struct i2c_driver { unsigned int class; /* Notifies the driver that a new bus has appeared. You should avoid原创 2021-06-16 14:08:14 · 447 阅读 · 0 评论 -
i2c总线实现client设备(2)-37
i2c总线实现client设备Linux l2C 驱动框架简介Linux中的I2C也是按照平台总线模型设计的,既然也是按照平台总线模型设计的,是不是也分为一个device和一个driver呢?但是I2C这里的 device在讲 platform 的时候就说过, platform是虚拟出来的一条总线;目的是为了实现总线、设备、驱动框架。对于I2C而言,不需要虚拟出一条总线,直接使用I2C总线即可。同样,我们也是先从非设备树开始,先来看一下,在没有设备树之前我们是怎么实现的i2C的device 部分原创 2021-06-16 14:07:21 · 672 阅读 · 0 评论 -
应用层实现i2c通信 - 36
i2c总线实现client设备Linux l2C 驱动框架简介Linux中的I2C也是按照平台总线模型设计的,既然也是按照平台总线模型设计的,是不是也分为一个device和一个driver呢?但是I2C这里的 device在讲 platform 的时候就说过, platform是虚拟出来的一条总线;目的是为了实现总线、设备、驱动框架。对于I2C而言,不需要虚拟出一条总线,直接使用I2C总线即可。同样,我们也是先从非设备树开始,先来看一下,在没有设备树之前我们是怎么实现的i2C的device 部分原创 2021-06-16 14:06:43 · 606 阅读 · 0 评论 -
输入子系统(二)-35
输入子系统(二)使用输入子系统设计按键驱动我们可以将开发板上的按键值设置为input.h文件里面的宏定义的任意一个,比如我们本次实验将开发板_上的KEY按键值设置为KEY__0在编写input设备驱动的时候我们需要先申请一个input dev结构体变量,使用input allocate device 函数来申请一个input dev.此函数原型如下所示:struct input dev *input_allocate_device(void)函数参数和返回值含义如下:参数:无。返原创 2021-06-16 14:06:04 · 315 阅读 · 0 评论 -
输入子系统(一)-34
输入子系统(一)什么是输入子系统?输入子系统是Linux专门做的一套框架来处理输入事件的,像鼠标,键盘,触摸屏这些都输入设备。但是这些输入设备的类型又都不是一样的,所以为了统一这些输入设备驱动标准应运而生的。统一了以后,在节点/dev/input下面则匙我们输入设备的节点,如下图所示:root@ubuntu:~# ls /dev/input/by-id by-path evento event1event2event3micemouseonouse1这些节点对应的则是我们当前系统的输入设备,原创 2021-06-16 14:05:16 · 186 阅读 · 0 评论 -
触屏消抖实验-33
代码test.c#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <l原创 2021-06-16 14:04:26 · 165 阅读 · 0 评论 -
内核定时器 -32
内核定时器Linux内核定时器概念 不同于单片机定时器,Linux内核定时器是一种基于未来时间点的计时方式,以当前时刻为启动的时间点,以未来的某一时刻为终止点。比如,现在是10点5分,我要定时5分钟,那么定时就是10点5分+5分钟=10点10分。这个和咱们的手机闹钟很类似。比如你要定一个第二天早晨的8点的闹钟,就是当前时间定时到第二天早晨8点。 需要注意的是,内核定时器定时精度不高,不能作为高精度定时器使用。并且内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那原创 2021-06-15 10:28:23 · 123 阅读 · 0 评论 -
工作队列-31
工作队列工作队列的基础概念什么是工作队列?工作队列(workqueue)是实现中断下文的机制之一,是一种将工作推后执行的形式。那工作队列和我们tasklet,机制的不同点tasklet 也是实现中断下文的机制。他们俩个最主要的区别是tasklet,不能休眠,而工作队列是可以休眠的。所以,tasklet可以用来处理比较耗时间的事情,而工作队列可以处理非常复杂并且更耗时间的事情。工作队列(workqueue)的工作原理 Linux系统在启动期间会创建内核线程,该线程创建以后就处于sleep状态原创 2021-06-15 10:27:42 · 214 阅读 · 1 评论 -
等待队列-30
等待队列阻塞与非阻塞的概念阻塞:当前设备如果不可读或不可写时,也就是不能获得资源的时候,那么当前进程程会被挂起。只有当设备满足条件的时候才可以返回。默认情况下,文件都是以这种方式打开。非阻塞:当前设备不可读或不可写时,该函数不会阻塞当前进程,要么放弃,要么不停的查询,或者直到可以操作为止。读写函数是否阻塞可以通过参数来指定:fd = open(filepath,O_RDWR);//默认阻塞打开fd = open(filepath,O_RDWR|O_NONBLOCK); //非阻塞方式打开原创 2021-06-15 10:26:59 · 112 阅读 · 0 评论 -
中断下文之tasklet -29
中断下文之tasklettasklet相关知识点什么是 tasklet?tasklet 是中断处理中断下文常用的一种方法,tasklet,是一种特殊的软中断。处理中断下文的机制还有工作队列和软中断。怎么使用tasklet来设计中断下文?中断发生 》》》》 中断上文,在中断处理一些紧急的事情 》》》》 调用tasklet 》》》》 中文下文,在中断下文做比较耗时的事情 Linux把中断分成俩个部分,一个是上半部分,一个是下半部分,在上半部分我们只处理紧急的事情,同时可以调用t原创 2021-06-15 10:26:19 · 173 阅读 · 0 评论 -
设备树中的中断节点以及相关函数-28
设备树中的中断节点以及相关函数设备树中的中断节点。 如果一个设备需要用到中断功能,开发人员就需要在设备树中配置好中断属性信息,因为设备树是用来描述硬件信息的,然后Linux内核通过设备树配置的中断属性来配置中断功能。设备树中断的参考绑定文档:Documentation/devicetree/bindings/arm/gic.txt 中断实际上是非常复杂的,但是作为开发人员,我们只需要关系怎么在设备树中指定中断,怎么在代码中获得中断就可以。其他的事情,比如设备树中的中断控制器,这些都是由原原创 2021-06-15 10:25:35 · 1710 阅读 · 0 评论 -
中断基础概念-27
中断基础概念中断概念CPU在正常运行期间,由外部或者内部引起的事件,让CPU停下当前正在运行的程序,转而去执行触发他的中断所对应的程序,这个就是中断。|举例:我现在正在厨房做饭,突然电话响了,然后我关火去接电话,接完电话在回去开火继续做饭,这个过程就是中断的一个过程。在这个看似简单的过程中,却涉及到了中断的几个过程,我们一起来看一下:电话铃声响了:中断请求我要去接电话:中断响应我关掉火:保护现场我接电话的过程:中断处理接完电话回到厨房开火:恢复现场继续做饭:中断返回如果我不接电话:原创 2021-06-15 10:24:47 · 182 阅读 · 0 评论 -
ioctl接口(二) -26
ioctl接口(二)unlocked_ioctl与compat_ioctl的区别最近在调试驱动的时候遇到这个问题,在这里记录一下。在做测试驱动的时候是这样写法的,但将驱动加载之后驱动进不去myioctl里面struct file_operations fops = { .owner = THIS_MODULE, .compat_ioctl = myioctl,};然后file一下我的用户程序,发现用户程序是32位的,于是找到网上相关信息,修改成如下,就可以正常进到myioctl原创 2021-06-15 10:24:09 · 129 阅读 · 0 评论 -
ioctl接口(一) -25
ioctl接口(一)unlocked_ipctl接口什么是unlocked_ioctl 接口?unlocked_ioctl 实际上就是ioctl接口,但是功能和对应的系统调用均没有发生变化。unlocked_ioctl和read/write函数有什么相同点和不同点?相同点:都可以往内核中写数据。不同点:read函数只能完成读的功能,write 函数只能完成写的功能。但是read和write 在读写大数据时效率比较高 ioctl既可以读也可以写。读取大数据效率不是很高。un原创 2021-06-15 10:23:24 · 320 阅读 · 1 评论 -
pinctl和gpio子系统(三)-24
pinctl和gpio子系统(三)以rk3399为例设备树//在根节点中添加test1: test { #address-cells = <1>; #size-cells = <1>; compatible = "test"; reg = <0xff790000 0x00000004>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_beep>; test-bee原创 2021-06-11 11:19:29 · 152 阅读 · 2 评论 -
pinctl和gpio子系统(二)-23
pinctl和gpio子系统(二) Linux内核提供了pinctrl子系统和 gpio子系统用于GPIO驱动,当然 pinctrl子系统负责的就不仅仅是 GPIO 的驱动了而是所有 pin脚的配置。pinctrl子系统是随着设备树的加入而加入的,依赖于设备树。GPIO子系统在之前的内核中也是存在的,但是 pinctrl子系统的加入GPIO子系统也是有很大的改变。 在以前的内核版本中,如果要配置GPIO 的话一般要使用SOC厂家实现的配置函数,例如三星的配置函s3c_gp原创 2021-06-11 11:17:25 · 151 阅读 · 0 评论 -
pinctl和gpio子系统(一)-22
pinctl和gpio子系统(一)什么是pinctrl和gpio子系统?前面编写的基于设备树的 LED 驱动,本质上还是配置 LED 使用的 GPIO 寄存器,驱动开发方式和裸机基本没区别。Linux 内核提供了 pinctrl 和 gpio 子系统用于 GPIO 驱动,借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。Linux Pinctrl子系统提供的功能是什么?管理系统中所有的可以控制的pin,在系统初始化的时候,枚举所有可以控制的pin,并标识这些pin。管理这些p原创 2021-06-11 11:16:11 · 250 阅读 · 1 评论 -
设备树下的platform总线-21
设备树下的platform总线of _iomap 函数作用:of iomap函数用于直接内存映射,以前我们会通过ioremap函数来完成物理地址到虚拟地址的映射。函数原型:#include <linux/of_address.h>void iomem *of_iomap(struct device_node *np,int index)参数:np:设备节点。index: reg属性中要完成内存映射的段,如果reg属性只有一段的话index就设置0。返回值:经过内存映射后的虚拟原创 2021-06-11 11:14:58 · 324 阅读 · 2 评论 -
设备树中常用的of操作函数-20
设备树中常用的of操作函数设备都是以节点的形式“挂”到设备树上的,因此要想获取这个设备的其他属性信息,必须先获取到这个设备的节点。Linux内核使用device_node结构体来描述一个节点,此结构体定义在文件include/linux/of.h中,定义如下struct device_node { const char *name;/*节点名字*/I const char *type; *设备类型*/ phandle phandle; const char*full_name;/*节点全名原创 2021-06-11 11:14:05 · 1177 阅读 · 3 评论 -
在设备树中添加自定义的节点-19
在设备树中添加自定义的节点在rk3399中,设备树的节点在Z:\itop-3399_8.1\kernel\arch\arm64\boot\dts\rockchip\rk3399.dtsi编辑rk3399.dtsitest1: test { #address-cells = <1>; #size-cells = <1>; compatible = "test"; reg = <0x20ac000 0x0000004>; status = "o原创 2021-06-10 10:56:09 · 814 阅读 · 0 评论 -
设备树基本语法-18
设备树基本语法设备树基本框架设备树从根节点开始,每个设备都是一个节点。节点和节点之间可以互相嵌套,形成父子关系设备的属性用key-value对{键值对)来描述,每个属性用分号结束设备树语法节点什么是节点呢?节点就好比一颗大树,从树的主干开始,然后有一节一节的树枝,这个就叫节点。在代码中的节点是什么样子的呢。我们把上面模板中的根节点摘出来,如下图所示,这个就是根节点。相当于大树的树干。/{}://分号而树枝就相当于设备树的子节点,同样我们把子节点摘出来就是根节点里面的node1和n原创 2021-06-10 10:55:02 · 226 阅读 · 0 评论 -
设备树基本概念-17
设备树基本概念什么是设备树?设备树是一种描述硬件资源的数据结构。它通过 bootloader将硬件资源传给内核,使得内核和硬件资源描述相对独立。I有了初步概念之后,我们再来一起探讨设备树的起源。设备树的由来Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没原创 2021-06-10 10:53:11 · 346 阅读 · 0 评论 -
平台总线probe函数的编写-16
平台总线probe函数的编写编写probe函数的思路:从device.c里面获得硬件资源方式一:直接获得,不推荐方法二:只用函数获得#include <linux/platform_device.h>extern struct resource *platform_get_resource(struct platform_device *,unsigned int, unsigned int);参数第一个platform_device 指针第二个是类型 resource原创 2021-06-10 10:41:49 · 334 阅读 · 0 评论 -
注册platform驱动-15
注册platform驱动编写driver.c 的思路首先定义一个platform_driver结构体变量,然后去实现结构体中的各个成员变量,那么当我们的driver和device 匹配成功的时候,就会执行 probe函数,所以匹配成功以后的重点就在于probe函数的编写。struct platform_driver { //当driver和device匹配成功的时候,就会执行probe函数 int (*probe)(struct platform_device *); //当driver和dev原创 2021-06-10 10:40:24 · 181 阅读 · 0 评论 -
注册Platform设备-14
注册Platform设备平台总线注册一个devicedevice.c里面写的是硬件资源,这里的硬件资源是指寄存器的地址,中断号,时钟等硬件资源。在Linux内核里面,我们是用一个结构体来描述硬件资源的。#include <linux/platform_device.h>struct platform_device { //设备id,一般写-1 int id; //平台总线进行匹配的时候用到的name,/sys/bus/platform/devices/name const原创 2021-06-10 10:38:20 · 250 阅读 · 0 评论 -
平台总线模型-13
平台总线模型什么是平台总线模型?平台总线模型也叫platform总线模型。是Linux内核虚拟出来的一条总线,不是真实的导线。平台总线模型就是把原来的驱动C文件给分成了俩个C文件,一个是device.c,一个是driver.c把稳定不变的放在driver.c里面,需要变得就放在了device.c里面。为什么会有平台总线模型?可以提高代码的重用性减少重复性代码。device.c 设备总线驱动 driver.c平台总线模型的优点。可以提高代码的重用性减少重复性代码。de原创 2021-06-09 11:29:06 · 129 阅读 · 0 评论 -
自动创建设备节点-12
自动创建设备节点怎么自动创建一个设备节点?在嵌入式 Linux中使用mdev来实现设备节点文件的自动创建和删除。什么是mdev?mdev是 udev 的简化版本,是busybox中所带的程序,最适合用在嵌入式系统。什么是udev?udev是一种工具,它能够根据系统中的代设答的状杏更奇备艺计件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。udev一般用在此上的 linux中,相对 mdev来说要复杂些。怎么自动创建设备原创 2021-06-09 10:50:35 · 261 阅读 · 0 评论