中断处理

内核如何检测SOFT LOCKUP与HARD LOCKUP?

匿名 (未验证) 提交于 2019-12-02 23:42:01
From article 所谓lockup,是指某段内核代码占着CPU不放。Lockup严重的情况下会导致整个系统失去响应。Lockup有几个特点: 首先只有内核代码才能引起lockup,因为用户代码是可以被抢占的,不可能形成lockup; 其次内核代码必须处于禁止内核抢占的状态(preemption disabled),因为Linux是可抢占式的内核,只在某些特定的代码区才禁止抢占,在这些代码区才有可能形成lockup。 Soft lockup是指CPU被内核代码占据,以至于无法执行其它进程。检测soft lockup的原理是给每个CPU分配一个定时执行的内核线程[watchdog/x],如果该线程在设定的期限内没有得到执行的话就意味着发生了soft lockup。 Hard lockup比soft lockup更加严重,CPU不仅无法执行其它进程,而且不再响应中断。检测hard lockup的原理利用了PMU的NMI perf event,因为NMI中断是不可屏蔽的,在CPU不再响应中断的情况下仍然可以得到执行,它再去检查时钟中断的计数器hrtimer_interrupts是否在保持递增,如果停滞就意味着时钟中断未得到响应,也就是发生了hard lockup。 Linux kernel设计了一个检测lockup的机制,称为NMI Watchdog,是利用NMI中断实现的

001_FREERTOS中断配置

匿名 (未验证) 提交于 2019-12-02 23:38:02
(一)优先级看: 022_STM32中断优先级分组解析 (二)FreeRTOS的中断配置中没有处理亚优先级(响应优先级)的情况,所以只能配置成组4,16个都为抢占优先级 (三)此宏用来设置 MCU 使用几位优先级,STM32 使用的是 4 位,因此此宏为 4! 2^4=16,那么就有16个优先级 #define configPRIO_BITS 4 (四)设置系统的优先级。最低优先级就是15,系统能管理的最高优先级是5,也就是说小于5的优先级FreeRTOS不能管理 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级 (五)关中断和开中断,vPortRaiseBASEPRI() 是 向 寄 存 器 BASEPRI 写 入 宏configMAX_SYSCALL_INTERRUPT_PRIORITY , 那 么 优 先 级 低 于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断就会被屏蔽! #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()    /*关中断*/ #define

C# 多线程学习笔记 - 3

匿名 (未验证) 提交于 2019-12-02 22:06:11
本文主要针对 GKarch 相关文章留作笔记,仅在原文基础上记录了自己的理解与摘抄部分片段。 遵循原作者的 CC 3.0 协议 。 如果想要了解更加详细的文章信息内容,请访问下列地址进行学习。 原文章地址: https://blog.gkarch.com/threading/part3.html 基于事件的异步模式 (event-based asynchronous pattern) 提供了简单的方式,让类型提供多线程的能力而不需要显式启动线程。 协作取消模型。 工作线程完成时安全更新 UI 的能力。 转发异常到完成事件。 EAP 仅是一个模式,需要开发人员自己实现。 EAP 一般会提供一组成员,在其内部管理工作线程,例如 WebClient 类型就使用的 EAP 模式进行设计。 // 下载数据的同步版本。 public byte[] DownloadData (Uri address); // 下载数据的异步版本。 public void DownloadDataAsync (Uri address); // 下载数据的异步版本,支持传入 token 标识任务。 public void DownloadDataAsync (Uri address, object userToken); // 完成时候的事件,当任务取消,出现异常或者更新 UI 操作都可以才该事件内部进行操作。

Linux设备树语法详解

匿名 (未验证) 提交于 2019-12-02 21:59:42
Linux内核从3.x开始引入设备树的概念,用于实现 驱动代码与设备信息相分离 。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。比如在ARM Linux内,一个 .dts(device tree source)文件 对应一个ARM的machine,一般放置在内核的 "arch/arm/boot/dts/" 目录内,比如exynos4412参考板的板级设备树文件就是 "arch/arm/boot/dts/exynos4412-origen.dts" 。这个文件可以通过 $make dtbs 命令 编译成二进制的 .dtb文件 供内核驱动使用。 基于同样的软件分层设计的思想,由于一个SoC可能对应多个machine,如果每个machine的设备树都写成一个完全独立的 .dts文件 ,那么势必相当一些 .dts 文件有重复的部分,为了解决这个问题,Linux设备树目录把一个SoC公用的部分或者多个machine共同的部分提炼为相应的 .dtsi文件 。这样每个 .dts 就只有自己差异的部分,公有的部分只需要 "include"相应的.dtsi文件

linux0.11进程调度详解

匿名 (未验证) 提交于 2019-12-02 21:59:42
sched_init() set_tss_desc() & set_ldt_desc() ltr() & lldt() LATCH do_timer() 璺宠浆 文章写的有些长,把相关的、用到的函数都列出来了,看完应该能对进程调度相关的代码有一定了解 sched_init() kernel/sched.c : 385 该函数只有36~40行与进程调度有关,只想了解进程调度的同学可以忽略该函数其他部分 void sched_init( void ) { int i; struct desc_struct * p; if ( sizeof ( struct sigaction) != 16 ) panic( "Struct sigaction MUST be 16 bytes" ); //以下两行初始化init任务(任务0)的任务状态段描述符和局部数据表描述符 //详细介绍见下文 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss)); set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt)); p = gdt+ 2 +FIRST_TSS_ENTRY; //指向gtd表中init任务的后一个任务的任务状态段描述符 for (i= 1 ;i<NR_TASKS;i++) { /

Linux-BSP-驱动-面试题大全

匿名 (未验证) 提交于 2019-12-02 21:56:30
1. 了解Linux的那个驱动?举例讲讲。 a .驱动注册过程:通过 platform_bus , register_platform_device 和 register_platform_driver 时都会在总线查询是否有匹配的设备或驱动,如果有就会调用 driver 的 probe 函数。 <延伸问题: device 和 driver 通过什么匹配的? name 或 id_table ( dtsi 里面 compatable 字段)> b .驱动类型:字符设备( fb 显示设备)、块儿设备、网络设备 c .字符设备为例,驱动需要实现的函数 fops :( open , read , write , release , store , show 实现暴露给 usr space 的设备节点, suspend , resume 并不是都实现这些) 2. 中断上半部下半部 top half : spinlock_irqsave 做很少的工作,需要快速处理完,一般是关中断,清中断标志位,保存数据,调用中断下半部,开中断。 botomm half : tasklet , workque (可以睡眠可以调度)。 中断里用 spin lock ,不能用 semphore (可以调度可以睡眠) 3. spinlock semphore mutex 区别 4. 内核空间和用户空间通信方式 5.

Linux探秘之用户态与内核态

匿名 (未验证) 提交于 2019-12-02 21:56:30
Ŀ¼ Unix/Linux的体系架构 用户态和内核态的切换 Unix/Linux的体系架构 宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核)。 下图是对上图的一个细分结构,从这个图上可以更进一步对内核所做的事有一个“全景式”的印象。主要表现为:向下控制硬件资源,向内管理操作系统资源:包括进程的调度和管理、内存的管理、文件系统的管理、设备驱动程序的管理以及网络资源的管理,向上则向应用程序提供系统调用的接口。从整体上来看,整个操作系统分为两层:用户态和内核态,这种分层的架构极大地提高了资源管理的可扩展性和灵活性,而且方便用户对资源的调用和集中式的管理,带来一定的安全性。 用户态的应用程序可以通过三种方式来访问内核态的资源: 系统调用 内核从本质上看是一种软件――控制计算机的硬件资源,并提供上层应用程序运行的环境。 用户态即上层应用程序的活动空间,应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。为了使上层应用能够访问到这些资源,内核必须为上层应用提供访问的接口:即系统调用。 系统调用的本质其实也是中断,相对于外围设备的硬中断,这种中断称为软中断,这是操作系统为用户特别开放的一种中断,如Linux int 80h中断。 从触发方式上来看,系统调用是进程主动请求切换的,而异常和硬中断则是被动的。 系统调用是操作系统的最小功能单位

Java线程池的底层实现与使用

匿名 (未验证) 提交于 2019-12-02 21:53:52
前言   在我们进行开发的时候,为了充分利用系统资源,我们通常会进行多线程开发,实现起来非常简单,需要使用线程的时候就去创建一个线程(继承Thread类、实现Runnable接口、使用Callable和Future),但是这样也有一点问题,就是如果并发的线程数量很多,创建线程、销毁线程都是需要消耗时间、资源,这个时候线程池就派上用场了 一、四种线程池的介绍   Java通过Executors提供了四种线程池,分别是    1.newSingleThreadExecutor()   创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务都是按照指定的顺序(FIFO,LIFO,优先级)执行 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor( 1 , 1 , 0L , TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable> ())); }    2.newFixedThreadExecutor()   创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 public static

Java并发

匿名 (未验证) 提交于 2019-12-02 21:53:52
Java内存模型是什么? Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程时思路更清晰。比如,先行发生关系确保了: 线程内的代码能够按先后顺序执行,这被称为程序次序规则。 对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。 前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。 一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。 一个线程的所有操作都会在线程终止之前,线程终止规则。 一个对象的终结操作必需在这个对象构造完成之后,也叫对象终结规则。 可传递性 更多介绍可以移步并发编程网: (深入理解java内存模型系列文章:http://ifeve.com/java-memory-model-0) Java中interrupted 和isInterruptedd方法的区别? interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt(

Java多线程基础

匿名 (未验证) 提交于 2019-12-02 21:52:03
什么是线程 线程是操作系统调度的最小单位,在一个进程中,一般至少有一个线程在运行。一个进程中包含的多个线程,在多核处理器中,操作系统可以将多个线程调度到不同的CPU核心上运行,多个线程可以并行运行。 在同一个进程中的多个线程,共享同一个进程空间,这意味着,线程间通信的成本相对进程间会低很多,但是由于可以同时访问同一个内存地址,所以不正确的同步可能会导致数据竞争而发生错误。 3. 创建一个线程 在Java中,创建一个线程最简单的方式是继承 java.lang.Thread 类。通过重写Thread类的run()方法,可以将线程中需要执行的代码放到run()方法中,这样,当这个线程被启动以后,可以在新启动的线程中执行这些逻辑。 public class SimpleThread extends Thread { @Override 上面的代码中,我们通过继承Thread创建了一个SimpleThread类,然后重写了Thread的run()方法,把需要在新的线程中执行的逻辑放到run()方法中,当通过Thread的start()方法启动线程以后,run()方法就会在新线程中被执行。 如果采用这种方式创建线程,那么当我们有多个不同的逻辑需要并行执行,那么我们需要像上面一样,通过继承的方式创建多个Thread的子类,然后重写run()方法来实现。这样看来,我们其实是创建了多个不同类型的线程