I am using uClibc on arm linux, in which there is not a
CLOCK_MONOTONIC implementation. Below is its code:
int clock_gettime(clockid_t clock_id, struct timespec* tp)
{
struct timeval tv;
int retval = -1;
switch (clock_id) {
case CLOCK_REALTIME:
retval = gettimeofday(&tv, NULL);
if (retval == 0) {
TIMEVAL_TO_TIMESPEC(&tv, tp);
}
break;
default:
errno = EINVAL;
break;
}
return retval;
}
So is there any other alternative choice if I want to do some measure
thing which can not be affected by user changing of system time?
Thanks.
-
narke
Since this is presumably something embedded, why is this a problem? If
the answer should be 'because I am running ntpdate from cron and the
system times jumps around like wounded rabbit every now and then', the
easiest solution would be to stop that: Set the time once during boot
(and don't set it from some random embedded, battery-powered
oscillator, because that's close to setting it to a random value) and
run an NTP-daemon, eg ntpd, afterwards. The net effect would be that
the system clock is both correct and monotonic.
If your kernel has the corresponding system call (sys_clock_gettime,
263), you could simply implement the interface routine/ macro yourself
or copy it from somewhere, eg glibc. Otherwise, the only userspace
option is to use a periodic timer to implement a monotonic clock
yourself.
Our system is an embedded device (terminal) which communicates with
another pc system called master station (MS). The MS need to change
the terminal's system time by sending it a specific datagram. I don't
know how often this will happen, but it is in the requirement list.
When the system time changed, the programs in the terminal may
behavior incorrectly if it using some logic such as "if time(NULL) -
prevTime > 5", this kind of code do include the communication program
itself. So, what I am looking for another kind of "time()" function,
its value need not to be absolutely meaningful but its relative value
should not be changed and keep monotonic. In PC Linux,
clock_gettime(CLOCK_MONOTONIC, tp) is just made for it, but this
routine is not implemented in ARM uClibc. So you understand my
problem?
> If your kernel has the corresponding system call (sys_clock_gettime,
> 263), you could simply implement the interface routine/ macro yourself
> or copy it from somewhere, eg glibc. Otherwise, the only userspace
> option is to use a periodic timer to implement a monotonic clock
> yourself.
In the linux-2.6 source kernel/posix-timers.c I found the definition
of the sys_clock_gettime, but the there is no a man page for it on my
pc linux. Is it a system API? How should I use it? I am not so clear.
asmlinkage long
sys_clock_gettime(const clockid_t which_clock, struct timespec __user
*tp)
{
struct timespec kernel_tp;
int error;
if (invalid_clockid(which_clock))
return -EINVAL;
error = CLOCK_DISPATCH(which_clock, clock_get,
(which_clock, &kernel_tp));
if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
error = -EFAULT;
return error;
}
That is the part of the linux kernel that implements the system call. To
make a system call you need do some special magic which depends on the
system, it isn't just a function that you can call. Your system library
may provide a function syscall(2) that does this for you, otherwise you
need to implement it. Probably the first place to look is at the source
of your libc if you have it.
viza
syscall(2) should be provided by uclibc for ARM (it is in 'mine', but
that's a fairly old version [0.9.19]). The other option would be to
use a _syscallN-macro to create a function invoking a particular
system call. This is no longer possible with glibc, but may still be
for the C-library in use. A real-world example would be:
_syscall3(int, madvise, void *, start, size_t, length, int, advice);
'madvise' was not originally provided by the uclibc-version used by
me. The invocation above declares 'madvise' as system call which takes
three arguments of types void *, size_t and int and returns int.
> So is there any other alternative choice if I want to do some measure
> thing which can not be affected by user changing of system time?
You can check the system uptime by reading /proc/uptime.
Another possibility is to track a 'system start time' value. You
update the 'system start time' value every time the system time is
changed (system start time = system time - uptime). You then get an
'offset' you can apply to system time to 'normalize' it.
You then store times as a pair: [system start time, system time]. To
compare two times, you apply the difference between the system start
times, if any.
There might be a much better way, depending on the precise details of
your problem.
DS
The Linux kernel and ARM cross compiler are provided by our vendor.
The cross compiler is based on uClibc 0.9.26. After I checked I
found,
1, It does get a syscall(2)
2. It does not get the system interface number definitions for the
system call sys_clock_gettime and sys_clock_getres. (i.e. it does not
get a __NR_gettime or SYS_gettime in its .h file bits/sysnum.h and
bits/syscall.h )
Does this imply that the kernel on hand may not support
sys_clock_gettime and sys_clock_getres at all? If this is true,
however I play with syscall(2), it will fail definitely.
-
narke
I think I can try this if /proc/uptime is monotonic. I am just afraid
that reading of a file is slow.
>
> Another possibility is to track a 'system start time' value. You
> update the 'system start time' value every time the system time is
> changed (system start time = system time - uptime). You then get an
> 'offset' you can apply to system time to 'normalize' it.
>
> You then store times as a pair: [system start time, system time]. To
> compare two times, you apply the difference between the system start
> times, if any.
I don't well understand this. but I think this doesn't make big
difference from using /proc/uptime directly.
[...]
>> That is the part of the linux kernel that implements the system call. To
>> make a system call you need do some special magic which depends on the
>> system, it isn't just a function that you can call. Your system library
>> may provide a function syscall(2) that does this for you, otherwise you
>> need to implement it. Probably the first place to look is at the source
>> of your libc if you have it.
>>
>> viza
>
> The Linux kernel and ARM cross compiler are provided by our vendor.
> The cross compiler is based on uClibc 0.9.26. After I checked I
> found,
>
> 1, It does get a syscall(2)
> 2. It does not get the system interface number definitions for the
> system call sys_clock_gettime and sys_clock_getres. (i.e. it does not
> get a __NR_gettime or SYS_gettime in its .h file bits/sysnum.h and
> bits/syscall.h )
>
> Does this imply that the kernel on hand may not support
> sys_clock_gettime and sys_clock_getres at all?
No. This implies that you are clueless and unwilling to learn.
> > You then store times as a pair: [system start time, system time]. To
> > compare two times, you apply the difference between the system start
> > times, if any.
> I don't well understand this. but I think this doesn't make big
> difference from using /proc/uptime directly.
It does, because you then don't have to read /proc/uptime every time.
DS
If it works, my program need to be noticed every time system time is
being changed by other processes or by another user. This is practicly
impossible. Another problem with the method is: If I can really be
noticed, why should I still bother with the uptime? Every time when
the system time is being change, I can calculate the offset = new time
- old time. I don't need uptime at all.
> If it works, my program need to be noticed every time system time is
> being changed by other processes or by another user.
No, only every time you care if the system time has changed.
For example, if your timer granularity is one second, you only need to
check the system time every second. This is so no matter how many
timers you set, fire, cancel, or check.
> This is practicly
> impossible. Another problem with the method is: If I can really be
> noticed, why should I still bother with the uptime? Every time when
> the system time is being change, I can calculate the offset = new time
> - old time. I don't need uptime at all.
Because then you'd need to update every time you had stored,
regardless of where you had stored it. The idea is to bound the number
of calculations and not require you to keep track of where you kept
every time so you can update them all at the same time.
DS