原理:为什么负数的表示方法是补码
正数 :原码
负数 :补码(反码+1)
因为需要 相同的正数和负数和需要为0 。
20 + -20 = 0
0001 0100
+1110 1011
1111 1111 + 1 = 0
定义 jiffies /Tick为 无符号32bits , 如何判断回绕
如果HZ为1000,那么回绕时间将只有50天左 右。
使用这几个宏进行判断
#define time_after(unknown,known) ((long)(known) - (long)(unknown)<0)
#define time_before(unkonwn,known) ((long)(unknown) - (long)(known)<0)
#define time_after_eq(unknown,known) ((long)(unknown) - (long)(known)>=0)
#define time_before_eq(unknown,known) ((long)(known) -(long)(unknown)>=0)
//当前时间 jiffies , 记录timeout的时间
unsigned long timeout = jiffies + HZ/2; /* timeout in 0.5s */
//一段时间以后
if (time_before(jiffies, timeout)) {
} else{
}
time_after等比较时间先后的宏背后的原理
#define uc_after(a, b) ((char)(b) - (char)(a) < 0)
假定当接近回绕的时候,b为临近8位无符号整型最大值附近的一个固定值254
a | b | (char)(b) - (char)(a) |
---|---|---|
254 (1111 1110) | 254(1111 1110) | 0 |
255 (1111 1111) | - 1 | |
0 (0) | - 2 | |
1 (1) | - 3 | |
… | ||
124 | -126 | |
125 | -127 | |
126 ( 0111 1110) | -128 | |
127 (0111 1111) | 127 | |
128 (1000 0000) | 126 | |
… | ||
252 | 2 | |
253 | 1 |
可以看出从 127 以后开始不对了。
使用这个宏必须满足一个条件。
两个值之间相差从逻辑值来讲应小于有符号整型的最大值。
如果HZ为1000,两个值之间相差小于25天左 右。
linux 常用时间结构
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
typedef __kernel_time_t time_t; //long
struct timeval
{
__kernel_time_t tv_sec; //从Epoch1970-01-01 00:00:00 UTC开始的秒数 ,long
__suseconds_t tv_usec; /* Microseconds. */
struct tm {
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */
int tm_isdst; /* daylight savings time flag */
};
};
获取系统时间
//获取当前时间time_t(秒) 从Epoch
time_t t=time(NULL);
//timeval 从Epoch
int gettimeofday(struct timeval *tv, struct timezone *tz);
时间转换和时间差
//转换time_t ==> struct tm,0时区的标准时间
struct tm *gmtime(const time_t *timep);
//转换time_t ==> struct tm
struct tm *localtime(const time_t *timep);
//线程安全,传入返回结果的指针
struct tm *localtime_r(const time_t *timep, struct tm *result);
//转换struct tm==> time_t
time_t mktime(struct tm *tm);
//double 和timespec转换
// struct timeval to double
double tv2double(const struct timeval *val)
{
double rv;
rv = val->tv_sec;
rv += (double) val->tv_usec / uSecsPerSec;
return rv;
}
// struct timespec to double
double ts2double(const struct timespec *val)
{
double rv;
rv = val->tv_sec;
rv += (double) val->tv_nsec / nSecsPerSec;
return rv;
}
// double to struct timespec
struct timespec double2ts(double amt)
{
struct timespec rv;
rv.tv_sec = floor(amt); //floor ceil
rv.tv_nsec = (amt - rv.tv_sec) * nSecsPerSec;
// TODO: Handle cases where amt is negative
while ((unsigned) rv.tv_nsec >= nSecsPerSec) {
rv.tv_nsec -= nSecsPerSec;
rv.tv_sec++;
}
return rv;
}
//时间差timespec
struct timespec tsDelta(const struct timespec *first,
const struct timespec *second)
{
struct timespec rv;
assert(first != NULL);
assert(second != NULL);
assert(first->tv_nsec >= 0 && first->tv_nsec < nSecsPerSec);
assert(second->tv_nsec >= 0 && second->tv_nsec < nSecsPerSec);
rv.tv_sec = second->tv_sec - first->tv_sec;
if (second->tv_nsec >= first->tv_nsec) {
rv.tv_nsec = second->tv_nsec - first->tv_nsec;
} else {
rv.tv_nsec = (second->tv_nsec + nSecsPerSec) - first->tv_nsec;
rv.tv_sec--;
}
return rv;
}
// Delta (difference) between two struct timeval.
// It is expected that the time given by the structure pointed to by
// second, is later than the time pointed to by first.
struct timeval tvDelta(const struct timeval *first,
const struct timeval *second)
{
struct timeval rv;
assert(first != NULL);
assert(second != NULL);
assert(first->tv_usec >= 0 && first->tv_usec < uSecsPerSec);
assert(second->tv_usec >= 0 && second->tv_usec < uSecsPerSec);
rv.tv_sec = second->tv_sec - first->tv_sec;
if (second->tv_usec >= first->tv_usec) {
rv.tv_usec = second->tv_usec - first->tv_usec;
} else {
rv.tv_usec = (second->tv_usec + uSecsPerSec) - first->tv_usec;
rv.tv_sec--;
}
return rv;
}
休眠延迟方法
//如果rmtp参数为NULL,不返回的剩余时间
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
void usleep(int micro_seconds);
```c
//延迟, 输入浮点数时间
void DelayNonint(float amt)
{
struct timespec start, current, delta;
struct timespec remaining;
// Get the time at which we started
clock_gettime(CLOCK_MONOTONIC, &start);
do {
// Get current time
clock_gettime(CLOCK_MONOTONIC, ¤t);
// How much time is left
delta = tsDelta(&start, ¤t);
if (ts2double(&delta) > amt) { break; }
// Request to sleep for the remaining time
remaining = double2ts(amt - ts2double(&delta));
(void) nanosleep(&remaining, NULL);
} while (true);
}
//延迟, 输入浮点数时间
void DelayNonintSpin(float amt)
{
struct timespec start, current, delta;
// Get the time at which we started
clock_gettime(CLOCK_MONOTONIC, &start);
do {
// Get current time
clock_gettime(CLOCK_MONOTONIC, ¤t);
// How much time is left
delta = tsDelta(&start, ¤t);
if (ts2double(&delta) > amt) { break; }
} while (true);
}