Linux-0.0.1内核阅读连载笔记-2013.08.23

简介: __________________________________________________________ ../kernel/Vsprintf.c __________________________________________________________ #include <linux/config.h> #include <linu
__________________________________________________________

../kernel/Vsprintf.c

__________________________________________________________

#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>

/*
 * This code handles all hd-interrupts, and read/write requests to
 * the hard-disk. It is relatively straigthforward (not obvious maybe,
 * but interrupts never are), while still being efficient, and never
 * disabling interrupts (except to overcome possible race-condition).
 * The elevator block-seek algorithm doesn't need to disable interrupts
 * due to clever programming.
 */

/* Max read/write errors/sector */
#define MAX_ERRORS 5
#define MAX_HD  2
#define NR_REQUEST 32

/*
 *  This struct defines the HD's and their types.
 *  Currently defined for CP3044's, ie a modified
 *  type 17.
 */
static struct hd_i_struct{
 int head,sect,cyl,wpcom,lzone,ctl;
 } hd_info[]= { HD_TYPE };

#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))

static struct hd_struct {
 long start_sect;
 long nr_sects;
} hd[5*MAX_HD]={{0,0},};   //一个硬盘可分5个区,共有2个硬盘

static struct hd_request {
 int hd;  /* -1 if no request */
 int nsector;
 int sector;
 int head;
 int cyl;
 int cmd;
 int errors;
 struct buffer_head * bh;
 struct hd_request * next;
} request[NR_REQUEST];

#define IN_ORDER(s1,s2) \
((s1)->hd<(s2)->hd || (s1)->hd==(s2)->hd && \
((s1)->cyl<(s2)->cyl || (s1)->cyl==(s2)->cyl && \
((s1)->head<(s2)->head || (s1)->head==(s2)->head && \
((s1)->sector<(s2)->sector))))

static struct hd_request * this_request = NULL;

static int sorting=0;

static void do_request(void);
static void reset_controller(void);
static void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
 unsigned int cyl,struct buffer_head * bh);
void hd_init(void);

#define port_read(port,buf,nr) \
//下面的内嵌汇编的意思是:
// movl port %edx
// movl buf %edi
// movl nr %ecx
// cld
// rep insw  //从edx指定的port传送字到es:edi指定的buf中
__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")

#define port_write(port,buf,nr) \
__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") //其中outsw是从ds:si指定的buf中传送字到edx指定的port

extern void hd_interrupt(void);   //在system_call.S中定义

static struct task_struct * wait_for_request=NULL;

static inline void lock_buffer(struct buffer_head * bh)
{
 if (bh->b_lock)    //此缓冲区是否上锁
  printk("hd.c: buffer multiply locked\n");
 bh->b_lock=1;
}

static inline void unlock_buffer(struct buffer_head * bh)
{
 if (!bh->b_lock)
  printk("hd.c: free buffer being unlocked\n");
 bh->b_lock=0;
 wake_up(&bh->b_wait);
}

static inline void wait_on_buffer(struct buffer_head * bh)
{
 cli();
 while (bh->b_lock)
  sleep_on(&bh->b_wait);  //进入等待对列
 sti();
}

void rw_hd(int rw, struct buffer_head * bh) //缓冲区和磁盘之间交换数据
{
 unsigned int block,dev;
 unsigned int sec,head,cyl;

 block = bh->b_blocknr << 1;   //默认1块=1024字节,二个扇区
 dev = MINOR(bh->b_dev);
 if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) //是否超过了分区,此分区是否满了
  return;
 block += hd[dev].start_sect;  //此分区的开始扇区+block,即在硬盘中定开始的位置
 dev /= 5;     //看看是哪个硬盘
 __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0), 
  "r" (hd_info[dev].sect));     //确定扇区号
 __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
  "r" (hd_info[dev].head));     //确定光头号
 rw_abs_hd(rw,dev,sec+1,head,cyl,bh); //实际写盘函数
}

/* This may be used only once, enforced by 'static int callable' */
int sys_setup(void)
{
 static int callable = 1;
 int i,drive;
 struct partition *p;

 if (!callable)
  return -1;
 callable = 0;
 for (drive=0 ; drive<NR_HD ; drive++) {
  rw_abs_hd(READ,drive,1,0,0,(struct buffer_head *) start_buffer); //读取引导扇区512字节到start_buffer中
  if (!start_buffer->b_uptodate) {
   printk("Unable to read partition table of drive %d\n\r",
    drive);
   panic("");
  }
  if (start_buffer->b_data[510] != 0x55 || (unsigned char)
      start_buffer->b_data[511] != 0xAA) {    //分析引导扇区是否合法,合法应为55AA
   printk("Bad partition table on drive %d\n\r",drive);
   panic("");
  }
  p = 0x1BE + (void *)start_buffer->b_data;  //指针指向分区信息的开始位置
  for (i=1;i<5;i++,p++) {    //保存分区信息
   hd[i+5*drive].start_sect = p->start_sect;
   hd[i+5*drive].nr_sects = p->nr_sects;
  }
 }
 printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
 mount_root();    //在super.c中定义
 return (0);
}

/*
 * This is the pointer to a routine to be executed at every hd-interrupt.
 * Interesting way of doing things, but should be rather practical.
 */
void (*do_hd)(void) = NULL;

static int controller_ready(void)
{
 int retries=1000;

 while (--retries && (inb(HD_STATUS)&0xc0)!=0x40); //0x40是第六个位置1为驱动器准备好,0x1f7端口是读取硬盘状态
 return (retries);
}

static int win_result(void)
{
 int i=inb(HD_STATUS); //读取硬盘状态

 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
  == (READY_STAT | SEEK_STAT))
  return(0); /* ok */
 if (i&1) i=inb(HD_ERROR); //0x1f1是硬盘错误寄存器,检查上一个命令是否出错
 return (1);
}

static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
  unsigned int head,unsigned int cyl,unsigned int cmd,
  void (*intr_addr)(void))
{
 register int port asm("dx");

 if (drive>1 || head>15) //只支持1个硬盘和14个头
  panic("Trying to write bad sector");
 if (!controller_ready())
  panic("HD controller not ready");
 do_hd = intr_addr;  //硬盘写或读操作指针
 outb(_CTL,HD_CMD);  //0x3f6是硬盘控制寄存器,置0为控制器为普通操作
 port=HD_DATA;   //0x1f0硬盘数据寄存器
 outb_p(_WPCOM,++port); //0x1f1,写预补偿,在从磁柱300X4处开始写
 outb_p(nsect,++port); //0x1f2是硬盘扇区记数寄存器,将要传送的扇区数放入该寄存器
 outb_p(sect,++port);  //0x1f3是硬盘扇区号寄存器,记录当前的扇区号
 outb_p(cyl,++port);  //0x1f4硬盘磁柱低寄存器,保存起始磁柱号的低8字节
 outb_p(cyl>>8,++port); //0x1f5硬盘磁柱高寄存器
 outb_p(0xA0|(drive<<4)|head,++port); //0x1f6硬盘驱动器和磁头寄存器,这里选择主盘(高4位为1010),低4位为磁头号
 outb(cmd,++port);  //0x1f7硬盘命令输出寄存器,主要向硬盘发出命令
}

static int drive_busy(void)
{
 unsigned int i;

 for (i = 0; i < 100000; i++) //循环,直到驱动器为READY_STAT或超时
  if (READY_STAT == (inb(HD_STATUS) & (BUSY_STAT | READY_STAT)))
   break;
 i = inb(HD_STATUS);   //再读硬盘状态
 i &= BUSY_STAT | READY_STAT | SEEK_STAT;
 if (i == READY_STAT | SEEK_STAT) //如果处于读状态或寻找状态,OK
  return(0);
 printk("HD controller times out\n\r");
 return(1);
}

static void reset_controller(void)
{
 int i;

 outb(4,HD_CMD);  //0x3f6是硬盘适配器控制寄存器,第二位置1为重启控制器
 for(i = 0; i < 1000; i++) nop(); //等待一会儿
 outb(0,HD_CMD);  //使驱动器处于普通状态
 for(i = 0; i < 10000 && drive_busy(); i++) /* nothing */;
 if (drive_busy())
  printk("HD-controller still busy\n\r");
 if((i = inb(ERR_STAT)) != 1)
  printk("HD-controller reset failed: %02x\n\r",i);
}

static void reset_hd(int nr)
{
 reset_controller();
 hd_out(nr,_SECT,_SECT,_HEAD-1,_CYL,WIN_SPECIFY,&do_request); //do_request是重新处理请求队列
}

void unexpected_hd_interrupt(void)
{
 panic("Unexpected HD interrupt\n\r");
}

static void bad_rw_intr(void)
{
 int i = this_request->hd;

 if (this_request->errors++ >= MAX_ERRORS) { //如果错误超过有效的最大错误数,放弃这次请求
  this_request->bh->b_uptodate = 0;
  unlock_buffer(this_request->bh);
  wake_up(&wait_for_request);
  this_request->hd = -1;
  this_request=this_request->next;
 }
 reset_hd(i);
}

static void read_intr(void)
{
 if (win_result()) {
  bad_rw_intr();
  return;
 }
 port_read(HD_DATA,this_request->bh->b_data+
  512*(this_request->nsector&1),256); //是从b_data指定位置读512字节
 this_request->errors = 0;
 if (--this_request->nsector)  //如果还有要传的数据,直接返回,不从请求队列中删除该请求
  return;
//以下6行代码是指数据传送完毕,就从请求队列中删除该请求
 this_request->bh->b_uptodate = 1;
 this_request->bh->b_dirt = 0;
 wake_up(&wait_for_request);
 unlock_buffer(this_request->bh);
 this_request->hd = -1;
 this_request=this_request->next;
 do_request();    //处理其他请求
}

static void write_intr(void)
{
 if (win_result()) {
  bad_rw_intr();  //如果有错误,重启驱动器,再继续处理请求
  return;
 }
 if (--this_request->nsector) {
  port_write(HD_DATA,this_request->bh->b_data+512,256); //向硬盘数据寄存器写数据
  return;
 }
 this_request->bh->b_uptodate = 1;
 this_request->bh->b_dirt = 0;
 wake_up(&wait_for_request);
 unlock_buffer(this_request->bh);
 this_request->hd = -1;
 this_request=this_request->next;
 do_request();    //处理下一个请求
}

static void do_request(void)
{
 int i,r;

 if (sorting)
  return;
 if (!this_request) {
  do_hd=NULL;
  return;
 }
 if (this_request->cmd == WIN_WRITE) {
  hd_out(this_request->hd,this_request->nsector,this_request->
   sector,this_request->head,this_request->cyl,
   this_request->cmd,&write_intr);
  for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++) //循环,直到控制器指示准备好
   /* nothing */ ;
  if (!r) {     //如果超时驱动器仍未准备好,重设该驱动器
   reset_hd(this_request->hd);
   return;
  }
  port_write(HD_DATA,this_request->bh->b_data+
   512*(this_request->nsector&1),256);  //传送数据
 } else if (this_request->cmd == WIN_READ) {
  hd_out(this_request->hd,this_request->nsector,this_request->
   sector,this_request->head,this_request->cyl,
   this_request->cmd,&read_intr);
 } else
  panic("unknown hd-command");
}

/*
 * add-request adds a request to the linked list.
 * It sets the 'sorting'-variable when doing something
 * that interrupts shouldn't touch.
 */
static void add_request(struct hd_request * req)
{
 struct hd_request * tmp;

 if (req->nsector != 2)
  panic("nsector!=2 not implemented");
/*
 * Not to mess up the linked lists, we never touch the two first
 * entries (not this_request, as it is used by current interrups,
 * and not this_request->next, as it can be assigned to this_request).
 * This is not too high a price to pay for the ability of not
 * disabling interrupts.
 */
 sorting=1;
 if (!(tmp=this_request))
  this_request=req;
 else {
  if (!(tmp->next))
   tmp->next=req;
  else {
   tmp=tmp->next;
   for ( ; tmp->next ; tmp=tmp->next)
    if ((IN_ORDER(tmp,req) ||
        !IN_ORDER(tmp,tmp->next)) &&
        IN_ORDER(req,tmp->next))
     break;
   req->next=tmp->next;
   tmp->next=req;
  }
 }
 sorting=0;
/*
 * NOTE! As a result of sorting, the interrupts may have died down,
 * as they aren't redone due to locking with sorting=1. They might
 * also never have started, if this is the first request in the queue,
 * so we restart them if necessary.
 */
 if (!do_hd)
  do_request();
}

void rw_abs_hd(int rw,unsigned int nr,unsigned int sec,unsigned int head,
 unsigned int cyl,struct buffer_head * bh)     //根据硬盘参数做磁盘读写
{
 struct hd_request * req;

 if (rw!=READ && rw!=WRITE)
  panic("Bad hd command, must be R/W");
 lock_buffer(bh);
repeat:
 for (req=0+request ; req<NR_REQUEST+request ; req++)
  if (req->hd<0)     //hd=-1表示没有请求
   break;
 if (req==NR_REQUEST+request) {    //不能超过最大的请求数
  sleep_on(&wait_for_request);
  goto repeat;
 }
 req->hd=nr;
 req->nsector=2;      //==1024字节
 req->sector=sec;
 req->head=head;
 req->cyl=cyl;
 req->cmd = ((rw==READ)?WIN_READ:WIN_WRITE);
 req->bh=bh;
 req->errors=0;
 req->next=NULL;
 add_request(req);
 wait_on_buffer(bh);      //进入等待
}

void hd_init(void)
{
 int i;

 for (i=0 ; i<NR_REQUEST ; i++) {    //初始化请求队列
  request[i].hd = -1;
  request[i].next = NULL;
 }
 for (i=0 ; i<NR_HD ; i++) {     //初始化硬盘分区
  hd[i*5].start_sect = 0;
  hd[i*5].nr_sects = hd_info[i].head*
    hd_info[i].sect*hd_info[i].cyl;
 }
 set_trap_gate(0x2E,&hd_interrupt);    //登记硬盘中断处理程序,中断号为0x2E
 outb_p(inb_p(0x21)&0xfb,0x21);    //开放IRQ2(中断控制器1)
 outb(inb_p(0xA1)&0xbf,0xA1);    //开放IRQ14,硬盘控制器
}

 

目录
相关文章
|
16天前
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
57 4
|
20天前
|
缓存 算法 Linux
深入理解Linux内核调度器:公平性与性能的平衡####
真知灼见 本文将带你深入了解Linux操作系统的核心组件之一——完全公平调度器(CFS),通过剖析其设计原理、工作机制以及在实际系统中的应用效果,揭示它是如何在众多进程间实现资源分配的公平性与高效性的。不同于传统的摘要概述,本文旨在通过直观且富有洞察力的视角,让读者仿佛亲身体验到CFS在复杂系统环境中游刃有余地进行任务调度的过程。 ####
40 6
|
5天前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
20 1
|
10天前
|
算法 Linux 开发者
Linux内核中的锁机制:保障并发控制的艺术####
本文深入探讨了Linux操作系统内核中实现的多种锁机制,包括自旋锁、互斥锁、读写锁等,旨在揭示这些同步原语如何高效地解决资源竞争问题,保证系统的稳定性和性能。通过分析不同锁机制的工作原理及应用场景,本文为开发者提供了在高并发环境下进行有效并发控制的实用指南。 ####
|
18天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
48 9
|
17天前
|
缓存 负载均衡 Linux
深入理解Linux内核调度器
本文探讨了Linux操作系统核心组件之一——内核调度器的工作原理和设计哲学。不同于常规的技术文章,本摘要旨在提供一种全新的视角来审视Linux内核的调度机制,通过分析其对系统性能的影响以及在多核处理器环境下的表现,揭示调度器如何平衡公平性和效率。文章进一步讨论了完全公平调度器(CFS)的设计细节,包括它如何处理不同优先级的任务、如何进行负载均衡以及它是如何适应现代多核架构的挑战。此外,本文还简要概述了Linux调度器的未来发展方向,包括对实时任务支持的改进和对异构计算环境的适应性。
38 6
|
18天前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
35 5
|
18天前
|
算法 Unix Linux
深入理解Linux内核调度器:原理与优化
本文探讨了Linux操作系统的心脏——内核调度器(Scheduler)的工作原理,以及如何通过参数调整和代码优化来提高系统性能。不同于常规摘要仅概述内容,本摘要旨在激发读者对Linux内核调度机制深层次运作的兴趣,并简要介绍文章将覆盖的关键话题,如调度算法、实时性增强及节能策略等。
|
19天前
|
存储 监控 安全
Linux内核调优的艺术:从基础到高级###
本文深入探讨了Linux操作系统的心脏——内核的调优方法。文章首先概述了Linux内核的基本结构与工作原理,随后详细阐述了内核调优的重要性及基本原则。通过具体的参数调整示例(如sysctl、/proc/sys目录中的设置),文章展示了如何根据实际应用场景优化系统性能,包括提升CPU利用率、内存管理效率以及I/O性能等关键方面。最后,介绍了一些高级工具和技术,如perf、eBPF和SystemTap,用于更深层次的性能分析和问题定位。本文旨在为系统管理员和高级用户提供实用的内核调优策略,以最大化Linux系统的效率和稳定性。 ###
|
18天前
|
Java Linux Android开发
深入探索Android系统架构:从Linux内核到应用层
本文将带领读者深入了解Android操作系统的复杂架构,从其基于Linux的内核到丰富多彩的应用层。我们将探讨Android的各个关键组件,包括硬件抽象层(HAL)、运行时环境、以及核心库等,揭示它们如何协同工作以支持广泛的设备和应用。通过本文,您将对Android系统的工作原理有一个全面的认识,理解其如何平衡开放性与安全性,以及如何在多样化的设备上提供一致的用户体验。