《linux 内核完全剖析》 mktime.c

tm结构体的定义在time.h里面

struct tm {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;

};
/*
 *  linux/kernel/mktime.c
 *
 *  (C) 1991  Linus Torvalds
 */

#include <time.h>

/*
 * This isn‘t the library routine, it is only used in the kernel.
 * as such, we don‘t care about years<1970 etc, but assume everything
 * is ok. Similarly, TZ etc is happily ignored. We just do everything
 * as easily as possible. Let‘s find something public for the library
 * routines (although I think minix times is public).
 */
/*
 * PS. I hate whoever though up the year 1970 - couldn‘t they have gotten
 * a leap-year instead? I also hate Gregorius, pope or no. I‘m grumpy.
 */
#define MINUTE 60         //一分钟60秒,这里60是以秒为单位计数
#define HOUR (60*MINUTE)  //一小时60分钟
#define DAY (24*HOUR)     //一天24小时
#define YEAR (365*DAY)    //一年365天

/* interestingly, we assume leap-years */
static int month[12] = {//初始化每个月开始的秒数,即以秒为单位的起始时间
    0,
    DAY*(31),
    DAY*(31+29),
    DAY*(31+29+31),
    DAY*(31+29+31+30),
    DAY*(31+29+31+30+31),
    DAY*(31+29+31+30+31+30),
    DAY*(31+29+31+30+31+30+31),
    DAY*(31+29+31+30+31+30+31+31),
    DAY*(31+29+31+30+31+30+31+31+30),
    DAY*(31+29+31+30+31+30+31+31+30+31),
    DAY*(31+29+31+30+31+30+31+31+30+31+30)
};

long kernel_mktime(struct tm * tm)
{
    long res;
    int year;

    year = tm->tm_year - 70;//从1970年开始计时,year得到的是和70年的年差
/* magic offsets (y+1) needed to get leapyears right.*/
    res = YEAR*year + DAY*((year+1)/4);//闰年多一天
    res += month[tm->tm_mon];//时间精确到月
/* and (y+2) here. If it wasn‘t a leap-year, we have to adjust */
    if (tm->tm_mon>1 && ((year+2)%4))
    //因为是从1970年算起的,这里year+2就能耦合上闰年。。。换而言之,1972年是闰年,但是年差是2,这里补上2就对齐了。。。。
        res -= DAY;//year不是闰年,则减一天
    res += DAY*(tm->tm_mday-1);
    res += HOUR*tm->tm_hour;
    res += MINUTE*tm->tm_min;
    res += tm->tm_sec;//时间精确到秒
    return res;
}

《linux 内核完全剖析》 mktime.c,布布扣,bubuko.com

时间: 2024-11-10 02:45:11

《linux 内核完全剖析》 mktime.c的相关文章

《linux 内核完全剖析》 keyboard.S 部分代码分析(key_map)

keyboard.S 部分代码分析(key_map) keyboard中间有这么一段,我一开始没看明白,究竟啥意思 key_map: .byte 0,27 .ascii "1234567890-=" .byte 127,9 .ascii "qwertyuiop[]" .byte 13,0 .ascii "asdfghjkl;'" .byte '`,0 .ascii "\\zxcvbnm,./" .byte 0,'*,0,32

《linux 内核完全剖析》 exit.c 代码分析笔记

exit.c 代码分析笔记 release 释放进程的函数release() 主要根据指定进程的任务数据结构指针,在任务数组中删除指定的进程指针,释放相关内存页,并立刻让内核重新调度进程的运行. void release(struct task_struct * p) //释放p指向的进程 { int i; if (!p) //常规检测p是否为0 return; if (p == current) { //不能把自己给释放了 printk("task releasing itself\n\r&q

《linux 内核完全剖析》chapter 13 内存管理 (不含swap.c)

内存管理(memory.c 和swap.s 部分) "倒着看" 先看memory management,很明显,前面各种阻力,都是因为涉及内存管理.不先看这个,我估计前面看了也是白看 我估算着理论打基础砸了差不多一个星期的时间在memory management上面了...感觉很有收获,是时候用实践(code)印证理论了! <modern operating system>讲内存管理那一章 http://blog.csdn.net/cinmyheart/article/de

《linux 内核完全剖析》 笔记 由逻辑地址转换成线性地址代码分析

一开始由这段代码引发的纠结 get_base(current->ldt[1]) 下面是各个相关的代码,摘自不同的header files... current是指向当前task的指针 struct desc_struct ldt[3]; struct desc_struct { unsigned long a,b; } ; #define _get_base(addr) ({unsigned long __base; __asm__("movb %3,%%dh\n\t" &quo

《linux 内核完全剖析》 include/asm/io.h

include/asm/io.h #define outb(value,port) __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) //宏定义outb用汇编实现了在端口地址port处写入值value //使用的寄存器是al,一个byte长度,而端口port使用的是2byte长度地址来标记的寄存器,注意这里寄存器的使用 #define inb(port) ({ unsigned char _v;

《linux 内核完全剖析》 void free_page() 分析

最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySql所以在配置的时候出现了一些问题,该篇文章就主要针对MySql绿色版的配置及其使用进行讨论. 一.MySql概述 MySql数据库是有瑞典MySql AB公司开发,现在该公司被Oracle收购属于Oracle所有.同SQL Server类似,它也是基于关系型数据库的数据库管理系统,在Web应用方面MySQL是最好的RDBMS之一,因为它

《linux 内核完全剖析》上帝为什么是右移20,而不是22! dir = (unsigned long *) ((from&gt;&gt;20) &amp; 0xffc)

在memory.c里面有这么一段代码.为了其中的一句话,让我内牛满面啊! dir = (unsigned long *) ((from>>20) & 0xffc) int free_page_tables(unsigned long from,unsigned long size) { unsigned long *pg_table; unsigned long * dir, nr; if (from & 0x3fffff) panic("free_page_tabl

《linux 内核完全剖析》 fork.c 代码分析笔记

fork.c 代码分析笔记 verifiy_area long last_pid=0; //全局变量,用来记录目前最大的pid数值 void verify_area(void * addr,int size) // addr 是虚拟地址 ,size是需要写入的字节大小 { unsigned long start; start = (unsigned long) addr; //把地址强制类型转换之后,赋值给start size += start & 0xfff; //取addr在当前虚拟地址中4

《linux 内核完全剖析》 笔记 CODE_SPACE 宏定义分析

在memory.c里面,遇到一个宏定义,如下: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < current->start_code + current->end_code) 看的第一眼,不知道,第二眼,还是不知道,纠结了半天还是不知道. 睡了一晚,今天早上再看,嘿嘿,居然看懂了... 这个宏定义用于判断给定的addr线性地址是否位于当前进程的代码段中. 4095 = 0xFFF; addr+4095的作用是将位于0~4095