Step to UEFI (14) ----- EADK clock()

除了前面介绍的tm struct 和 time_t定义,标准C的库还有clock_t的定义。相比前面两者,这个是一个更加单纯的“计时”定义,前两者更像是日期时间的定义。

对于 clock_t ,在 EadkPkg_A2\StdLib\Include\time.h 有如下定义

/** An arithmetic type capable of representing values returned by clock(); **/
#ifdef _EFI_CLOCK_T
  typedef _EFI_CLOCK_T  clock_t;
  #undef _EFI_CLOCK_T
#endif

 

在 StdLib\Include\sys\EfiCdefs.h 有下面的定义

#define _EFI_CLOCK_T      UINT64

 

和 clock_t 配合的还有CLOCKS_PER_SEC ,定义了一秒中的Clock数

EadkPkg_A2\StdLib\Include\time.h

#define CLOCKS_PER_SEC  __getCPS()

 

这个函数的具体实现在 EadkPkg_A2\StdLib\LibC\Time\Time.c

clock_t
EFIAPI
__getCPS(void)
{
  return gMD->ClocksPerSecond;
}

 

函数 clock() 的作用是取得从程序开始运行的处理器时钟数。特别需要注意:在NT32模拟环境中和实际环境中,这个函数是不同的。之前提到过,如果想在NT32环境中正常使用C Library,必须在AppPkg.dsc中做一些修改

[LibraryClasses.IA32]
  #TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
  ## Comment out the above line and un-comment the line below for running under Nt32 emulation.
  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf

 

当然,修改之后,能在NT32环境中运行了,但是无法取得clock值。输出始终为 0。

clock1

为了验证,我尝试在实际环境下测试。首先是要将上面的设定恢复原装。恢复完之后无法通过编译,需要修改成下面的样子(下面ORG给出的是原来的路径)。

[LibraryClasses.IA32]
  #ORG TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
  TimerLib|PerformancePkg/Library/TscTimerLib/DxeTscTimerLib.inf
  ## Comment out the above line and un-comment the line below for running under Nt32 emulation.
  #TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf

 

之后,我用WinISO做了一个 ISO镜像,将main.efi放在iso文件中,直接挂接到virtualbox的虚拟机中(4.3.10 r93012),发现运行之后无任何输出.

clock2

拷贝到实际机器上运行,看起来结果正常:

clock

这次实验使用的代码如下,依然是从 Demo 的Main.c中修改而来

/** @file
    A simple, basic, application showing how the Hello application could be
    built using the "Standard C Libraries" from StdLib.

    Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
    This program and the accompanying materials
    are licensed and made available under the terms and conditions of the BSD License
    which accompanies this distribution. The full text of the license may be found at
    http://opensource.org/licenses/bsd-license.

    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
//#include  <Uefi.h>
//#include  <Library/UefiLib.h>
//#include  <Library/ShellCEntryLib.h>

#include  <stdio.h>
#include  <time.h>

/***
  Demonstrates basic workings of the main() function by displaying a
  welcoming message.

  Note that the UEFI command line is composed of 16-bit UCS2 wide characters.
  The easiest way to access the command line parameters is to cast Argv as:
      wchar_t **wArgv = (wchar_t **)Argv;

  @param[in]  Argc    Number of argument tokens pointed to by Argv.
  @param[in]  Argv    Array of Argc pointers to command line tokens.

  @retval  0         The application exited normally.
  @retval  Other     An error occurred.
***/
int
EFIAPI
main (
  IN int Argc,
  IN char **Argv
  )
{
  int i;
  printf("Sizeof Clock_T %d\n",sizeof(clock_t));

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

  printf("Start %d\n",clock());

  for (i=1;i<0xFFFF; i++)  
   {
   }

  printf("End %d\n",clock());

  return EFI_SUCCESS;
}

 

依旧是使用 AppPkg 的环境进行编译。

代码下载

Main

编译的可以在实际机器上运行的EFI文件

Main_Actual

根据上面的 CLOCKS_PER_SEC 我们同样能做出来一个测算当前CPU频率的程序。同时我们也完全可以写出一个 delay 函数(我在C 标准库中查看了一下,惊奇的发现这个函数并非标准函数......)

为了总结关于时间的库函数,总结下面这个图表

time lib

参考:
1.http://ganquan.info/standard-c/function/clock

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注