代码不是重点,重点是陌生的东西
首先,推荐一本好书:«understanding unix-linux programming»,以下所有的灵感来自于这本书。
这里,重点记忆如下:
如何寻找有用的信息
充分利用man的联机文档,技巧有
man -k key-word grep “xx”
这样可以有效抓取你想要的联机帮助。运气好的话可能会有code,要多多阅读、仔细阅读。
例如在这段代码中,首先 man who,结果可以知道,这个命令读取的是/var/run/utmp文件,接下来,使用
man -k utmp
可以看到一大堆的东西,学会甄别。
open和close read
其实光知道概念意义不大,必须还会使用,这些命令的实现的价值也在于此。
int main(){
struct utmp current_record;
int utmpfd;
int reclen = sizeof(current_record);
if( ( utmpfd = open(UTMP_FILE,O_RDONLY)) == -1){
perror(UTMP_FILE); /* UTMP_FILE is in utmp.h*/
exit(1);
}
while(read(utmpfd, ¤t_record,reclen) == reclen)
show_info(¤t_record);
close(utmpfd);
return 0;
}
令人震撼的是read的实现,因为你不必实现知道要写入的结构、类型,只需要事先将结构定义好,然后按照read的使用要求就可以了。
time 相关
time
#include <time.h>
time_t time(time_t *t);
功能: 以秒(seconds)为单位得到自从the Epoch的时间。
If t is non-null, the return value is also stored in the memory pointed to by t.
time_t
这里是有很多的坑要填的。相关的代码在
struct {
int32_t tv_sec; /* Seconds */
int32_t tv_usec; /* Microseconds */
} ut_tv; /* Time entry was made */
timeval
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
tm
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
需要特别注意的是,年份是从1970年01月01日0:00:00开始计算的。
这就是在处理有关时间的问题时,经常打交道的三个结构体。
相关的时间函数
接下来是几个比较容易常用的有关时间的函数:
char *strptime()
#include <time.h>
char *strptime(const char *s, const char *format,struct tm *tm);
功能: 将一个字符串的时间表达式转化进tm结构体。
这里要注意一下第二个参数,因为有些麻烦,所以最好是需要用的时候man一下。 这个函数在使用的时候,必须首先初始化一下tm。
size_t strftime()
size_t strftime(char *s, size_t max, const char *format,
const struct tm *tm);
功能: 格式化日期和时间(format data and time),其相关的信息来自于tm,第三个参 数和strptime函数类似,用的时候联机man 一下。
举个例子测试下:
/*
* $ ./a.out '%m'
* Result string is "11"
* $ ./a.out '%5m'
* Result string is "00011"
* $ ./a.out '%_5m'
* Result string is " 11"
*/
Here is the program source:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char outstr[200];
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
if (tmp == NULL) {
perror("localtime");
exit(EXIT_FAILURE);
}
if (strftime(outstr, sizeof(outstr), argv[1], tmp) == 0) {
fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE);
}
printf("Result string is \"%s\"\n", outstr);
exit(EXIT_SUCCESS);
}
上面的注释将这段代码的功能描述的很清楚,也就是用’%Y’等格式化来当前时间关键 字段的输出。
将这两段程序综合起来看,就明白了
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int
main(void)
{
struct tm tm;
char buf[255];
memset(&tm, 0, sizeof(struct tm));
strptime("2016-07-06 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);
strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
puts(buf);
exit(EXIT_SUCCESS);
}
其结果是:
06 Jul 2016 09:53
char *asctim3(),char *ctime(),struct tm *gmtime(),struct tm *localtime(), struct mktime()
#include <time.h>
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
time_t mktime(struct tm *tm);
功能:
The ctime(), gmtime() and localtime() functions all take an argument of data type time_t which represents calendar time. When interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
The asctime() and mktime() functions both take an argument representing broken-down time which is a representation separated into year,month, day, etc.
ctime()
The call ctime(t) is equivalent to asctime(localtime(t)). It converts the calendar time t into a null-terminated string of the form
"Wed Jun 30 21:49:08 1993\n"
简单说一下就是将日历时间(calendar time t)转化为如上的字符串格式,这个 calendar time t,应该就是time_t 类型,其中记录了从 1970年01月01日0:00:00开始的时间。
注意,这几个后缀为_r的是可以返回到用户自定义的字符串中。
gmtime()
转为为UTC(Coordinated Universal Time)
localtime()
转为为用户所在的时区的时间表达形式.
asctime()
将形式为tm成员的时间表达式转化成类似于ctime 的形式。
mktime()
将零碎的tm成员的时间表达式转化为local time,也是以calendar的形式。
简单的使用
版本1
#include<stdio.h>
#include<time.h>
int main(){
time_t timep;
time(&timep); /* 获取time_t 类型的当前时间 */
printf("%s\n",asctime(gmtime(&timep)));
/* 使用gtime将time_t类型的时间转换为
* struct tm类型的时间,然后再用asctime转换为
* 我们常见的格式: Fri Wed Jul 6 05:40:11 2016
*
*/
return 0;
}
输出结果为:
Wed Jul 6 05:45:15 2016
版本2
#include<stdio.h>
#include<time.h>
int main(){
time_t timep;
time(&timep); /* 获取time_t类型的当前时间*/
printf("%s\n",ctime(&timep));
/*转换为常见的字符串 Wed Jul 6 01:49:11 2016 */
return 0;
}
输出结果:
Wed Jul 6 01:51:54 2016
我在验证这两个程序的时候,时间间隔不会超过20分钟,所以,我们看到后者与我现在 的时间时区是一样的。因为我是在vps验证的,经过date命令的输出,我发现ctime函数 与date的输出是一致的。那么,我是否可以认为ctime函数经过了时区处理?
root@hehe:~/test/unix_linux# date
2016年 07月 06日 星期三 01:54:28 EDT
版本3
#include<stdio.h>
#include<time.h>
int main(){
char *wday[] = {"Sun", "Mon","Tue","Wed","Thu","Fri","Sat"};
time_t timep;
struct tm *p;
time(&timep); /*获得time_t结构的时间, UTC时间*/
p = gmtime(&timep); /*转化为 struct* tm 结构的时间 */
printf("%d/%d/%d\n",1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
printf("%s %d:%d:%d\n",wday[p->tm_wday], p->tm_hour, p->tm_min,p->tm_sec);
return 0;
}
输出的结果为:
2016/7/6
Wed 6:16:20
这个结果与版本1相类似
版本4
#include<time.h>
int main()
{
char *wday[] = {"Sun", "Mon", "Tue", "Wed","Thu", "Fri", "Sat"};
time_t timep;
struct tm *p;
time(&timep);/*获得time_t结构的时间,UTC时间 */
p = localtime(&timep);
printf("%d/%d/%d\n", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
printf("%s %d:%d:%d\n",wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
return 0;
}
输出结果为:
2016/7/6
Wed 2:57:55
与版本2的结果类似。
这个程序中使用到函数
然后使用ctime函数:
#define UT_TIME_MEMBER(UT_PTR) ((UT_PTR)->ut_tv.tv_sec)
void show_time(struct utmp *utmpfd)
{
time_t tm = UT_TIME_MEMBER(utmpfd);
char *ptr = ctime(&tm) + 4;
ptr[16] = '\0';
printf("%s",ptr);
/* int len = strlen(ptr);
* printf("The length of time is %D\n",len);
*/
}
如果这时对time_t类型的数据进行总结,还达不到那个程度,先简单的记录下来进行备案。
还有,一定要充分利用gdb的调试功能,就是在调这个程序的时候,一直在报段错误,其实是根本就没有编译过去,因为少了一个time.h文件,但是我的Makefile的gcc编译语句没有体现出来。