Naveen Kumar Naveen Kumar - 4 months ago 18
Linux Question

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

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)
/*send the error string.*/

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;
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?


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_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.