驱动工程师

1.内核和用户空间的通信?

2.、写个字符设备需要什么?

一句话,系统调用是内核给用户空间提供的一个可以访问内核资源的一个接口。

linux内核内存的分布:

Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟地址空间也为0~4G.Linux内核将这4G字节的空间分为两部分。将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为"内核空间".而将较低的3G字节(从虚拟地址
0x00000000到0xBFFFFFFF),供各个进程使用,称为"用户空间)。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。

linux内核的保护机制

Linux使用两级保护机制:0级供内核使用,3级供用户程序使用。从图中可以看出(这里无法表示图),每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的。最高的1GB字节虚拟内核空间则为所有进程以及内核所共享。

内核空间中存放的是内核代码和数据
进程的用户空间中存放的是用户程序的代码和数据
不管是内核空间还是用户空间,它们都处于虚拟空间中。
 虽然内核空间占据了每个虚拟空间中的最高1GB字节,但映射到物理内存却总是从最低地址(0x00000000)开始。对内核空间来说,其地址映射是很简单的线性映射,0xC0000000就是物理地址与线性地址之间的位移量,在Linux代码中就叫做PAGE_OFFSET.

内核空间和用户空间之间如何进行通讯?

内核空间和用户空间一般通过系统调用函数进行通信。

如何判断一个驱动是用户模式驱动还是内核模式驱动? 判断的标准是什么?

用户空间模式的驱动一般通过系统调用来完成对硬件的访问,如通过系统调用将驱动的io空间映射到用户空间等。因此,主要的判断依据就是系统调用。

内核空间和用户空间的不同?

内核空间和用户空间上不同太多了,说不完,比如用户态的链表和内核链表不一样;用户态用printf,内核态用printk;用户态每个应用程序空间是虚拟的,相对独立的,内核态中却不是独立的,所以编程要非常小心。等等

还有用户态和内核态程序通讯的方法很多,不单单是系统调用,实际上系统调用是个不好的选择,因为需要系统调用号,这个需要统一分配。

还有用户态和内核态程序通讯的方法很多,不单单是系统调用,实际上系统调用是个不好的选择,因为需要系统调用号,这个需要统一分配。
  可以通过ioctl、sysfs、proc等来完成。

去/sys看一看,

localhost:/sys#ls /sys/

block/ bus/ class/ devices/ firmware/ kernel/ module/ power/

Block目录:包含所有的块设备

Devices目录:包含系统所有的设备,并根据设备挂接的总线类型组织成层次结构

Bus目录:包含系统中所有的总线类型

Drivers目录:包括内核中所有已注册的设备驱动程序

Class目录:系统中的设备类型(如网卡设备,声卡设备等)

sys下面的目录和文件反映了整台机器的系统状况。比如bus,如查看USB鼠标信息等

去/proc看一看,

proc被称为虚拟文件系统,它是一个控制中心,可以通过更改其中某些文件改变内核运行状态,
它也是内核提空给我们的查询中心,用户可以通过它查看系统硬件及当前运行的进程信息。
Linux中许多工具的数据来源正是proc目录中的内容,比如lsmod的命令是cat /proc/modules的别名。

/proc目录下常用文件介绍:

/proc/loadavg 前三列分别保存最近1分钟,5分钟,及15分钟的平均负载。
/proc/meminfo 当前内存使用信息
/proc/diskstats 磁盘I/O统计信息列表
/proc/net/dev 网络流入流出统计信息
/proc/filesystems 支持的文件系统
/proc/cpuinfo CPU的详细信息
/proc/cmdline 启动时传递至内核的启动参数,通常由grub进行传递
/proc/mounts 系统当前挂在的文件系统
/proc/uptime 系统运行时间
/poc/version 当前运行的内核版本号等信息

为什么要分内核空间和用户空间,其区别是什么?

在我的理解里,其实这样分是一种保护机制,提供保护的目的。是要避免系统中的一个任务访问属于另外的或属于其他的存储区域,这样的保护机制它能抵御恶意用户的窥探,也能防止质量低劣的用户程序的侵害,从而使系统运行得更稳定可靠。

内核程序不能使用标准库函数(strlen strcmp等fopen ),只能使用系统调用函数 如open
区别
内核空间中存放的是内核代码和数据**
进程的用户空间中存放的是用户程序的代码和数据

信息交互方法

信息交互按信息传输发起方可以分为
用户向内核传送/提取数据

内核向用户空间提交请求两大类,先来说说:

字符设备和块设备的区别,请分别列举一些实际的设备说出它们是属于哪一类设备

字符设备:/dev下的设备驱动文件,字符设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少实现open,close,read和write系统调用。字符终端、串口、鼠标、键盘、摄像头、声卡和显卡等就是典型的字符设备。

块设备:和字符设备类似,块设备也是通过/dev目录下的文件系统节点来访问。块设备上能够容纳文件系统,如:u盘,SD卡,磁盘等。

字符设备和块设备的区别仅仅在于内核内部管理数据的方式,也就是内核及驱动程序之间的软件接口,而这些不同对用户来讲是透明的。在内核中,和字符驱动程序相比,块驱动程序具有完全不同的接口。

LINUX系统可以分为四个部分

1、引导加载程序(BootLoader->uboot),
(1)初始化 RAM
因为 Linux 内核一般都会在 RAM 中运行,所以在调用 Linux 内核之前 bootloader 必须设置和初始化 RAM,为调用 Linux内核做好准备。
(2)初始化串口
(3)检测处理器类型
Bootloader在调用 Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给 Linux 内核。Linux 内核在启动过程中会根据该处理器类型调用相应的初始化程序
(5)调用 Linux内核映像
Bootloader完成的最后一项工作便是调用 Linux内核。如果 Linux 内核存放在 Flash 中,并且可直接在上面运行(这里的 Flash 指 Nor Flash),那么可直接跳转到内核中去执行。但由于在 Flash 中执行代码会有种种限制,而且速度也远不及 RAM 快,所以一般的嵌入式系统都是将 Linux内核拷贝到 RAM 中,然后跳转到 RAM 中去执行
start_kernel-》跳到内核初始化的函数

2、linux内核,
3、文件系统,
4、应用程序。

Linux内核启动过程概述**

(首先会执行汇编代码,其目的是用来做一些内核启动前的检测(内核是否支持当前CPU),环境的建立(MMU))。
 
 1、首先看这段汇编代码,它主要是用来做一些内核启动前的检测。
 
__lookup_processor_type 检测内核是否支持当前CPU、__lookup_machine_type检测是否支持当前单板,并且__create_page_tables创建页表,__enable_mmu使能MMU。初始化中断,IO的映射表,定时器,内存环境的初始化和建立。
后就跳到C语言部分。

2、接下来进入start_kernel启动内核的C函数。上面是start_kernel的部分代码。这部分代码的主要作用是处理uboot传递来的参数,设置与体系结构相关的环境,初始化控制台,最后执行应用程序,实现功能。这里我把start_kernel函数的几个主要功能的子函数逐层写出,帮助大家理解start_kernel的功能结构。

linux设备驱动框架

一.Linux设备分类
字符设备: 以字节为单位读写的设备。
例如:
字符设备驱动程序通常至少要实现open、close、read和write的系统调 用。字符终端(/dev/console)和串口(/dev/ttyS0以及类似设备)就是两个字符设备,

块设备 : 以块为单位(效率最高)读写的设备。
因此,块设备和字符设备的 区别仅仅在于内核内部管理数据的方式

网络设备 : 用于网络通讯设备。
任何网络事物都需要经过一个网络接口形成。
如网络接口的方法仍然是给它们分配一个唯一的名字(比如eth0)

二. 上层应用程序是如何访问到底层驱动程序的呢?

在linux的世界里一切皆文件,
在这里我们拿字符设备为例,来看一下应用程序如何和底层驱动程序关联起来。
??????

1:应用层通过系统调用函数去访问linux内核,首先会进入到VFS虚拟文件系统,因为一切皆与文件,其中会有一个变量叫文件描述符,通过这个文件描述符就可以直接调用对应的文件驱动 从而跟内核通信,与硬件通信。
在这里插入图片描述

linux内核调度器 调度原理(2.6.24笔记整理)

Linux内核中,运行一个进程,会因为各种因素,进程会处于何种状态。

由调度器调度

有如下几种状态:

1.用户运行态:用户层面,由用户执行程序,执行与等待结果过程。

2.运行态:CPU处理进程任务并返回运行结果

3.僵尸态:进程运行完,但是没有进行资源回收,编程僵尸进程

4.可中断睡眠:可中断的睡眠状态的进程会睡眠直到某个条件变为真,如产生一个硬件中断、释放进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。

5.不可中断睡眠:不可中断睡眠状态与可中断睡眠状态类似,但是它有一个例外,那就是把信号传递到这种睡眠状态的进程不能改变它的状态,也就是说它不响应信号的唤醒。

6.就绪态:多个进程在等待CPU的处理,队列形式等待(调度优先级高的先执行)

7.暂停态:进程在CPU中,收到暂停信号,变成暂停态

(每个CPU都会有一个RQ运行队列,将就绪态的进程组织在一起。其实是一个双向链表,将相同优先等级的实时进程被组织在一个双向链表中。)

在这里插入图片描述

  1. 查看驱动模块中打印信息的命令:dmesg
    2)查看字符设备信息可以用lsmod
  2. 显示当前使用的中断号cat /proc/interrupt

copy_to_user()和copy_from_user()主要用于实现什么功能?一般用于file_operations结构的哪些函数里面?

由于内核空间和用户空间是不能互相访问的,如果需要访问就必须借助内核函数进行数据读写。copy_to_user():完成内核空间到用户空间的复制,copy_from_user():是完成用户空间到内核空间的复制。一般用于file_operations结构里的read,write,ioctl等内存数据交换作用的函数。当然,如果ioctl没有用到内存数据复制,那么就不会用到这两个函数。

请简述主设备号和次设备号的用途。

在Linux内核看来,主设备号标识设备对应的驱动程序,告诉Linux内核使用哪一个驱动程序为该设备(也就是/dev下的设备文件)服务;
而次设备号则用来标识具体且唯一的某个设备。

设备驱动程序中如何注册一个字符设备?分别解释一下它的几个参数的含义。

注册一个字符设备驱动有两种方法:

1) void cdev_init(struct cdev *cdev, struct file_operations *fops)

该注册函数可以将cdev结构嵌入到自己的设备特定的结构中。cdev是一个指向结构体cdev的指针,而fops是指向一个类似于f file_operations结构(可以是file_operations结构,但不限于该结构)的指针.

2) int register_chrdev(unsigned int major, const char *namem , struct file)operations *fopen);
该注册函数是早期的注册函数,major是设备的主设备号,name是驱动程序的名称,而fops是默认的file_operations结构(这 是只限于file_operations结构)。对于register_chrdev的调用将为给定的主设备号注册0-255作为次设备号,并为每个 设备建 立一个对应的默认cdev结构。

linux中RCU原理?

从RCU(read-copy-update)的名称上看,我们就能对他的实现机制有一个大概的了解,在修改数据的时候,首先需要读取数据,然后生成一个副本,对副本进行修改,修改完成之后再将老数据update成新的数据,此所谓RCU。

  1. 对于读操作,可以直接对共享资源进行访问,但是前提是需要CPU支持访存操作的原子化,现代CPU对这一点都做了保证。但是RCU的读操作上下文是不可抢占的(这一点在下面解释),所以读访问共享资源时可以采用read_rcu_lock(),该函数的工作是停止抢占。

2 . 对于写操作,其需要将原来的老数据作一次备份(copy),然后对备份数据进行修改,修改完毕之后再用新数据更新老数据,更新老数据时采用了rcu_assign_pointer()宏,在该函数中首先屏障一下memory,然后修改老数据。

  1. 在RCU机制中存在一个垃圾回收的daemon,当共享资源被update之后,可以采用该daemon实现老数据资源的回收。

LINUX内存管理

在linux操作系统中,内存管理有2个概念,一个是虚拟内存与物理内存。

对应于虚拟内存,它实际上不占用实际物理内存

Linux内核在用户申请内存的时候,只是给它分配了一个线性区(也就是虚存),并没有分配实际物理内存;只有当用户使用这块内存的时候,内核才会分配具体的物理页面给用户,这时候才占用宝贵的物理内存。内核释放物理页面是通过释放线性区,找到其所对应的物理页面,将其全部释放的过程。

char *p=malloc(2048) //这里只是分配了虚拟内存2048,并不占用实际内存。
strcpy(p,”123”) //分配了物理页面,虽然只是使用了3个字节,但内存还是为它分配了2048字节的物理内存。
free§ //通过虚拟地址,找到其所对应的物理页面,释放物理页面,释放线性区。

进程内存空间

进程如何使用内存?

虚拟内存分为以下几个部分
BSS 数据段 代码段 堆 栈
堆栈:
他们一个向下“长”(i386体系结构中栈向下、堆向上),一个向上“长”,相对而生。但你不必担心他们会碰头,因为他们之间间隔很大(到底大到多少,你可以从下面的例子程序计算一下),绝少有机会能碰到一起。
在这里插入图片描述

因为内存中的段机制可将虚拟地址转换为线性地址,
通过页机制可将线性地址转换为物理地址,这之后虚拟地址才实实在在地映射到了系统的物理内存上

在这里插入图片描述
从用户向内核看,所使用的内存表象形式会依次经历“逻辑地址”——“线性地址”——“物理地址”

逻辑地址经段机制转化成线性地址;线性地址又经过页机制转化为物理地址。(但是我们要知道Linux系统虽然保留了段机制,但是将所有程序的段地址都定死为0-4G,所以虽然逻辑地址和线性地址是两种不同的地址空间,但在Linux中逻辑地址就等于线性地址,它们的值是一样的)

而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表

第一、4G的进程地址空间被人为的分为两个部分——用户空间与内核空间。用户空间从0到3G(0xC0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。

第二、用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表(init_mm.pgd),用户进程各自有不同的页表。

insmod 一个驱动模块,会执行模块中的哪个函数?rmmod呢?这两个函数在设计上要注意哪些?遇到过卸载驱动出现异常没?是什么问题引起的?

 答: insmod调用init函数,rmmod调用exit函数。这两个函数在设计时要注意什么?卸载模块时曾出现卸载失败的情形,原因是存在进程正在使用模块,检查代码后发现产生了死锁的问题。

  要注意在init函数中申请的资源在exit函数中要释放,包括存储,ioremap,定时器,工作队列等等。也就是一个模块注册进内核,退出内核时要清理所带来的影响,带走一切不留下一点痕迹。

platform或设备驱动模型的组成三个成员

platform = platform bus + platform device + platform driver
设备驱动模型三个重要成员是 总线、设备、驱动;

platfoem总线的匹配规则是:要匹配的设备和驱动都要注册,设备可以在设备树里注册,也可以通过代码注册设备,匹配成功会去调用驱动程序里的probe函数(probe函数在这个platform_driver结构体中注册)。

在驱动调试过程中遇到过oops没?你是怎么处理的?

Oops 这个单词含义为“惊讶”
,当内核出错时(比如访问非法地址)打印出来的信息被
称为 Oops 信息。
分析 Oops 信息
(1)明确出错原因。
由出错信息“Unable to handle kernel NULL pointer dereference at virtual address 00000000”
可知内核是因为非法地址访问出错,使用了空指针。
(2)根据栈回溯信息或报错信息找出函数调用关系。
内核崩溃时,可以从 pc 寄存器得知崩溃发生时的函数、出错指令。但是很多情况下,错
误有可能是它的调用者引入的,所以找出函数的调用关系也很重要。
实在不行就可以通过汇编
(3)结合内核源代码和反汇编代码定位问题。

Ioctl与unlocked_ioctl的区别

**而在驱动程序中这个指针函数变了之后最大的影响是参数中少了inode **

驱动中操作物理绝对地址为什么要先ioremap?

因为内核没有办法直接访问物理内存地址,必须先通过ioremap获得对应的虚拟地址
Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地址映射到核心虚地址空间(3GB-4GB)中(这里是内核空间),

你平常是怎么用C写嵌入式系统的死循环的?

  for(;;){}  

  while(1){}

 一般for(;;)性能更优

for(;😉{}

 这两个;; 空语句,编译器一般会优掉的,直接进入死循环

while(1){}  

每循环一次都要判断常量1是不是等于零,在这里while比for多做了这点事

不过从汇编的角度来说,都是一样的代码。

kmalloc和vmalloc的区别

kmalloc()
用于申请较小的、连续的物理内存

  1. 以字节为单位进行分配,在<linux/slab.h>中
  2. void *kmalloc(size_t size, int flags) 分配的内存物理地址上连续,虚拟地址上自然连续

vmalloc()
用于申请较大的内存空间,申请的物理内存是非连续内存区。虚拟内存是连续的

  1. 以字节为单位进行分配,在<linux/vmalloc.h>中
  2. void *vmalloc(unsigned long size) 分配的内存虚拟地址上连续,物理地址不连续
    . 一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用 kmalloc(),而只有在需要获得大块内存时才使用vmalloc(),例如当模块被动态加载到内核当中时,就把模块装载到由vmalloc()分配 的内存上。

malloc(), vmalloc()和kmalloc()区别
[]kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存
[
]kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西(这点是自己猜测的,不一定正确)
[]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大
[
]内存只有在要被DMA访问的时候才需要物理上连续
[*]vmalloc比kmalloc要慢

IIC原理,总线框架,设备编写方法,i2c_msg

1.I2C协议

2条双向串行线,一条数据线SDA,一条时钟线SCL。
SDA传输数据是大端传输,每次传输8bit,即一字节。
支持多主控(multimastering),任何时间点只能有一个主控。
总线上每个设备都有自己的一个addr,共7个bit,广播地址全0.
系统中可能有多个同种芯片,为此addr分为固定部分和可编程部份,细节视芯片而定,看datasheet。

Kernel Panic(内核崩溃)常见原因以及解决方法

出现原因 1. Linux在中断处理程序中,它不处于任何一个进程上下文,如果使用可能睡眠的函数,则系统调度会被破坏,导致kernel panic。因此,在中断处理程序中,是不能使用有可能导致睡眠的函数(例如信号量等)。

  1. 内核堆栈溢出,或者指针异常访问时,会出现kernel panic。 堆栈溢出:程序循环或者多层嵌套的深度过多时,可能会导致栈溢出。参考Linux的内存模型

一、内核空间和用户空间

Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟地址空间也为0~ 4G。Linux内核将这4G字节的空间分为两部分。将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为“内核空间”。而将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间“)。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。
二、内核态和用户态

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

怎样申请大块内核内存?

   vmalloc

用户进程间通信主要哪几种方式?

无名管道(fork 父子进程能通信),有名管道FIFO,消息队列,信号量,共享内存,网络编程套接字,

framebuffer机制?

Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,通过mmap将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的。通过mmap调用把显卡的物理内存空间映射到用户空间

1. spinlock与信号量的区别?

虽然听起来两者之间的使用条件复杂,其实在实际使用中信号量和自旋锁并不易混淆。
注意以下原则:

如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。如果需要在自旋 锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选 择。另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。

linux内核原子操作的实现

所谓原子操作,就是“不可中断的一个或一系列操作”。

自旋锁和信号量在互斥使用时需要注意哪些?在中断服务程序里面的互斥是使用自旋锁还是信号量?还是两者都能用?为什么(答案见1分析)?

答:使用自旋锁的进程不能睡眠,使用执行时间短的任务。
使用信号量的进程可以睡眠,适合于执行时间较长的任务。
中断服务例程中的互斥使用的是自旋锁,原因是在中断处理例程中,硬中断是关闭的,这样会丢失可能到来的中断。

驱动里面为什么要有并发、互斥的控制?如何实现?讲个例子?

并发(concurrency)指的是多个执行单元同时、并行被执行,而并发的执行单元对共 享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态(race conditions)。
解决竞态问题的途径是保证对共享资源的互斥访问,所谓互斥访问就是指一个执行单元 在访问共享资源的时候,其他的执行单元都被禁止访问。

访问共享资源的代码区域被称为临界区,临界区需要以某种互斥机 制加以保护,中断屏蔽,原子操作,自旋锁,和信号量都是linux设备驱动中可采用的互斥途径。

硬中断与软中断的区别

硬中断:

  1. 硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)。
  2. 处理中断的驱动是需要运行在CPU上的,因此,当中断产生的时候,CPU会中断当前正在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU(也有一种特殊的情况,就是在大型主机上是有硬件通道的,它可以在没有主CPU的支持下,可以同时处理多个中断。)。
  3. 硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些时间去处理的进程,中断代码本身也可以被其他的硬中断中断。
  4. 对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。
    软中断:
  5. 软中断的处理非常像硬中断。然而,它们仅仅是由当前正在运行的进程所产生的。
  6. 通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。
  7. 软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度。一些内核允许设备驱动的一些部分存在于用户空间,并且当需要的时候内核也会调度这个进程去运行。
  8. 软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。

问:软中断所经过的操作流程是比硬中断的少吗?换句话说,对于软中断就是:进程 ->内核中的设备驱动程序;对于硬中断:硬件->CPU->内核中的设备驱动程序?

答:是的,软中断比硬中断少了一个硬件发送信号的步骤。产生软中断的进程一定是当前正在运行的进程,因此它们不会中断CPU。但是它们会中断调用代码的流程。

tasklet和workqueue区别?

tasklet运行于中断上下文,不允许阻塞 、休眠,而workqueue运行与进程上下文,可以休眠和阻塞。

为什么要区分上半部和下半部?

中断服务程序异步执行,可能会中断其他的重要代码,包括其他中断服务程序。因此,为了避免被中断的代码延迟太长的时间,中断服务程序需要尽快运行,而且执行的时间越短越好,所以中断程序只作必须的工作,其他工作推迟到以后处理。所以Linux把中断处理切为两个部分:上半部和下半部。

4. 中断的申请及何时执行(何时执行中断处理函数)?

中断的响应流程:cpu接受中断->保存中断上下文跳转到中断处理历程->执行中断上半部->执行中断下半部->恢复中断上下文。

中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?

中断是CPU处于被动状态下来接受设备的信号,而轮询是CPU主动去查询该设备是否有请求。凡事都是两面性,所以,看效率不能简单的说那个效率高。
如果是请求设备是一个频繁请求cpu的设备,或者有大量数据请求的网络设备,那么轮询的效率是比中断高。如果是一般设备,并且该设备请求cpu的频率比较底,则用中断效率要高一些。主要是看请求频率

写一个中断服务需要注意哪些?如果中断产生之后要做比较多的事情你是怎么做的?

第一: 中断处理例程应该尽量短,把能放在后半段(tasklet,等待队列等)的任务尽量放在后半段。
写一个中断服务程序要注意快进快出,在中断服务程序里面尽量快速采集信息,包括硬件信息,然后退出中断,要做其它事情可以使用工作队列或者tasklet方式。也就是中断上半部和下半部。

第二:中断服务程序中不能有阻塞操作。应为中断期间是完全占用CPU的(即不存在内核调度),中断被阻塞住,其他进程将无法操作;

第三:中断服务程序注意返回值,要用操作系统定义的宏做为返回值,而不是自己定义的OK,FAIL之类的。

驱动中操作物理绝对地址为什么要先ioremap?

因为内核没有办法直接访问物理内存地址,必须先通过ioremap获得对应的虚拟地址。

Linux软中断和工作队列的作用是什么?

  https://blog.csdn.net/godleading/article/details/52971179

什么是设备驱动模型?

设备驱动模型其实是Linux内核为了管理硬件上的设备和对应的驱动制定的一套软件体系。那么其实设备驱动模型是一个比较
抽象、比较广的一个概念,一两句话是很难说清楚的,类(class)、总线(bus)、设备(device)、驱动(driver)、mdev(自动创建设备节点和设备类)。??

停车场管理系统

V4L2是linux操作系统下用于采集图片、视频的API接口,可以实现图片、视频、音频的采集。可以对免驱摄像头进行数据采集。V4L2采集的方法是内存映射方式(mmap) 来采集数据,用于连续的视频数据采集。步骤:1、打开视频设备文件,进行视频采集的参数初始化,2、申请若干视频采集的帧缓冲区,便于应用程序读取/处理视频数据;3、将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集;
4、驱动开始视频数据的采集,应用程序从视频采集输出队列取出帧缓冲区,可抓帧显示在LCD屏上。处理完后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据;第五,停止视频采集。

语音播报:
通过TCP 套接字与ubuntu进行通信,应用程序是科大讯飞的一个输入一串字符串将其转换成音频文件的。这样当开发板的程序要播放音频的时候,首先传字符串,科大讯飞合成音频文件,将音频文件通过套接字发送给开发板程序。最后通过alsa去播放wav文件的音频。

然后也学习过alsa开源库(ALSA 是Advanced Linux Sound Architecture,高级Linux 声音架构的简称),在开发板上安装配置alsa库,利用代码可以实现录制(arecode)一段音频,并且播放(aplay)一段音频。音频的格式为WAV和PCM。

触摸算法

触摸部分:Rx去读spi得到的数据,分为2个数据一个数据是AD-X 另一个AD-Y然后开始去多次采样、去头掐尾求平均等简单滤波算法最后通过tslib去计算出真正的xy的值,获取到后通过input_report_abs上报这个点。 设置总线 设从机地址。 去写

I2c 显示

设置总线 设从机地址。
在这里插入图片描述在这里插入图片描述
去写
在这里插入图片描述

input设备子系统

在这里插入图片描述

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章