Linux内核开发之中断与时钟(一) linux 内核时间

   2023-02-09 学习力0
核心提示:“小王,醒醒,开始上课了,今天咱们开始讲中断,这可是高级东西,错过不补哈”我使劲推着睡梦中的小王。 “嗯?感情好啊,快点,快点”小王一听有新东西讲,像打了鸡血似的兴奋,连我都怀疑起她是不是性格中喜新厌旧。 不管那么多了,我讲我的,她厌她的…

“小王,醒醒,开始上课了,今天咱们开始讲中断,这可是高级东西,错过不补哈”我使劲推着睡梦中的小王。

“嗯?感情好啊,快点,快点”小王一听有新东西讲,像打了鸡血似的兴奋,连我都怀疑起她是不是性格中喜新厌旧。

不管那么多了,我讲我的,她厌她的…

  啥叫中断?就是指cpu在执行过程中,出现了某些突发事件时CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU有返回原程序被中断的位置并继续执行。

  中断的分法不懂,分类就不同,向什么内外部中断,可/不可屏蔽中断…等等乱七八糟一大堆,我这里要说明的一点是按照中断入口跳转方法的不同,可分为向量中断和非向量中断。采用向量中断的CPU通常为不同的中断分配不同的中断号,当检测到某中断号的中断到来后,就自动跳转到与该中断号对应的地址执行。不同的中断号有不同的中断地址(即入口)。而非向量中断的多个中断共享一个入口地址。进入后根据软件判断中断标志来识别具体是哪个中断。也就是说,向量中断是由硬件提供中断服务程序入口地址,非向量中断由软件提供中断服务程序入口地址。

  我们在后边会说到一个时钟定时器,它也是通过中断来实现的。它的原理很简单,嵌入式微处理器它接入一个时钟输入,当时钟脉冲到来时,就将目前的计数器值加1并和预先设置的计数值比较,若相等,证明计数周期满,产生定时器中断并复位目前计数器值。

              Linux内核开发之中断与时钟(一)

 

 

 

 

 

 

Linux中断处理架构

设备的中断会打断内核中进程的正常调度和运行,会影响系统的性能。为了在中断执行时间尽可能短和中断处理需完成大量工作之间找到一个平衡点,Linux将中断处理程序分解成两个半部:顶半部和底半部。其中顶半部尽可能完成尽可能少的比较紧急的功能。而底半部几乎做了中断处理程序所有的事情,而且可以被新的中断打断。

在linux设备驱动中,提供了一系列函数来帮助设备实现中断的相关操作:

1)设备申请中断

int request_irq(unsigned int irq,  //irq是要申请的中断号

                    void (*handler)(int irq, void *dev_id, struct pt_regs * *regs),//回调函数,中断发生时,系统会调用该函数,

                    unsigned long irqflags,

                    const char *devname,

                    void *dev_id);

其中irqflags是中断处理的属性,若设置为SA_INTERRUPT,则表示中断处理程序是快速处理程序,它被调用时屏蔽所有中断。若设置为SA_SHIRQ,则表示多个设备共享中断,dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL.

该函数返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回EBUSY表示中断已经被占用且不能共享。

2)释放中断

free_irq(unsigned int irq, void *dev_id);

3)使能和屏蔽中断

void disable_irq(int irq);   //这个会立即返回

void disable_irq_nosync(int irq);//等待目前的中断处理完成再返回。

void enable_irq(int irq);

上述三个函数作用于可编程中断处理器,因此对系统内所有的CPU都生效。

void local_irq_save(unsigned long flags);//会将目前的中断状态保留在flags中

void local_irq_disable(void);//直接中断

这两个将屏蔽本CPU内的所有中断。对应的上边两个中断的方法如下

void local_irq_restore(unsigned long flags);

void local_irq_enable(void);

 

我们两边说了Linux系统中中断是分为顶半部和底半部的,那么在系统实现方面是具体怎样实现的呢,这主要有tasklet,工作队列,软中断:

1)tasklet:使用比较简单,如下:

void my_tasklet_function(unsigned long); //定义一个处理函数

DECLARE_TASKLET(my_tasklet, my_tasklet_function, data); //定义了一个名叫my_tasklet的tasklet并将其与处理函数绑定,而传入参数为data

在需要调度tasklet的时候引用一个tasklet_schedule()函数就能使系统在适当的时候进行调度运行:tasklet_schedule(&my_tasklet);

2)工作队列:使用方法和tasklet相似,如下:

struct work_struct my_wq; //定义一个工作队列

void my_wq_func(unsigned long);  //定义一个处理函数

通过INIT_WORK()可以初始化这个工作队列并将工作队列与处理函数绑定,如下:

INIT_WORK(&my_wq, (void (*)(void *))my_wq_func, NULL);  //初始化工作队列并将其与处理函数绑定

同样,使用schedule_work(&my_irq);来在系统在适当的时候需要调度时使用运行。

3)软中断:使用软件方式模拟硬件中断的概念,实现宏观上的异步执行效果,tasklet也是基于软中断实现的。

在Linux内核中,用softirq_action结构体表征一个软中断,这个结构体中包含软中断处理函数指针和传递给函数的参数,使用open_softirq()可以注册软中断对应的处理函数,而raise_softirq()函数可以触发一个中断。

软中断和tasklet仍然运行与中断上下文,而工作队列则运行于进程上下文。因此,软中断和tasklet的处理函数不能休眠,但工作队列是可以的。

local_bh_disable()和local_bh_enable()是内核用于禁止和使能软中断和tasklet底半部机制的函数。

 

下边咱们再来说说有关中断共享的相关点:中断共享即是多个设备共享一根硬件中断线的情况。Linux2.6内核支持中断共享,使用方法如下:

*共享中断的多个设备在申请中断时都应该使用SA_SHIRQ标志,而且一个设备以SA_SHIRQ申请某中断成功的前提是之前该中断的所有设备也都以SA_SHIRQ标志申请该终端

*尽管内核模块可访问的全局地址都可以作为request_irq(….,void *dev_id)的最后一个参数dev_id,但是设备结构体指针是可传入的最佳参数。

*在中断带来时,所有共享此中断的中断处理程序都会被执行,在中断处理程序顶半部中,应迅速根据硬件寄存器中的信息比照传入的dev_id参数判断是否是被设备的中断,如果不是,应迅速返回。

 

结语:在这次讲解中说了三种Linux系统中中断的顶/底半部机制和中断共享的先关内容,但碍于页面空间的原因,没有给出例子,我在下次博客中会专门来对每个点给出典型的模版.

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 【强转】QEMU+GDB调试linux内核全过程
    【强转】QEMU+GDB调试linux内核全过程
    昨天更新了一篇名为《QEMU+GDB调试linux内核全过程》[link][https://blog.csdn.net/weixin_37867857/article/details/88138432]的博客,发现排版比较混乱,而且思维也比较混乱。咋一看下来简直是惨不忍睹,而且会给读者在安装过程中一种云里雾里的感觉,加上
    03-08
  • Linux下Bochs,NASM安装和使用 linux bom
    Linux下Bochs,NASM安装和使用 linux bom
    以Ubuntu为例,先更新一下:sudo apt-get updatesudo apt-get upgrade然后安装Bochs环境:sudo apt-get install build-essential xorg-dev libgtk2.0-dev安装NASMNASM官网下载,这以nasm-2.14.02.tar.gz为例:用tar zxvf nasm-2.14.02.tar.gz解压后编译安装cd
    03-08
  • 把玩Alpine linux(一):安装
    把玩Alpine linux(一):安装
    导读Alpine Linux是一个面向安全应用的轻量级Linux发行版。它采用了musl libc和busybox以减小系统的体积和运行时资源消耗,同时还提供了自己的包管理工具apk。Alpine 的内核都打了grsecurity/PaX补丁,并且所有的程序都编译为Position Independent Executabl
    03-08
  • 日志审计与分析实验三(rsyslog服务器端和客户端配置)(Linux日志收集)
    日志审计与分析实验三(rsyslog服务器端和客户
     Linux日志收集一、实验目的:1、掌握rsyslog配置方法2、配置rsyslog服务收集其他Linux服务器日志:C/S架构:客户端将其日志上传到服务器端,通过对服务器端日志的查询,来实现对其他客户端的日志进行集中管理;下面实现就是通过两套机器来实现,(server:19
    03-08
  • Linux学习系列--如何在Linux中进行文件的管理
    Linux学习系列--如何在Linux中进行文件的管理
    文件在常见的Linux的文件系统中,经常使用能了解到的文件管理系统是分为多个文件夹进行管理的。如何查看文件路径 pwd ,在文件目录中,会有一个点(.)代表的是当前目录,两个点(..)代表的是当前目录的上层目录在Linux下,所有以点开始的文件都是“隐藏文件
    03-08
  • [JetBrains] 我想在 Linux 上使用 macOS 键绑定!
    [JetBrains] 我想在 Linux 上使用 macOS 键绑定
    很高兴认识你,我的名字是kitakkun。我最近开始实习,是工程界的新手。顺便说一句,这是我的第一篇文章。你最喜欢的操作系统是什么?视窗?苹果系统?还是Linux?我将它们全部用于不同的目的,但感觉就像 macOS ≒ LinuxWindows。一两个月前,我最喜欢 Linux
    03-08
  • linux 配置Socks51
    linux 配置Socks51
    ***大家耳熟能详,但是socks用到的人比较少,那什么是socks呢?请看第二段或者百度百科,socks分别有4和5两个版本,现在5为主流。工作中经常用***访问国外,但是同时国内的速度又慢了,让人很纠结,实际上这个时候可以考虑使用socks。指定某一个程序使用国外s
    02-10
  • linux下如何单独编译设备树? linux设备树是什
    答: make vendor/device_name.dtb  如: make freescale/fsl-1043a-rdb.dtb
    02-10
  • linux下mysql开启远程访问权限及防火墙开放3306端口
    linux下mysql开启远程访问权限及防火墙开放3306
    开启mysql的远程访问权限默认mysql的用户是没有远程访问的权限的,因此当程序跟数据库不在同一台服务器上时,我们需要开启mysql的远程访问权限。主流的有两种方法,改表法和授权法。相对而言,改表法比较容易一点,个人也是比较倾向于使用这种方法,因此,这
    02-10
  • 移植linux3.7到nuc900系列开发板遇到的问题
    通过移植学习linux新版本内核,大概了解一下内核变化。记录一下移植过程中遇到的问题或值得注意的地方。1,添加一款arm9芯片的支持首先修改\arch\arm\tools\mach-types文件添加一行w90p950evbMACH_W90P950EVBW90P950EVB同目录下的脚本文件在编译内核时会根据
    02-10
点击排行