在Linux中查询RTC和NTP时间?

时间:2018-07-27 04:20:45

标签: c++ c linux time posix

Linux内核处理时间的方式有些复杂,因为它使用不同的时间源,并定期重新同步所有内容。有命令行工具(例如hwclock)可以显式查询RTC时间。但是,我想在C或C ++程序中以编程方式进行操作。如果Linux提供了命令行工具,那么我认为可以通过编程的方式来实现,但是到目前为止,我还没有找到正确的功能以及如何使用它。

所以我的问题是:

  • 如何在C或C ++程序中明确向系统询问RTC时间? (即get_rtc()函数的外观如何?)
  • 如何在C或C ++程序中明确向系统询问NTP时间? (即get_ntp()函数的外观如何?)

1 个答案:

答案 0 :(得分:0)

如果希望获得更高的精度,请使用time(time_t*)中的clock_gettime(clockid_t,struct timespec *)time.h header作为RTC时间。

有一个article describing how to get query NTP time(距离google search远)。

描述NTP数据包的结构

typedef struct
{

  uint8_t li_vn_mode;      // Eight bits. li, vn, and mode.
                           // li.   Two bits.   Leap indicator.
                           // vn.   Three bits. Version number of the protocol.
                           // mode. Three bits. Client will pick mode 3 for client.

  uint8_t stratum;         // Eight bits. Stratum level of the local clock.
  uint8_t poll;            // Eight bits. Maximum interval between successive messages.
  uint8_t precision;       // Eight bits. Precision of the local clock.

  uint32_t rootDelay;      // 32 bits. Total round trip delay time.
  uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
  uint32_t refId;          // 32 bits. Reference clock identifier.

  uint32_t refTm_s;        // 32 bits. Reference time-stamp seconds.
  uint32_t refTm_f;        // 32 bits. Reference time-stamp fraction of a second.

  uint32_t origTm_s;       // 32 bits. Originate time-stamp seconds.
  uint32_t origTm_f;       // 32 bits. Originate time-stamp fraction of a second.

  uint32_t rxTm_s;         // 32 bits. Received time-stamp seconds.
  uint32_t rxTm_f;         // 32 bits. Received time-stamp fraction of a second.

  uint32_t txTm_s;         // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
  uint32_t txTm_f;         // 32 bits. Transmit time-stamp fraction of a second.

} ntp_packet;              // Total: 384 bits or 48 bytes.

发送查询

// Call up the server using its IP address and port number.

if ( connect( sockfd, ( struct sockaddr * ) &serv_addr, sizeof( serv_addr) ) < 0 )
  error( "ERROR connecting" );

// Send it the NTP packet it wants. If n == -1, it failed.

n = write( sockfd, ( char* ) &packet, sizeof( ntp_packet ) );

if ( n < 0 )
  error( "ERROR writing to socket" );

阅读回复

// Wait and receive the packet back from the server. If n == -1, it failed.

n = read( sockfd, ( char* ) &packet, sizeof( ntp_packet ) );

if ( n < 0 )
  error( "ERROR reading from socket" );

并解析

// These two fields contain the time-stamp seconds as the packet left the NTP server.
// The number of seconds correspond to the seconds passed since 1900.
// ntohl() converts the bit/byte order from the network's to host's "endianness".

packet.txTm_s = ntohl( packet.txTm_s ); // Time-stamp seconds.
packet.txTm_f = ntohl( packet.txTm_f ); // Time-stamp fraction of a second.

// Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server.
// Subtract 70 years worth of seconds from the seconds since 1900.
// This leaves the seconds since the UNIX epoch of 1970.
// (1900)------------------(1970)**************************************(Time Packet Left the Server)

time_t txTm = ( time_t ) ( packet.txTm_s - NTP_TIMESTAMP_DELTA );