Search code examples
c++clinuxtimeposix

Query RTC and NTP time in Linux?


The way the Linux kernel handle time is somewhat complicated as it uses different source of time, and regularly resynchronize everything. There are command-line tools (like hwclock) to query the RTC time explicitely. However I would like to do it programmatically, inside a C or C++ program. If Linux provides command-line tools, I assume that there is a way to do this programmatically, but so far I haven't been able to find the right function, and how to use it.

So my questions are:

  • How to explicitly ask the system for the RTC time inside a C or C++ program? (ie what a get_rtc() function would look like?)
  • How to explicitly ask the system for the NTP time inside a C or C++ program? (ie what a get_ntp() function would look like?)

Solution

  • Use time(time_t*) or clock_gettime(clockid_t,struct timespec *) if you wish for more precision, from the time.h header for the RTC time.

    there is an article describing how to get query NTP time ( which was a google search away ).

    describing the structure of an NTP packet

    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.
    

    sending a query

    // 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" );
    

    reading the response

    // 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" );
    

    and parsing it

    // 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 );