0% found this document useful (0 votes)
7 views

cm06 Time

Uploaded by

Sabina H.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

cm06 Time

Uploaded by

Sabina H.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

CM06 : Time

Nicolas Magaud (largely inspired by many courses in


Strasbourg and Baku by Pierre David, Julien Montavont,
Vincent Loechner, Konul Aliyeva, etc.)

1 R.W. Stevens. Advanced Programming in the UNIX


Environment. 2013. Addison-Wesley
2 A. Tenenbaum and H. Bos. Modern Operating Systems:
Global Edition. Fourth edition. 2014. Pearson Education.
ISBN-13: 978-1292061429
Time

I Dealing with time is one of the basic tasks of an operating


system. It must obtain the time when starting, and then keep
counting as time passes.
I There are several solutions. The first one consists in reading
the time on a RTC (Real Time Clock) device. This requires
an hardware clock which runs on batteries when power is
switch off. The second one consists in asking the user for time
at startup (historical solution, still uses today, e.g. Raspberry
PI).
How to measure time ?

I The kernel must take control of the execution regularly. It


requires some hardware devices.
I It used to be based on the frequency of electricity which is
very stable (USA : 60Hz 60 interrruptions by second; Europe
50 Hz 50 interruptions by second).
I Nowadays, it is based on a quartz device (the frequency is
programmable by the kernel, depending on the kernel
configuration, 50 to 1000 interruptions by second (1 to 20
ms). Each interruption increases a counter. When the counter
reaches the frequency, it increments the time.
Units

I There are 2 main units for time (what time is it ? what date
is it ? and some ticks of a clock).
I The data-structure time_t can contain the current date and
time, the date and time of creation of a file, etc. It contains
the number of seconds since The Epoch. Epoch is January,
1st 1970 at 00:00:00 UTC (it used to be GMT before 1986).
Time is stored in UTC format (no time zone). time_t used
to be encoded using 32 bits (that would be an issue in 2038
(number of seconds ≥ 231 ). So it switched to 64 bits (from
Linux ≥ 3.17) A value of time time_t is easy to deal with by
the kernel, but not at all for the user.
Making it readable by a human
I How to convert a time_t structure into something readable ?
I It has to take into account the time zone, daylight saving,
dates of changes in daylight saving, years with 366 days,
additionnal seconds - e.g. 1 second was added to time after
23:59:59 at the end of December 31st, 2016.
I This can be achieved using some library functions localtime,
asctime,strftime. Indeed, it is not a concern of the kernel.
I clock_t This unit allows to compute the CPU time used by a
process for instance. It counts a nuber of ticks from the clock.
The unit depends on the configuration of the kernel. POSIX
provides a primitive long sysconf(int p) where p is a
parameter of configuration.
I E.g. freq = sysconf(_SC_CLK_TCK) returns the number of
tops of the clock in one second.
I It can be used to compute the CPU consumption of a process.
At each clock interruption, the kernel increases a counter of
the current process (+1). It provides an estimation of the
consumption.
Current time
I Functions
time_t time (time_t *heure)
int stime (time_t *heure)
time returns the current time (or -1) and using the provided
address. stime modifies the current time (it is only accessible
by the admins) This sort of time is sometimes called wall
clock.
I gettimeofday
int gettimeofday (struct timeval *tv, struct timezone *
This function was provided by the University of Berkeley and it
is more accurate. A timeval data-structure contains 2 fields:
I time_t tv_sec : number of seconds since the Epoch
I suseconds_t tv_usec : number of microseconds
time is now a library function based on the primitive
gettimeofday.
Example
I Example
tv_sec = 1 500 000 000 and tv_usec = 123 456 This
corresponds to July 14th 2017 at 02:40:00 and 123 456
microseconds UTC.
I Code
time_t heure ;
struct tm * tm ;
char * s1 , s2 [ MAX ] ;
size_t n ;
heure = time ( NULL ) ;
tm = localtime (& heure ) ;
s1 = asctime ( tm ) ;
printf ( " maintenant : % s \ n " , s1 ) ;
n = strftime ( s2 , sizeof s2 ,
" date = % d /% m /% Y a % H :% M :% S " , tm )
if ( n == 0)
printf ( " s2 is too small \ n " ) ;
else printf ( " now : % s \ n " , s2 ) ;
Clock

I clock_t times (struct tms *buf) stores the CPU


consumption at the address pointed by buf. The structure
tms contains 4 fields:
I tms_utime: CPU consumption in user mode
I tms_stime: CPU consumption in system mode
I tms_cutime : CPU consumption of all children in user mode
I tms_cstime: CPU consumption of all children in system mode
All fields are of type clock_t.
I times also returns the time distance from an arbitrary instant
in the past (or -1). Usually it corresponds to the start of the
kernel, which may not be very useful, there can be overflows.
Overall this value is not significant (except to check whether
it is -1 or not).
How to retrieve the CPU time of children processes ?

I The zombie state allows to transmit a return code (exit


primitive): CPU consumption utime and cutime into cutime
in the parent process. stime and cstime into cstime in the
parent process. These pieces of information are transmitted
when the wait command is executed by the parent process. If
a child is not finished yet, we can not have its consumption.
int getrusage (int who, struct rusage *res)
The times primitive is limited to CPU consumption. We need
a more general one to deal with all the ressources used by a
process.
I The parameter who can be either RUSAGE_SELF (own
consumption of the process itself) or RUSAGE_CHILDREN
(aggregate of the consumption of all children).
CPU time of the children

I Here are some of the field of the structure struct rusage:


I ru_utime: user mode CPU,
I ru_stime: system mode CPU
I ru_maxrss: max memory used
I ru_inblock: number of disk reads
I ru_outblock: number of disk writes
I Only the 2 first ones are normalized by POSIX. These values
are shipped back to the parent process when wait happens.
Files and dates
int utime (const char *path, const struct utimbuf *ut)
int utimes (const char *path, const struct timeval tv [2])
I We recall the main atrributes of a file :
I st_mtime : last modification of the contents of a file
I st_ctime: last modification of the i-node
I st_atime: last access
I The primitive utime allows to modify the dates of a file.
Fields of the structure utimbuf include actime (date of the
last access) and modtime (date of the last modification of the
contents of a file).
I Alternative approach: primitive utimes, behaves as utime
but using struct timeval like gettimeofday. tv[0] is the
last access and tv[1] is the last modification of the contents.
I Depending on which process is being executed on CPU and
when clock interruptions happen, computing consumption can
be added to wrong process.
I To have an accurate benchmark, run several times the same
program and collect the average time.
A library function: gmtime
#include <stdio.h>
#include <time.h>
#define BST (+1)
#define CCT (+8)

int main () {
time_t rawtime;
struct tm *info;

time(&rawtime);
info = gmtime(&rawtime ); /* Get GMT time */

printf("Current world clock:\n");


printf("London : %2d:%02d\n",
(info->tm_hour+BST)%24, info->tm_min);
printf("China : %2d:%02d\n",
(info->tm_hour+CCT)%24, info->tm_min);
return(0); }

You might also like