热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux内核中断数值,Linux内核内核数据类型

将Linux移植到新的体系结构时,开发者遇到的若干问题都与不正确的数据类型有关。坚持使用严格的数据类型和使用-Wall-Wstrict-prototypes进行编译可

将Linux 移植到新的体系结构时,开发者遇到的若干问题都与不正确的数据类型有关。坚持使用严格的数据类型和使用 -Wall -Wstrict-prototypes 进行编译可能避免大部分的 bug。

-Wall

显示所有的警告

-Wstrict-prototypes

严格的检测原型,如果不一致,则出现警告

内核数据使用的数据类型主要分为3个类型: 标准C语言类型、确定大小的类型和特定内核对象的类型。

标准 C 语言类型

当需要“一个2字节填充符”或“用一个4字节字串来代表某个东西”,就不能使用标准C语言类型,因为在不同的体系结构,C 语言的数据类型所占的空间大小不同。而且有的构架,内核空间和用户空间的C数据类型所占空间大小也可能不同。

内核中的地址是unsigned long类型,指针大小和long类型相同。

尽管概念上地址是指针,但使用一个无符号整型可以更好地实现内存管理; 内核把物理内存看成一个巨型数组, 内存地址就是该数组的索引。我们可以方便地对指针取值,但直接处理内存地址时,我们几乎从不会以这种方式对他取值。使用一个整数类型避免了这种取值,因此避免了bug。所以,利用至少在 Linux 目前支持的所有平台上,指针和长整型始终是相同大小的这一事实,内核中内存地址常常是unsigned long。

C99 标准定义了 intptr_t 和 uintptr_t 类型,它们是能够保存指针值的整型变量。但没在 2.6 内核中几乎没使用。

确定大小的类型

内核:当需要知道你定义的数据的大小时,可以使用内核提供的下列数据类型:

u8; /* unsigned byte (8 bits) */

u16; /* unsigned word (16 bits) */

u32; /* unsigned 32-bit value */

u64; /* unsigned 64-bit value */

/*虽然很少需要有符号类型,但是如果需要,只要用 s 代替 u*/

用户空间:若一个程序用户空间需要使用这些类型,可在符号前加一个双下划线: __u8和其它类型是独立于 __KERNEL__ 定义的。

接口特定的类型(_t 类型)

内核中最常用的数据类型由它们自己的 typedef 声明,阻止了任何移植性问题。

“接口特定(interface-specific)”由某个库定义的一种数据类型, 以便为了某个特定的数据结构提供接口。

注意:

近来已经很少定义新的接口特定的类型。有许多内核开发者已经不再喜欢使用 typedef 语句,他们宁愿看到代码中直接使用的真实类型信息。

很多老的接口特定类型在内核中保留,他们不会很快消失。

即使没有定义接口特定类型,也应该始终是用和内核其他部分保持一致、适当的数据类型。只要驱动使用了这种“定制”类型的函数,但又不遵照约定,编译器会发出警告,这时使用 -Wall 编译器选项并小心去除所有的警告,就可以确信代码的可移植性了。

_t 类型的主要问题:

打印它们时,常常不容易选择正确的 printk 或 printf 格式。

打印接口特定的数据的最好方法是:将其强制转换为可能的最大类型(常常是 long 或 unsigned long ) 并用相应的格式打印。

时间间隔

当处理时间间隔时,不要假定每秒的jiffies个数,不是每个 Linux 平台都以固定的速度运行。当计算时间间隔时,要使用 HZ ( 每秒的定时器中断数 ) 来标定你的时间。

Hz:Linux核心每隔固定周期会发出timer interrupt (IRQ 0),HZ是用来定义每一秒有几次timer interrupts。举例来说,HZ为1000,代表每秒有1000次timer interrupts。

Tick:Tick是HZ的倒数,意即timer interrupt每发生一次中断的时间。如HZ为250时,tick为4毫秒(millisecond)。

Jiffies:Jiffies为Linux核心变数(unsigned long),它被用来记录系统自开机以来,已经过了多少tick。每发生一次timer interrupt,Jiffies变数会被加一。

页大小

当使用内存时,记住一个内存页是 PAGE_SIZE 字节, 不是 4KB。相关的宏定义是 PAGE_SIZE 和 PAGE_SHIFT(包含将一个地址移位来获得它的页号的位数)。如果用户空间程序需要这些信息,可以使用 getpagesize 库函数。

若一个驱动需要 16 KB 来暂存数据,一个可移植得解决方法是 get_order:

#include

int order = get_order(16*1024);

buf = get_free_pages(GFP_KERNEL, order);

/*get_order 的参数必须是 2 的幂*/

字节存储顺序

不要假设字节序。 代码应该编写成不依赖所操作数据的字节序的方式。

头文件定义:

#ifdef __ARMEB__

#include linux/byteorder/big_endian.h>

#else

#include linux/byteorder/little_endian.h>

#endif

在中定义了__BIG_ENDIAN ,

而在中定义了__LITTLE_ENDIAN,

这些依赖处理器的字节序当处理字节序问题时,需要编码一堆类似

#ifdef __LITTTLE_ENDIAN 的条件语句。

但是还有一个更好的方法:Linux 内核有一套宏定义来处理处理器字节序和特定字节序之间的转换。例如:

u32 cpu_to_le32 (u32);

u32 le32_to_cpu (u32);

/*这些宏定义将一个CPU使用的值转换成一个无符号的32位小头数值,无论 CPU 是大端还是小端,也不管是不是32 位处理器。在没有转换工作需要做时,返回未修改的值。*/

数据对齐

编写可移植代码而值得考虑的最后一个问题是如何访问未对齐的数据。存取不对齐的数据应当使用下列宏:

#include

get_unaligned(ptr);

put_unaligned(val, ptr);

这些宏是无类型的,并对各总数据项,不管是 1、2、4或 8 个字节,他们都有效,并且在所有内核版本中都有定义。

关于对齐的另一个问题是数据结构的跨平台移植性。同样的数据结构在不同的平台上可能被不同地编译。为了编写可以跨体系移植的数据结构,应当始终强制数��项的自然对齐。

自然对齐(natural alignment)指的是:数据项大小的整数倍的地址上存储数据项。 应当使用填充符避免强制自然对齐时编译器移动数据结构的字段,在数据结构中留下空洞。

为了目标处理器的良好性能,编译器可能悄悄地插入填充符到结构中,来保证每个成员是对齐的。若定义一个和设备要求的结构体相匹配结构,自动填充符会破坏这个意图。解决这个问题的方法是告诉编译器这个结构必须是"紧凑的", 不能增加填充符。例如下列的定义:

struct

{

u16 id;

u64 lun;

u16 reserved1;

u32 reserved2;

}

__attribute__ ((packed)) scsi;

/*如果在 64-位平台上编译这个结构,若没有 __attribute__ ((packed)), lun 成员可能在前面被添加 2 个或 6 个填充符字节。指针和错误值*/

可以在利用ARM9和USB摄像头进行视频采集的servfox源代码的spcaframe.h头文件中找到这种方法的实际应用:

struct frame_t{

char header[5];

int nbframe;

double seqtimes;

int deltatimes;

int w;

int h;

int size;

int format;

unsigned short bright;

unsigned short contrast;

unsigned short colors;

unsigned short exposure;

unsigned char wakeup;

int acknowledge;

} __attribute__ ((packed));

struct client_t{

char message[4];

unsigned char x;

unsigned char y;

unsigned char fps;

unsigned char updobright;

unsigned char updocontrast;

unsigned char updocolors;

unsigned char updoexposure;

unsigned char updosize;

unsigned char sleepon;

} __attribute__ ((packed));

Linux Kernel 的详细介绍:请点这里

Linux Kernel 的下载地址:请点这里

相关阅读:

Ubuntu 13.10 (Saucy Salamander) 内核已升级至 Linux Kernel 3.10 RC5 http://www.linuxidc.com/Linux/2013-06/86110.htm

0b1331709591d260c1c78e86d0c51c18.png



推荐阅读
  • 【妙】bug称它为数组越界的妙用
    1、聊一聊首先跟大家推荐一首非常温柔的歌曲,跑步的常听。本文主要把自己对C语言中柔性数组、零数组等等的理解分享给大家,并聊聊如何构建一种统一化的学习思想 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • 在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • centos 7.0 lnmp成功安装过程(很乱)
    下载nginx[rootlocalhostsrc]#wgethttp:nginx.orgdownloadnginx-1.7.9.tar.gz--2015-01-2412:55:2 ... [详细]
  • 本文通过基准测试(Benchmark)对.NET Core环境下Thrift和HTTP客户端的微服务通信性能进行对比分析。基准测试是一种评估系统或组件性能的方法,通过运行一系列标准化的测试来衡量其表现。 ... [详细]
  • Linux 防火墙与端口管理必备命令
    在使用 Linux 系统进行服务部署和问题排查时,防火墙和端口管理是不可或缺的操作。本文将详细介绍如何查看防火墙状态、端口占用情况,以及如何开放和关闭端口,帮助初学者更好地掌握这些技能。 ... [详细]
  • 本文整理了一份基础的嵌入式Linux工程师笔试题,涵盖填空题、编程题和简答题,旨在帮助考生更好地准备考试。 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 本文对比了杜甫《喜晴》的两种英文翻译版本:a. Pleased with Sunny Weather 和 b. Rejoicing in Clearing Weather。a 版由 alexcwlin 翻译并经 Adam Lam 编辑,b 版则由哈佛大学的宇文所安教授 (Prof. Stephen Owen) 翻译。 ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 在C语言程序开发中,调试和错误分析是确保代码正确性和效率的关键步骤。本文通过一个简单的递归函数示例,详细介绍了如何编写和调试C语言程序。具体而言,我们将创建一个名为 `factorial.c` 的文件,实现计算阶乘的功能,并通过逐步调试来分析和解决可能出现的错误。此外,文章还探讨了常见的调试工具和技术,如GDB和断点设置,以帮助开发者高效地定位和修复问题。 ... [详细]
author-avatar
fionafongkaian
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有