linux并不是严格意义上的实时操作系统,为了实际需要,工程师们必须想尽办法来祢补这一不足,于是出现了rtlinux和rtai等并不强调商业性的软件。免费的rtlinux显然庞大而并不兼容大部分的嵌入式平台,最新版本的rtlinux也只能支持I386和PPC而已。Rtai是不错的选择,但要把它移植到你的平台上去,为了适应你的linux版本,你的CPU,你必须的花费许多的工作,比如说最近比较流行的AT91RM9200DK,光修改linux版本补丁就要花费许多的功夫。Rtlinux和rtai为了增强linux操作系统的实时性,主要是通过开辟内核模块与应用程序之间可以共享的内存快来实现的。它们在内核空间控制硬实时任务的运行,并通过一个名为FIFO的共享内存块来与应用程序进行通信。他们是很不错的软件,我想用不了多久他们就会具备更强大的可移植性。但我在本文主要是想详细的介绍一个适合小型使用的增强linux操作系统实时性的方法。当然,原理也是开辟一个实时应用程序与内核模块之间可以共享的内存。

众所周知,内核空间和用户空间只能通过系统调用来共享数据,如果进程要等待一个中断的发生,它所能做的就是把自己挂在等待队列里,直到中断服务程序来唤醒它。然后,进程才把内核空间的的数据通过特定的系统调用写到用户空间里。大部分程序员为了避免这样造成的不可忍耐的延时,都会把对数据的操作都放在内核空间里运行,也就是扩大中断服务程序的功能。但如果开辟两个空间可以共享的内存块,程序员就不必要这么为难了。我以AT91RM9200DK的平台为例,linux操作系统版本为2.4.19-rmk7,不需要半天时间,就可以实现两个空间的共享内存。

AT91RM9200DK的SDRAM的大小为31Mbyte,正常情况下,System RAM的大小也是31Mbyte,我们要把31Mbyte的高端地址空出2M来作为我们的共享内存块,这个内存块是独立的,不能为linux操作系统的内存管理所用了。首先必须通知内核它的内存只有30Mbyte了,我的方法是在u-boot的环境变量里设置mem=29M。然后在include/asm-arm/目录下建立头文件:new_fifo.h,代码如下:

#ifndef NEW_FIFO

#define NEW_FIFO

#endif

#ifdef NEW_FIFO

#define AT91_NEW_FIFO_BASE 0x21d00000

#define num_base(a) (0x21d00000 (0x1000 * a))

/SDRAM最后1M空间的起始地址,我把它以0x1000Byte的大小划分成256个FIFO/

#define SPI_NUM_FIFO 2

/SPI设备占用了一个FIFO,是第三个FIFO/

#define MAX_NUM_FIFO 256

#define READONLY 0

#define READEN 0x1

#define WRITONLY 0x2

#define WRITEN 0x4

typedef struct new_fifo{

int code,key;

int start,size;

int flags;

char data[4000]; /数据区/

int endflag;

} *at91_fifo;

static char * new_fifo_fun(int num,int flags,int code,int size)

{

at91_fifo fifo_p;

int num_addr;

char * data;

if(num > MAX_NUM_FIFO)

return -1;

num_addr = num_base(num);

/printk("the num_addr is %p \n",num_addr);

fifo_p = (at91_fifo)ioremap(num_addr,(1024 * 4));

/ printk("the fifo_p is %p\n",fifo_p);

fifo_p->code = code;

/ printk("the code addr is %p\n",(fifo_p->code));

fifo_p->flags = flags;

fifo_p->size =size;

data = (fifo_p->data[0]);

/printk("the data addr is %p\n",data);

return data;

}

#endif

在设备驱动程序中,首先在注册中断服务程序之前,要调用new_fifo_fun函数,得到数据区首地址的指针。这个指针在这个设备驱动程序中可被设置成全程变量。然后在中断服务程序中直接对数据进行读写。

比如说,在文件头部写:

static char * data;

然后在初始化文件中,注册中断之前加入:

data = new_fifo_fun(SPI_NUM_FIFO,WRITEN,0,100);

最后在中断服务程序中加入:

for(i=0;i100;i )

*(data ) = i;

接下来,需要做的工作必须到用户空间去做,我设计了一个简单的进程,就是读取SPI的FIFO空间的数据,通过/dev/mem来读取SDRAM高地址的数值,使用的是mmap函数,全文如下:

#include sys/types.h>

#include stdio.h>

#include sys/stat.h>

#include unistd.h>

#include sys/mman.h>

#include sys/fcntl.h>

#include dirent.h>

#include stdlib.h>

#include errno.h>

#include string.h>

#include assert.h>

#include getopt.h>

main()

{

int *mmaddr;

int i,fd;

fd=open("/dev/mem", O_RDWR);

mmaddr = (int *)mmap(0, 1024,PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0x21d02000);

for(i=0;i10;i )

{printf("the mmaddr data is %p\n",*(mmaddr ));

printf("%d\n",i);

}

}

打印出来的结果是:

the mmaddr data is (nil)

0

the mmaddr data is 0xd24e92c2

1

the mmaddr data is 0xf01ab26d

2

the mmaddr data is 0x64

3

the mmaddr data is 0x4

4

the mmaddr data is 0x3020100

5

the mmaddr data is 0x7060504

6

the mmaddr data is 0xb0a0908

7

the mmaddr data is 0xf0e0d0c

8

the mmaddr data is 0x13121110

9

太好了,说明我们数据读写都成功拉。同样的,如果要把用户空间的数据写到内核空间也是可以的。只不过实时系统比较少有这样的要求。如果这个时候,进程在用户空间监视FIFO里的某几个数值,当这个数值变得符合要求的时候,进程认为中断已经发生,并可以读取数据了。

但是,直接对共享内存空间的数据操作比通过系统调用能够增加多少的实时性呢?这个我没有进行精确的计算,但以前我做过一个试验:用2.4.14版本的linux,平台以MPC823E(motorola的PPC)为CPU,主频为50M,扩展了一个语音压缩调制系统,该系统的中断线中断频率是几乎1ms一次。使用系统调用的结果就是10个中断的数据几乎就被有冲掉3-4个,因为语音的要求系统又不能开更多的缓存,后来就使用了这篇文章里说的这个方法,0.1ms级的中断都扛住了。这对以后平台上跑更多的进程比较有保障。

linux中断共享程序实现,如何在非实时linux上实现实时应用程序与内核模块之间共享存储器...相关推荐

  1. linux默认开启sudo_Sudo漏洞允许非特权Linux和macOS用户以root身份运行命令

    原标题:Sudo漏洞允许非特权Linux和macOS用户以root身份运行命令 苹果安全团队成员Joe Vennix发现了sudo实用程序中的一个重要漏洞,即在特定配置下,它可能允许低特权用户或恶意程 ...

  2. Linux中断子系统

    首先感谢原文作者 LoyenWang 的分享,可以点击章节阅读原作者原文,或者查看本文的转载地址,再次感谢原作者分享,已经在公众号上征得作者同意. 说明: Kernel版本:4.14 ARM64处理器 ...

  3. Linux中断子系统-通用框架处理

    背景 Kernel版本:4.14 ARM64处理器,Contex-A53,双核 使用工具:Source Insight 3.5, Visio 1. 概述 <Linux中断子系统(一)-中断控制器 ...

  4. 浅入浅出linux中断子系统

    浅入浅出linux中断子系统,如需深入,直接跳转重要参考章节. 什么是中断? 当CPU被某些信号触发,CPU暂停当前工作,转而处理信号的事件,简单的称它为中断,这个信号可以是系统外设的信号,也可能是芯 ...

  5. Linux中断子系统(四)之中断申请注册

    Linux中断子系统(四)之中断申请注册 备注:   1. Kernel版本:5.4   2. 使用工具:Source Insight 4.0   3. 参考博客: Linux中断子系统(一)中断控制 ...

  6. Linux中断线程化的优势,记一个实时Linux的中断线程化问题

    背景 有一个项目对实时性要求比较高,于是在linux内核上打了RT_PREEMPT补丁. 最终碰到的一个问题是,芯片本身性能不强,CPU资源不足,急需优化. 初步分析 看了下cpu占用率,除了主应用之 ...

  7. rtos与linux软件开发,实时Linux和RTOS的基本特性及技术进行比较

    描述 体系结构异同 对实时操作系统(RTOS)特性进行比较和分析.对于我们刚接触这个操作系统时一定要对他们要有一定的了解,我们先对实时操作系统来了解下,它就是指当外界事件或数据产生时,能够接受并以足够 ...

  8. arm Linux 中断管理机制

    关键词:GIC.IAR.EOI.SGI/PPI/SPI.中断映射.中断异常向量.中断上下文.内核中断线程.中断注册. 1.1 ARM支持中断类型 ARM GIC-v2支持三种类型的中断: SGI:软件 ...

  9. Linux 中断所有知识点

    目录 Linux 中断管理机制 GIC 硬件原理 GIC v3中断类别 GIC v3 组成 中断路由 中断状态机 中断处理流程 GIC 驱动 设备树 初始化 中断的映射 数据结构 中断控制器注册 ir ...

最新文章

  1. 由一次奇怪的编译出错想起的
  2. python 屏幕找图 点击_捕获屏幕并查找参考图像
  3. Java 判断字符串是否为空的四种方法、优缺点与注意事项
  4. 使用hexo yeele主题搭建个人博客
  5. Delphi面向对象学习随笔六:接口
  6. 简单的一道题 背包问题
  7. JS正则判断输入框是否仅仅含有汉字、字母和数字
  8. Servlet使用基本步骤及功能实现
  9. Kylin修改默认hbase namespace命名空间default的解决方案
  10. python代码命令行tab补齐_Python语言交互模式下命令tab补全
  11. 依赖反转原理,IoC容器和依赖注入:第2部分
  12. 编程语言对比 字符串
  13. 总结js中数据类型的bool值及其比较
  14. python教程系列(三.6.2、XML)
  15. 系统名称:联想ThinkpadOEM Win7SP1简体中文旗舰版原版光盘镜像64位
  16. 5miles:这家电商公司,想做推动区块链技术落地的标杆
  17. 相对标准偏差用计算机,公路工程用计算器计算相对标准偏差(RSD)
  18. 「L2TP」- Layer 2 Tunneling Protocol @20210210
  19. Batch Renormalization
  20. Tetrate万凯:SkyWalking MAL的监控虚拟机和Kubernetes实践

热门文章

  1. 为什么UI线程中创建Handler可以不传Looper?
  2. 2021年大数据常用语言Scala(十):基础语法学习 方法
  3. HarmonyOS Java工程目录结构
  4. Android 自定义 —— View lineTo 与 rLineTo 的区别
  5. Android Studio 工具栏消失了 设置回来
  6. 计数排序之python
  7. 尼克的任务 dp 洛谷1280
  8. 调用bat文件执行java文件
  9. devexpress toolbar 填充整行宽度
  10. LeetCode: Longest Consecutive Sequence