Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which clock should be used for inter process communication in linux?

Tags:

c

linux

ipc

clock

I have implemented two single thread process A & B with two msg queue [separate queue for send and receive]. Process A will send a message to B and wait for reply in the receive queue.

I want to send a time-stamp from process A to process B. If process B receives the message after 10 second, i want to send a Error string from process B to A.

Accuracy should be in milliseconds.

In process A i used ,

  struct timespec   msg_dispatch_time;
  clock_gettime(CLOCK_REALTIME, &msg_dispatch_time);
  :
  :
  add_timestamp_in_msg(msg, msg_dispatch_time);
  :
  if (msgsnd(msqid, msg, sizeof(msg), msgflg) == -1)
      perror("msgop: msgsnd failed");

In process B,

  struct timespec   msg_dispatch_time;
  struct timespec  msg_receive_time;
  :
  clock_gettime(CLOCK_REALTIME, &msg_received_time);
  :
  if( !(time_diff(msg_received_time, msg_dispatch_time) >= 10 ))
      msgsnd(msqid, &sbuf, buf_length, msg_flag)
  else
  {
      /*send the error string.*/
      //msgsnd(msgid,)
  }

My question is,

1) How to write a time_diff function here with millisecond accuracy to compare against 10 seconds?

   if( !(time_diff(msg_received_time, msg_dispatch_time) >= 10 ))



    /********Existing time diff code******************/
  long int time_diff (struct timeval time1, struct timeval time2)
  {
      struct timeval diff, 

      if (time1.tv_usec < time2.tv_usec) {
          time1.tv_usec += 1000000;
          time1.tv_sec--;
      }
      diff.tv_usec = time1.tv_usec - time2.tv_usec;
      diff.tv_sec = time1.tv_sec - time2.tv_sec;    
      return diff.tv_sec; //return the diff in second
  }

2) Is clock_gettime is fine to use across process in the same system?

like image 759
BEPP Avatar asked Mar 14 '26 01:03

BEPP


1 Answers

If you wish to keep using the struct timespec type, then I recommend using a difftime() equivalent for struct timespec type, i.e.

double difftimespec(const struct timespec after, const struct timespec before)
{
    return (double)(after.tv_sec - before.tv_sec)
         + (double)(after.tv_nsec - before.tv_nsec) / 1000000000.0;
}

However, I think there exists a better option for your overall use case.

If you are satisfied for your program to work till year 2242, you could use a 64-bit signed integer to hold the number of nanoseconds since Epoch. For binary messages, it is a much easier format to handle than struct timespec. Essentially:

#define _POSIX_C_SOURCE 200809L
#include <stdint.h>
#include <time.h>

typedef  int64_t     nstime;
#define  NSTIME_MIN  INT64_MIN
#define  NSTIME_MAX  INT64_MAX

nstime nstime_realtime(void)
{
    struct timespec  ts;

    if (clock_gettime(CLOCK_REALTIME, &ts))
        return NSTIME_MIN;

    return ((nstime)ts.tv_sec * 1000000000)
         + (nstime)ts.tv_nsec;
}

double nstime_secs(const nstime ns)
{
    return (double)ns / 1000000000.0;
}

struct timespec nstime_timespec(const nstime ns)
{
    struct timespec  ts;

    if (ns < 0) {
        ts.tv_sec = (time_t)(ns / -1000000000);
        ts.tv_nsec = -(long)((-ns) % 1000000000);
        if (ts.tv_nsec < 0L) {
            ts.tv_sec--;
            ts.tv_nsec += 1000000000L;
        }
    } else {
        ts.tv_sec = (time_t)(ns / 1000000000);
        ts.tv_nsec = (long)(ns % 1000000000);
    }
}

You can add and substract nstime timestamps any way you wish, and they are suitable for binary storage, too (byte order (aka endianness) issues notwithstanding).

(Note that the code above is untested, and I consider it public domain/CC0.)


Using clock_gettime() is fine. Both CLOCK_REALTIME and CLOCK_MONOTONIC are system-wide, i.e. should report the exact same results in different processes, if executed at the same physical moment.

CLOCK_REALTIME is available in all POSIXy systems, but CLOCK_MONOTONIC is optional. Both are immune to daylight savings time changes. Incremental NTP adjustments affect both. Manual changes to system time by an administrator only affect CLOCK_REALTIME. The epoch for CLOCK_REALTIME is currently Jan 1, 1970, 00:00:00, but it is unspecified for CLOCK_MONOTONIC.

Personally, I recommend using clock_gettime(CLOCK_REALTIME,), because then your application can talk across processes in a cluster, not just on a local machine; cluster nodes may use different epochs for CLOCK_MONOTONIC.

like image 155
Nominal Animal Avatar answered Mar 16 '26 17:03

Nominal Animal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!