《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》——2.8 开机启动时间设置

简介: 本节书摘来自华章计算机《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》一书中的第2章,第2.8节,作者:新设计团队著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.8 开机启动时间设置

开机启动时间是大部分与时间相关的计算的基础。操作系统中一些程序的运算需要时间参数;很多事务的处理也都要用到时间,比如文件修改的时间、文件最近访问的时间、i节点自身的修改时间等。有了开机启动时间,其他时间就可据此推算出来。
具体执行步骤是:CMOS是主板上的一个小存储芯片,系统通过调用time_init()函数,先对它上面记录的时间数据进行采集,提取不同等级的时间要素,比如秒(time.tm_sec)、分(time.tm_min)、年(time.tm_year)等,然后对这些要素进行整合,并最终得出开机启动时间(startup_time)。
执行代码如下:

//代码路径:init/main.c:
void main(void)
{
    …
    time_init();
    …
}

#define CMOS_READ(addr) ({ \    //读CMOS实时时钟信息
outb_p(0x80|addr,0x70); \        //0x80|addr读CMOS地址,0x70写端口
inb_p(0x71); \            //0x71读端口
})

#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)//十进制转二进制

static void time_init(void)
{
    struct tm time;

    do {
         time.tm_sec= CMOS_READ(0);//当前时间的秒值,以下类推
         time.tm_min= CMOS_READ(2);
         time.tm_hour= CMOS_READ(4);
         time.tm_mday= CMOS_READ(7);
         time.tm_mon= CMOS_READ(8);
         time.tm_year= CMOS_READ(9);
    } while (time.tm_sec != CMOS_READ(0));
    BCD_TO_BIN(time.tm_sec);
    BCD_TO_BIN(time.tm_min);
    BCD_TO_BIN(time.tm_hour);
    BCD_TO_BIN(time.tm_mday);
    BCD_TO_BIN(time.tm_mon);
    BCD_TO_BIN(time.tm_year);
    time.tm_mon--;
    startup_time= kernel_mktime(&time);    //开机时间,从1970年1月1日0时计算
}

//代码路径:include\asm\io.h:        //嵌入汇编参看trap_init的注释
#define outb_p(value,port) \        //将value写到port
__asm__ ("outb %%al,%%dx\n" \    
          "\tjmp 1f\n" \            //jmp到下面的第一个1:处,目的是延迟
          "1:\tjmp 1f\n" \        
          "1:"::"a" (value),"d" (port))

#define inb_p(port) ({ \
unsigned char _v; \
__asm__ volatile ("inb %%dx,%%al\n" \    // volatile,禁止编译器优化下列代码
                        "\tjmp 1f\n" \    //延迟
                        "1:\tjmp 1f\n" \
                        "1:":"=a" (_v):"d" (port)); \
                     _v; \
                     })

计算过程及开机启动时间在内存中的存储位置如图2-16所示。

image

相关文章
|
1天前
|
Linux 芯片 Ubuntu
Linux驱动入门 —— 利用引脚号操作GPIO进行LED点灯
Linux驱动入门 —— 利用引脚号操作GPIO进行LED点灯
|
1天前
|
Ubuntu Linux
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-2
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-2
|
1天前
|
Linux 芯片
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-1
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯
Linux驱动入门 —— 利用寄存器操作GPIO进行LED点灯-1
|
1天前
|
NoSQL Ubuntu Linux
【操作系统】实验三 编译 Linux 内核
【操作系统】实验三 编译 Linux 内核
3 1
|
3天前
|
Linux Windows 编译器
|
3天前
|
存储 Linux C++
linux信号量与PV操作知识点总结
linux信号量与PV操作知识点总结
|
4天前
|
存储 算法 Linux
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
【Linux】线程的内核级理解&&详谈页表以及虚拟地址到物理地址之间的转化
|
4天前
|
安全 Linux
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
|
4天前
|
存储 Linux C++
【Linux】详解信号的保存&&信号屏蔽字的设置
【Linux】详解信号的保存&&信号屏蔽字的设置
|
4天前
|
存储 Linux
【Linux】对信号产生的内核级理解
【Linux】对信号产生的内核级理解