国色天香在线观看全集免费播放

你的位置:国色天香在线观看全集免费播放 > 无码精品久久久天天影视 > 无码精品久久久天天影视

大名鼎鼎的程度更动等于从这里入手的

发布日期:2022-06-18 17:03    点击次数:74

大名鼎鼎的程度更动等于从这里入手的

书接上回,上回书我们说到,time_init 举止通过与 CMOS 端口进行读写交互,获取到了年月日时候秒等数据,并通过这些盘算出了开机时代 startup_time 变量,是从 1970 年 1 月 1 日 0 时起到开机其时经过的秒数。

我们连接往下看,大名鼎鼎的程度更动启动化,shed_init。

void main(void) {     ...     mem_init(main_memory_start,memory_end);     trap_init();     blk_dev_init();     chr_dev_init();     tty_init();     time_init();     sched_init();     buffer_init(buffer_memory_end);     hd_init();     floppy_init();          sti();     move_to_user_mode();     if (!fork()) {init();}     for(;;) pause(); } 

这举止可了不得,因为它等于多程度的基石!

终于来到了昌盛的时刻,是不是很慷慨?不外先别慷慨,这里仅仅程度更动的启动化,也等于为程度更动所需要用到的数据结构做个准备,简直的程度更动还需要更动算法、时钟中断等机制的互助。

天然,关于默契操作系统,过程和数据结构最为紧迫了,而这一段行为系数这个词过程的首先,以及树立数据结构的场所,就显得格外紧迫了。

我们干涉这个举止,极少点往后看。

void sched_init(void) {     set_tss_desc(gdt+4, &(init_task.task.tss));     set_ldt_desc(gdt+5, &(init_task.task.ldt));     ... } 

两行代码启动化了下 TSS 和 LDT。

先别急问这俩结构是啥。还铭刻之前讲的全局描述符表 gdt 么?它在内存的这个位置,而况被诞生成了这个表情。

忘了的看一下等八回 | 烦死了又要再行诞生一遍 idt 和 gdt,这就评释之前看似没用的细节有多紧迫了,全球一定要有耐烦。

说回这两行代码,其实等于往后又加了两项,分裂是 TSS 和 LDT。

好,那再说说这俩结构是干嘛的,不外本篇先浅易默契,后头会详备讲到。

TSS 叫任务状况段,等于保存和规复程度的高下文的,所谓高下文,其实等于各个寄存器的信息长途,这么程度切换的时候,能力做到保存和规复高下文,连接执行。

由它的数据结构你应该不错看出点真理。

struct tss_struct{     long back_link;     long esp0;     long ss0;     long esp1;     long ss1;     long esp2;     long ss2;     long cr3;     long eip;     long eflags;     long eax, ecx, edx, ebx;     long esp;     long ebp;     long esi;     long edi;     long es;     long cs;     long ss;     long ds;     long fs;     long gs;     long ldt;     long trace_bitmap;     struct i387_struct i387; }; 

而 LDT 叫局部描述符表,是与 GDT 全局描述符表相对应的,内核态的代码用 GDT 里的数据段和代码段,而用户程度的代码用每个用户程度我方的 LDT 里得数据段和代码段。

先无论它,我这里放一张超纲的图,你先找找嗅觉。

我们接着往下看。

struct desc_struct {     unsigned long a,b; }  struct task_struct * task[64] = {&(init_task.task), };  void sched_init(void) {     ...     int i;     struct desc_struct * p;         p = gdt+6;     for(i=1;i<64;i++) {         task[i] = NULL;         p->a=p->b=0;         p++;         p->a=p->b=0;         p++;     }     ... } 

这段代码有个轮回,干了两件事。

一个是给一个长度为 64,结构为 task_struct 的数组 task 附上启动值。

这个 task_struct 结构等于代表每一个程度的信息,这关联词个相当相当紧迫的结构了,把它放在心里。

struct task_struct { /* these are hardcoded - don't touch */     long state; /* -1 unrunnable, 0 runnable, >0 stopped */     long counter;     long priority;     long signal;     struct sigaction sigaction[32];     long blocked; /* bitmap of masked signals */   /* various fields */     int exit_code;     unsigned long start_code,end_code,end_data,brk,start_stack;     long pid,father,pgrp,session,
a级毛片免费观看在线播放leader;     unsigned short uid,euid,suid;     unsigned short gid,egid,sgid;     long alarm;     long utime,stime,cutime,cstime,start_time;     unsigned short used_math;   /* file system info */     int tty;  /* -1 if no tty, so it must be signed */     unsigned short umask;     struct m_inode * pwd;     struct m_inode * root;     struct m_inode * executable;     unsigned long close_on_exec;     struct file * filp[NR_OPEN];   /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */     struct desc_struct ldt[3];   /* tss for this task */     struct tss_struct tss; }; 

这个轮回做的另一件事,是给 gdt 剩下的位置填充上 0,也等于把剩下留给 TSS 和 LDT 的描述符都先附上空值。

往后预测一下的话,等于以后每创建一个新程度,就会在后头添加一组 TSS 和 LDT 默示这个程度的任务状况段以及局部描述符表信息。

还铭刻刚刚的超纲图吧,改日系数这个词内存的盘算等于这么的,不外你先无谓默契得很细。

那为什么一入手就先有了一组 TSS 和 LDT 呢?当今也没创建程度呀。错了,当今固然我们还莫得树立上路度更动的机制,但我们正在运行的代码等于会行为改日的一个程度的请示流。

也等于当改日程度更动机制一树立起来,正在执行的代码就会化身成为程度 0 的代码。是以我们需要提前把这些改日会行为程度 0 的信息写好。

淌若你以为很狐疑,别急,等后头系数这个词程度更动机制树立起来,而况让你亲眼看到程度 0 以及程度 1 的创建,以及它们后头因为程度更动机制而切换,你就昭彰这一切的真理了。

好,收回首,启动化了一组 TSS 和 LDT 后,再往下看两行。

#define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n))) #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))  void sched_init(void) {     ...     ltr(0);     lldt(0);     ... } 

这又波及到之前的常识咯。

还铭刻 lidt 和 lgdt 请示么?一个是给 idtr 寄存器赋值,以告诉 CPU 中断描述符表 idt 在内存的位置;一个是给 gdtr 寄存器赋值,以告诉 CPU 全局描述符表 gdt 在内存的位置。

那这两行和刚刚的访佛,无码精品久久久天天影视ltr 是给 tr 寄存器赋值,以告诉 CPU 任务状况段 TSS 在内存的位置;lldt 一个是给 ldt 寄存器赋值,以告诉 CPU 局部描述符 LDT 在内存的位置。

这么,CPU 之后就能通过 tr 寄存器找到现时景度的任务状况段信息,也等于高下文信息,以及通过 ldt 寄存器找到现时景度在用的局部描述符表信息。

我们连接看。

void sched_init(void) {     ...     outb_p(0x36,0x43);      /* binary, mode 3, LSB/MSB, ch 0 */     outb_p(LATCH & 0xff , 0x40);    /* LSB */     outb(LATCH >> 8 , 0x40);    /* MSB */     set_intr_gate(0x20,&timer_interrupt);     outb(inb_p(0x21)&~0x01,0x21);     set_system_gate(0x80,&system_call);     ... } 

四行端口读写代码,两行诞生中断代码。

端口读写我们也曾很老练了,等于 CPU 与外设交互的一种形状,之前讲硬盘读写以及 CMOS 读写时,也曾讲和过了。

而此次交互的外设是一个可编程定时器的芯片,这四行代码就开启了这个定时器,之后这个定时器变会不息的、以一定频率的向 CPU 发出中断信号。

而这段代码中诞生的两个中断,第一个等于时钟中断,中断号为 0x20,中断处理面目为 timer_interrupt。那么每次定时器向 CPU 发出中断后,便会执行这个函数。

这个定时器的触发,以实时钟中断函数的诞生,是操作系统主导程度更动的一个关节!莫得他们这么的外部信号不休触发中断,操作系统就莫得主义行为程度处治的主人,通过强制的时期收回程度的 CPU 执行权限。

第二个诞生的中断叫系统调用 system_call,中断号是 0x80,这个中断又是个绝顶绝顶绝顶绝顶绝顶绝顶绝顶紧迫的中断,系数效户态面目想要调用内核提供的举止,都需要基于这个系统调用来进行。

比如 Java 面目员写一个 read,底层会执行汇编请示 int 0x80,这就会触发系统调用这个中断,最终调用到 Linux 里的 sys_read 举止。

这个过程之后会重心呈报,当今只需要廓清,在这个场所,暗暗把这个极为紧迫的中断,诞生好了。

是以你看这一章的内容,暗暗诞生了影响程度和影响用户面目调用系统举止的两个分量级中断处理函数,不浅易呀~

到面前为止,中断也曾诞生了不少了,我们当今望望所诞生好的中断有哪些。

中断号 中断处理函数 0 ~ 0x10 trap_init 里诞生的一堆 0x20 timer_interrupt 0x21 keyboard_interrupt 0x80 system_call

其中 0-0x10 这 17 个中断是 trap_init 里启动化诞生的,是一些基本的中断,比如除零极度等。这个在 第14回 中断启动化 trap_init 有讲到。

之后,在收尾台览动化 con_init 里,我们又诞生了 0x21 键盘中断,这么按下键盘就有反映了。这个在 第16回 收尾台览动化 tty_init 有讲到。

当今,我们又诞生了 0x20 时钟中断,而况开启定时器。临了又暗暗诞生了一个极为紧迫的 0x80 系统调用中断。

找到些嗅觉没,有莫得越来越发现,操作系统有点靠中断驱动的真理,各个模块不休启动化各式中断处理函数,而况开启指定的外设开关,让操作系统我方冉冉“活”了起来,渐渐通过中断坚苦于各式事情中,无法自拔。

恭喜你,我们也曾渐渐在接近操作系统的内容了。

回首一下我们今天干了什么,就三件事。

第一,我们往全局描述符表写了两个结构,TSS 和 LDT,行为改日程度 0 的任务状况段和局部描述符表信息。

第二,我们启动化了一个结构为 task_struct 的数组,改日这里会存放系数程度的信息,而况我们给数组的第一个位置附上了 init_task.init 这个具体值,亦然行为改日程度 0 的信息。

第三,诞生了时钟中断 0x20 和系统调用 0x80,一个行为程度更动的首先,一个行为用户面目调用操作系统功能的桥梁,绝顶之紧迫。

后头,我们将会渐渐看到,这些紧迫的事情,是何如精良且精妙地聚会在沿途,弘扬非凡妙的作用。

欲知后事何如,且听下回解析。

本文转载自微信公众号「低并发编程」,不错通过以下二维码关心。转载本文请筹办低并发编程公众号。本网站已得回低并发编程的授权