当前位置:  编程技术>移动开发
本页文章导读:
    ▪对ARM处理器的内存对齐有关问题(译)        对ARM处理器的内存对齐问题(译) 介绍 可以对齐或不对齐的内存访问。对齐的内存访问发生时的数据都位于其自然大小边界。例如,如果该数据类型的大小是4个字节,那么它属于被4整除.........
    ▪ 二个Activity之间传递数据_startActivityForResult()        2个Activity之间传递数据_startActivityForResult()首先需要用到函数有: startActivityForResult; public final void setResult(int resultCode, String data) protected void onActivityResult(int requestCode, int resultCode, Intent data) .........
    ▪ 智能360:汉语语音助手       智能360:中文语音助手   智能360是国内第一款也是用户量最多的中文智能语音助手,主要功能包括:语音命令、智能对话、生活服务查询、信息搜索。   近期独家推出休眠唤醒功能,.........

[1]对ARM处理器的内存对齐有关问题(译)
    来源: 互联网  发布时间: 2014-02-18
对ARM处理器的内存对齐问题(译)


介绍

可以对齐或不对齐的内存访问。对齐的内存访问发生时的数据都位于其自然大小边界。例如,如果该数据类型的大小是4个字节,那么它属于被4整除的内存地址是位于其自然大小边界。未对齐的内存访问发生在所有其他情况下(在上面的例子中,内存地址时,是不能被4整除)。 ARM处理器的设计有效地访问对齐的数据。在ARM处理器上试图访问未对齐的数据会导致不正确的数据或显着的性能损失(这些不同的症状会在稍后讨论)。与此相反,大多数CISC型处理器(即x86)的访问未对齐的数据是无害的。 这份文件将讨论一些比较常见的方式,一个应用程序可能会执行未对齐的内存访问,并提供一些建议的,以避免这些问题, 。 



症状

上述问题,适用于所有ARM架构。然而,根据MMU(内存管理单元)和操作系统支持的可用性,应用程序可能会看到不同的行为在不同的平台上。默认情况下,未对齐的内存访问不会被困住了,会导致不正确的数据。与功能的MMU的平台上,但是,OS捕获非对齐访问,它在运行时进行纠正。其结果将是正确的数据,但在10-20 CPU周期的成本。

常见原因


上述问题的类型转换适用于所有ARM架构。然而,根据MMU(内存管理单元)和操作系统支持的可用性,应用程序可能会看到不同的行为在不同的平台上。默认情况下,未对齐的内存访问不会被困住了,会导致不正确的数据。与功能的MMU的平台上,但是,OS捕获非对齐访问,它在运行时进行纠正。其结果将是正确的数据,但在10-20 CPU周期的成本。

代码:

void my_func(char *a) {
  int *b = (int *)a;
  DBGPRINTF("%d", *b);
}

这个简单的例子,可能会导致未对齐的内存访问,因为我们不能保证的char * a是一个4字节的边界上对齐。只要有可能,应避免这种类型的施放。

使用数据缓冲区
未对齐的内存访问的最常见的原因源于不正确地处理数据缓冲区。这些数据缓冲区可能包含任何数据从USB端口读取,通过网络,或从一个文件中。这个数据是很常见的包装,有没有插入填充,以确保数据在缓冲区内位于其自然大小边界。在这个例子中,我们会考虑的情况下,从文件加载的Windows BMP和解析的头。 的Windows BMP文件包含一个头的像素数据。的标头是由两个结构: 

代码:

typedef PACKED struct {
   unsigned short int type;         /* Magic identifier            */
   unsigned int size;               /* File size in bytes          */
   unsigned short int reserved1, reserved2;
   unsigned int offset;             /* Offset to image data, bytes */
} HEADER;

typedef PACKED struct {
   unsigned int size;               /* Header size in bytes      */
   int width,height;                /* Width and height of image */
   unsigned short int planes;       /* Number of colour planes   */
   unsigned short int bits;         /* Bits per pixel            */
   unsigned int compression;        /* Compression type          */
   unsigned int imagesize;          /* Image size in bytes       */
   int xresolution,yresolution;     /* Pixels per meter          */
   unsigned int ncolours;           /* Number of colours         */
   unsigned int importantcolours;   /* Important colours         */
} INFOHEADER;


请注意,在的HEADER和INFOHEADER结构的大小,分别为14和40字节。 让我们假设我们要确定在运行时的图像的宽度和高度。的代码来访问这些数据可能看起来像这样: 

代码:

#define INFOHEADER_OFFSET (sizeof(HEADER))
#define WIDTH_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, width))
#define HEIGHT_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, height))

int imageWidth, imageHeight;
void * fileBuf;

pMe->mFile = IFILEMGR_OpenFile(pMe->mFileMgr, "test.bmp", _OFM_READ);

if (pMe->mFile) {
   IFILE_GetInfo(pMe->mFile, &fileInfo);
   fileBuf = MALLOC(fileInfo.dwSize);

   if (fileBuf) {
      result = IFILE_Read(pMe->mFile, fileBuf, fileInfo.dwSize);

      if (result == fileInfo.dwSize) {
         imageWidth = *((uint32*)(((byte*)fileBuf) + WIDTH_OFFSET));
         imageHeight = *((uint32*)(((byte*)fileBuf) + HEIGHT_OFFSET));
      }
   }
}


注意的宽度和高度的偏移量。因为他们属于一个半字边界上,以上述方式访问这些值会导致未对齐的内存访问。下面列出的一些推荐的方法来避免这个问题。

推荐的


使用memcpy

我们的第一个选项是,只需执行MEMCPY从缓冲区中的数据到本地变量:

代码:

if (result == fileInfo.dwSize) {
   MEMCPY(&imageWidth,
          (((byte*)fileBuf)+WIDTH_OFFSET),
          sizeof(uint32));

   MEMCPY(&imageHeight,
          (((byte*)fileBuf)+HEIGHT_OFFSET), 
          sizeof(uint32));
}


其结果是,存储器被复制字节逐字节,避免任何疑问对准。 


包装的编译器指令

或者,我们可以使用压缩的编译器指令允许使用指针,直接将我们需要的数据,同时迫使编译器来处理对齐问题。在BREW环境中,PACKED被定义如下:

代码:

#ifdef __ARMCC_VERSION
  #define PACKED __packed
#else
  #define PACKED
#endif


包装形式,通过指定一个指针,ARM编译器将生成相应的说明来正确地访问内存,无论对齐。修改后的版本,上面的例子中,使用PACKED指针,如下: 

代码:

#define INFOHEADER_OFFSET (sizeof(HEADER))
#define WIDTH_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, width))
#define HEIGHT_OFFSET (INFOHEADER_OFFSET + offsetof(INFOHEADER, height))

PACKED uint32 * pImageWidth;
PACKED uint32 * pImageHeight;
uint32 imageWidth, imageHeight;
void * fileBuf;

pMe->mFile = IFILEMGR_OpenFile(pMe->mFileMgr, "test.bmp", _OFM_READ);

if (pMe->mFile) {
   IFILE_GetInfo(pMe->mFile, &fileInfo);
   fileBuf = MALLOC(fileInfo.dwSize);

   if (fileBuf) {
      result = IFILE_Read(pMe->mFile, fileBuf, fileInfo.dwSize);

      if (result == fileInfo.dwSize) {
         pImageWidth = (uint32*)(((byte*)fileBuf) + WIDTH_OFFSET);
         pImageHeight = (uint32*)(((byte*)fileBuf) + HEIGHT_OFFSET);
         imageWidth = *pImageWidth;
         imageHeight = *pImageHeight;
      }
   }
}




虽然程序员通常会无法控制标准化的数据格式,如BMP头在上面的例子中,当你定义自己的数据结构应确保奠定了良好的对齐方式中的数据定义对齐的数据结构。下面的基本示例演示了这样的原则:

代码:

#ifdef __ARMCC_VERSION
typedef PACKED struct {
   short a;		// offsetof(a) = 0
   int   b;		// offsetof(b) = 2 � misalignment problem!
   short c;		// offsetof(c) = 6
} BAD_STRUCT;
 
typedef struct {
   int   b;		// offsetof(b) = 0 � no problem!
   short a;		// offsetof(a) = 4
   short c;		// offsetof(c) = 6
} GOOD_STRUCT; 


通过简单地重新排列中,我们声明的结构成员,我们可以解决一些对齐的问题。另外请注意,如果未声明为包装,BAD_STRUCT,编译器通常会插入填充,每个字段对齐。然而,这通常是不希望的,因为它浪费内存和避免几乎总是可以简单地通过声明为了减小尺寸的字段。 

BREW模拟器测试


BREW模拟器3.1.2及以上版本提供了能够使数据对齐检查。BREW模拟器启用此功能时,将显示一个对话框,通知您的每一个未对齐的内存访问,并为您提供的选项对这一问题视而不见,或闯入的代码 ,请参阅BREW SDK用户文档一节揗isaligned数据异常支持更多信息,此功能。 注: 由于x86架构的访问未对齐的数据不会有任何问题,你可以不编译模拟器的DLL使用__packed指令(PACKED这就是为什么在WIN32环境下的空白被定义为)。这意味着,通过使用PACKED指针的非对齐访问,解决依旧会触发在模拟器的对齐检查。 


https://brewx.qualcomm.com/bws/content/gi/common/appseng/en/knowledgebase/docs/kb95.html


    
[2] 二个Activity之间传递数据_startActivityForResult()
    来源: 互联网  发布时间: 2014-02-18
2个Activity之间传递数据_startActivityForResult()

首先需要用到函数有:

startActivityForResult;
 public final void setResult(int resultCode, String data) 
 protected void onActivityResult(int requestCode, int resultCode, Intent data) 

例如 A 到 B, 从 B 得到 A 的数据:

A 到 B

static final int RG_REQUEST = 0; //判断回调函数的值
Intent intent = new Intent(); 
intent.setClass(A.this, B.class); 
startActivityForResult(intent,RG_REQUEST);

//在 B 中处理

Bundle bundle = new Bundle(); 
bundle.putString("DataKey", edittext.getText().toString());//给 bundle 写入数据 
Intent mIntent = new Intent(); 
mIntent.putExtras(bundle); 
setResult(RESULT_OK, mIntent); 
finish(); 

//最后在 A 的回调函数里面接收数据

if (requestCode == RG_REQUEST) { 
    if (resultCode == RESULT_CANCELED) 
        setTitle("Canceled..."); 
    else if(resultCode == RESULT_OK) { 
       setTitle((String)data.getCharSequenceExtra("DataKey")); 
    } 
 } 

//demo

http://download.csdn.net/detail/dannor2010/4898671




    
[3] 智能360:汉语语音助手
    来源: 互联网  发布时间: 2014-02-18
智能360:中文语音助手

  智能360是国内第一款也是用户量最多的中文智能语音助手,主要功能包括:语音命令、智能对话、生活服务查询、信息搜索。

  近期独家推出休眠唤醒功能,手机在休眠、锁频状态也能被唤醒,实现全程语音交互,目前国内其他语音助手包括Siri也不具备此功能。

  主要应用场景:

  1.双手不方便操作的时候,比如开车,操作电脑的时候,手机放在一边,可以全程语音控制

  2.在嘈杂环境中的时候,可以佩戴耳机,通过耳机进行语音控制,同样不需要使用双手

  3.手机落家里但找不到时,只需要喊一声:“智能360”就能唤醒智能360,从而快速找到手机。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3