Linux 的同步机制不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随Linux从单处理器到对称多处理器的过渡;
我们知道外设访问内存需要通过DMA进行数据搬移,关于cpu, cache, device, dma, memory的关系可以通过下图说明:
资料中,难免会有一些错误,有任何问题,都可以在github向我提交issue。文中的勘误,我都会更新在github中。点击阅读原文可以直达github。
工业场合里面也有大量的模拟量和数字量之间的转换,也就是我们常说的 ADC 和 DAC。而且随着手机、物联网、工业物联网和可穿戴设备的爆发,传感器的需求只持续增强。比如手机或者手环里面的加速度计、光传感器、陀螺仪、气压计、磁力计等,这些传感器本质上都是ADC,大家注意查看这些传感器的手册,会发现他们内部都会有个 ADC,传感器对外提供 IIC或者 SPI 接口,SOC 可以通过 IIC 或者 SPI 接口来获取到传感器内部的 ADC 数值,从而得到想要测量的结果。Linux 内核为了管理这些日益增多的 ADC 类传感器,特地推出了 IIO 子系统,我们学习如何使用 IIO 子系统来编写 ADC 类传感器驱动。
1、字符设备驱动: 当我们的应用层读写(read()/write())字符设备驱动时,是按字节/字符来读写数据的,期间没有任何缓存区,因为数据量小,不能随机读取数据,例如:按键、LED、鼠标、键盘等 2、块设备: 块设备是i/o设备中的一类, 当我们的应用层对该设备读写时,是按扇区大小来读写数据的,若读写的数据小于扇区的大小,就会需要缓存区, 可以随机读写设备的任意位置处的数据,例如 普通文件(.txt,.c等),硬盘,U盘,SD卡。 3、块设备结构: 段(Segments):由若干个块组成。是Linux内存管理机制中一个内存页或者内存页的一部分。 块 (Blocks): 由Linux制定对内核或文件系统等数据处理的基本单位。通常由1个或多个扇区组成。(对Linux操作系统而言) 扇区(Sectors):块设备的基本单位。通常在512字节到32768字节之间,默认512字节 应用程序进行文件的读写,通过文件系统将文件的读写转换为块设备驱动操作硬件。
Linux系统文件操作主要是通过块设备驱动来实现的。 块设备主要指的是用来存储数据的设备,类似于SD卡、U盘、Nor Flash、Nand Flash、机械硬盘和固态硬盘等。块设备驱动就是用来访问这些存储设备的,其与字符设备驱动不同的是:
移动设备的操作系统阵营之一的Android,底层基于Linux内核,中间为Native&Runtime层和Framework层。我们知道Linux本身有着很成熟的IPC(进程间通信)机制,比如管道、消息队列、共享内存、socket、信号和信号量等。然而,Android却使用Binder来作为它的IPC的方案,这是为何呢?接下来,就把我之前学习Binder的心得写下来。
互联网、Linux内核书籍上充满了各种关于Linux DMA ZONE和dma_alloc_coherent、dma_map_single等的各种讲解,由于很多童鞋缺乏自身独立的思考,人云亦云,对这些概念形成了很多错误的理解。本文的目的在于彻底澄清这些误解。
此类驱动适合于大多数简单的硬件设备。比如并口打印机,我们通过在/dev下建立一个设备文件(如/dev/printer)来访问它。
MemoryFile 是 Java 层对 Ashmem 的一个封装,下面来一起学习 MemoryFile,掌握它的使用姿势和底层原理。
指挥linux系统稳定运行的核心是linux内核。这个内核相当于linux系统的“大脑”,linux系统的就是在linux内核上发展起来的。linux高可用就是针对linux内核的。
2.进入目录:/lib/modules/3.13.0-24-generic/kernel/drivers/media/v4l2-core,运行:
端口(port)是接口电路中能被CPU直接访问的寄存器的地址。几乎每一种外设都是通过读写设备上的寄存器来进行的。CPU通过这些地址即端口向接口电路中的寄存器发送命令,读取状态和传送数据。外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。
有了前两节的学习相信读者已经知道CPU所有的操作都是建立在虚拟地址上处理(这里的虚拟地址分为内核态虚拟地址和用户态虚拟地址),CPU看到的内存管理都是对page的管理,接下来我们看一下用来管理page
有了前两节的学习相信读者已经知道CPU所有的操作都是建立在虚拟地址上处理(这里的虚拟地址分为内核态虚拟地址和用户态虚拟地址),CPU看到的内存管理都是对page的管理,接下来我们看一下用来管理page的经典算法--Buddy。
1)物理地址:CPU地址总线传来的地址,由硬件电路控制其具体含义。物理地址中很大一部分是留给内存条中的内存的,但也常被映射到其他存储器上(如显存、BIOS等)。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。
Kmalloc分配的是连续的物理地址空间。如果需要连续的物理页,可以使用此函数,这是内核中内存分配的常用方式,也是大多数情况下应该使用的内存分配方式。
转载请标明原址:linux驱动最新面试题(面试题整理,含答案)_不忘初心-CSDN博客_linux驱动面试题
我们知道,linux系统中用户空间和内核空间是隔离的,用户空间程序不能随意的访问内核空间数据,只能通过中断或者异常的方式进入内核态,一般情况下,我们使用copy_to_user和copy_from_user等内核api来实现用户空间和内核空间的数据拷贝,但是像显存这样的设备如果也采用这样的方式就显的效率非常底下,因为用户经常需要在屏幕上进行绘制,要消除这种复制的操作就需要应用程序直接能够访问显存,但是显存被映射到内核空间,应用程序是没有访问权限的,如果显存也能同时映射到用户空间那就不需要拷贝操作了,于是字符设备中提供了mmap接口,可以将内核空间映射的那块物理内存再次映射到用户空间,这样用户空间就可以直接访问不需要任何拷贝操作,这就是我们今天要说的0拷贝技术。
本文补充校正一些Linux内核开发者关于GFP_ATOMIC的认知不完整的地方,阐述GFP_ATOMIC与free内存watermark的关系,并明确什么时候应该用GFP_ATOMIC申请内存。目录:
内存是计算机系统最重要的资源之一,当操作系统内存不足时,进程申请内存将会失败,从而导致其运行异常或者崩溃。
在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置fb_info 3) 设置硬件相关的操作
主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。
这篇文章会先对照Binder机制与Linux的通信机制的区别,了解为什么Android会另起炉灶,採用Binder。接着,会依据Binder的机制,去理解什么是Service Manager,在C/S模型中扮演什么角色。最后,会从一次完整的通信活动中,去理解Binder通信的过程。
通过前面的文章我们已经了解了「数据包从HTTP层->TCP层->IP层->网卡->互联网->目的地服务器」这中间涉及的知识。
在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动。本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存。 下面就开始学习如何写一个简单的字符设备驱动。首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作。 1、主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的。他们通常位于/dev目录下。如下: xxx@ubuntu:~$ ls
本文主要分享一个Cache一致性踩内存问题的定位过程,涉及到的知识点包括:backtrace、内存分析、efence、wrap系统函数、硬件watchpoint、DMA、Cache一致性等。
如图所示,在海思平台上将内存分为两个部分:os内存和mmz内存。os内存指:由linux操作系统管理的内存;mmz内存:由mmz驱动模块进行管理供媒体业务单独使用的内存,在驱动加载时可以指定该模块管理内存的大小:
C/C++程序为编译后的二进制文件,运行时载入内存,运行时内存分布由代码段、初始化数据段、未初始化数据段、堆和栈构成,如果程序使用了内存映射文件(比如共享库、共享文件),那么包含映射段。Linux环境程序典型的内存布局如图1-5所示。
V4L2英文全称是Video for Linux2,它是专门为视频设备设计的内核驱动。在做视频的开发中,一般我们操控V4L2的设备节点就可以直接对摄像头进行操作。通常V4L2在Linux的设备节点是**/dev/video0**。无论是MIPI摄像头还是UVC摄像头,它们底层默认操作的都是/dev/video0的节点。
要操作GPIO引脚,先把所用引脚配置为GPIO功能,这通过Pinctrl子系统来实现。 然后就可以根据设置引脚方向(输入还是输出)、读值──获得电平状态,写值──输出高低电平。 以前我们通过寄存器来操作GPIO引脚,即使LED驱动程序,对于不同的板子它的代码也完全不同。 当BSP工程师实现了GPIO子系统后,我们就可以: a. 在设备树里指定GPIO引脚 b. 在驱动代码中: 使用GPIO子系统的标准函数获得GPIO、设置GPIO方向、读取/设置GPIO值。 这样的驱动代码,将是单板无关的。
出于安全原因,使用Android 原生的Camera接口,必须要使用可见的surface显示摄像头的preview图像,即必须要让用户看到你的应用正在使用摄像头。另外Android Camera framework经过层层封装,同时必须调用到显示和MediaPlayer两个模块,数据处理的环节比较多。 在开发过程中,可能会有需求只需要去获取camera数据结合AI进行处理。通过V4L2接口可以直接从驱动获取camera数据,省去了很多中间环节,同时可以在后台处理数据,不需要作为前台应用运行。
RIFFA 是一种开源通信架构,它允许通过 PCIe 在用户的 FPGA IP 内核和 CPU 的主存储器之间实时交换数据。为了建立其逻辑通道,RIFFA 在 CPU 端拥有一系列软件库,在 FPGA 端拥有 IP 核。本文主要针对其中的DMA性能(Scatter-Gather DMA)进行测试。
(1)复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
有时我们需要在 Linux 内核中预留一部分内存空间用作特殊用途(给安全模块使用,给其它处理器使用,或是给特定的驱动程序使用等),在 Device Tree 中有提供两种方法对预留内存进行配置:memreserve 和 reserved-memory。
用户空间(User Space) :用户空间又包括用户的应用程序(User Applications)、C 库(C Library) 。
本节目的: 通过分析块设备驱动的框架,知道如何来写驱动 1.之前我们学的都是字符设备驱动,先来回忆一下 字符设备驱动: 当我们的应用层读写(read()/write())字符设备驱动时,是按字
对于用户空间的应用程序,我们通常根本不关心page的物理存放位置,因为我们用的是虚拟地址。所以,只要虚拟地址不变,哪怕这个页在物理上从DDR的这里飞到DDR的那里,用户都基本不感知。那么,为什么要写一篇论述页迁移的文章呢?
原文出自:http://blog.csdn.net/ghostyu/article/details/6908805
块设备驱动块是Linux下3大设备驱动框架之一,块设备主要是针对存储类型的设备设计的驱动,配合文件系统完成数据存储。在应用层的cp、cd、touch、vim、mount等等可以操作文件,可以操作目录的命令都会通过文件系统,通过块设备驱动完成对底层存储设备的访问,实现数据读取或者写入。
前面已经将所有的硬件驱动实现,验证了硬件功能。但是每一个硬件都是单独测试的,而且并不完善。下一步,我们需要对各个驱动进行整合完善。在整合之前,需要做一些基础工作。其中之一就是实现内存管理。什么叫内存管理呢?为什么要做内存管理?前面我们已经大概了解了程序中的变量现在我们复习一下:局部变量、全局变量。
之前写了两篇详细分析 Linux 内存管理的文章,读者好评如潮。但由于是分开两篇来写,而这两篇内容其实是有很强关联的,有读者反馈没有看到另一篇读起来不够不连贯,为方便阅读这次特意把两篇整合在一起,看这一篇就够了!
答案:如果在实际的调试过程中,怀疑某处发生了内存泄露,可以查看该进程的maps表,看进程的堆段或者mmap段的虚拟地址空间是否持续增加,如果是,说明很可能发生了内存泄露,如果mmap段虚拟地址空间持续增加,还可以看到各个段的虚拟地址空间的大小,从而可以确定是申请了多大的内存,对调试内存泄露类问题可以起到很好的定位作用。
进程和线程究竟是什么?如何使用进程和线程?什么场景下需要使用进程和线程?协程又是什么?协程和线程的关系和区别有哪些? 程序切换-CPU时间的分配 首先,我们的任何一个程序都需要运行在一个操作系统中,如 Windows XP, RedHat Linux, FreeBSD, AIX 等; 其次,在操作系统中运行的程序,不止一个,而是成百上千个不同功能的程序,如键盘驱动,显示器驱动,HTTP服务,游戏,聊天,网页......; 最后,CPU等资源是有限的,在这成百上千个程序中,不可能每个程序都占用一个 CPU 来
虚拟地址空间(Virtual Address Space)是每一个程序被加载运行起来后,操作系统为进程分配的虚拟内存,它为每个进程提供了一个假象,即每个进程都在独占地使用主存。
领取专属 10元无门槛券
手把手带您无忧上云