code:sched - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki

Table of Contents

Source

  • 进程图像 调入调出 的主循环,由0#进程执行

1921

1922 /*

1923  * The main loop of the scheduling (swapping)

1924  * process.

1925  * The basic idea is:

1926  * see if anyone wants to be swapped in;

1927  * swap out processes until there is room;

1928  * swap him in;

1929  * repeat.

1930  * Although it is not remarkably evident, the basic

1931  * synchronization here is on the runin flag, which is

1932  * slept on and is set once per second by the clock routine.

1933  * Core shuffling therefore take place once per second.

1934  *

1935  * panic: swap error -- IO error while swapping.

1936  * this is the one panic that should be

1937  * handled in a less drastic way. Its

1938  * very hard.

1939  */

1940 sched()

1941 {

1942     struct proc *p1;

1943     register struct proc *rp;

1944     register a, n;

1945

1946     /*

1947      * find user to swap in

1948      * of users ready, select one out longest

1949      */

1950

1951     goto loop;

1952

1953 sloop:

1954     runin++;

1955     sleep(&runin, PSWP);

1956

1957 loop:

1958     spl6();

  • 处理机优先级设为6
1959     n = -1;

1960     for(rp = &proc[0]; rp < &proc[NPROC]; rp++)

1961     if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&

1962          rp->p_time > n) {

1963           p1 = rp;

1964           n = rp->p_time;

1965          }

  • 遍历proc数组,寻找处于盘交换区上的就绪态进程中,在盘交换区呆了时间最长的进程
1966     if(n == -1) {

1967          runout++;

1968          sleep(&runout, PSWP);

  • 若未能搜到盘交换区上的就绪态进程,则
1969          goto loop;

1970     }

1971

1972     /*

1973      * see if there is core for that process

1974     */

1975

1976     spl0();

1977     rp = p1;

1978     a = rp->p_size;

  • 置a为进程图像的大小(暂不包含共享正文段)
1979     if((rp=rp->p_textp) != NULL)

1980          if(rp->x_ccount == 0)

1981           a =+ rp->x_size;

  • 若该进程图像有共享正文段,且该正文段还未被载入内存,则将a再加上共享正文段大小
1982     if((a=malloc(coremap, a)) != NULL)

1983          goto found2;

1984

  • 为待调入的进程图像分配空间,若分配成功,则转到2031行
  • 否则继续
1985     /*

1986      * none found,

1987      * look around for easy core

1988      */

1989

1990     spl6();

1991     for(rp = &proc[0]; rp < &proc[NPROC]; rp++)

1992          if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&

1993          (rp->p_stat == SWAIT || rp->p_stat==SSTOP))

  • 遍历proc数组,寻找内存中状态为SWAIT或SSTOP 且 不含SSYS或SLOCK标志 的进程
  • 若能找到,则转到2021行
1994           goto found1;

1995

1996     /*

1997      * no easy core,

1998      * if this process is deserving,

1999      * look around for

2000      * oldest process in core

2001      */

2002

2003     if(n < 3)

2004          goto sloop;

  • 若之前选中的待调入进程在硬盘的驻留时间没有到3秒
    • 则跳转至1953行
    • 置runin标志
    • 在runin上睡眠,参看睡眠原因
  • 否则继续
2005     n = -1;

2006     for(rp = &proc[0]; rp < &proc[NPROC]; rp++)

2007          if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&

2008          (rp->p_stat==SRUN || rp->p_stat==SSLEEP) &&

2009          rp->p_time > n) {

2010           p1 = rp;

2011           n = rp->p_time;

2012     }

  • 从内存 找到 状态为SRUN或SSLEEP 且 不含SSYS或SLOCK标志 且 驻留时间最长 的进程
2013     if(n < 2)

2014          goto sloop;

  • 若找不到符合上述条件且在内存驻留时间超过2秒的进程
    • 则跳转至1953行
    • 置runin标志
    • 在runin上睡眠,参看睡眠原因
  • 否则将找到的进程调出
2015     rp = p1;

2016

2017     /*

2018      * swap user out

2019      */

2020

2021 found1:

2022     spl0();

2023     rp->p_flag =& ~SLOAD;

2024     xswap(rp, 1, 0);

  • 去SLOAD标志
  • 将进程调出到盘交换区
2025     goto loop;

2026

2027     /*

2028      * swap user in

2029      */

2030

2031 found2:

2032     if((rp=p1->p_textp) != NULL) {

2033          if(rp->x_ccount == 0) {

2034           if(swap(rp->x_daddr, a, rp->x_size, B_READ))

2035                goto swaper;

2036           rp->x_caddr = a;

2037           a =+ rp->x_size;

  • 若要调入的进程有共享正文段,且尚未被调入内存,则将其先调入内存
  • 若调入失败,则直接跳至2050行,抛出错误
  • 否则更新相应信息
    • 共享正文段起始地址置为1982行分配所得的开始地址a
    • 将共享正文段的结尾地址赋给a
2038          }

2039          rp->x_ccount++;

2040     }

2041     rp = p1;

2042     if(swap(rp->p_addr, a, rp->p_size, B_READ))

2043          goto swaper;

2044     mfree(swapmap, (rp->p_size+7)/8, rp->p_addr);

  • 调入除共享正文段外的进程图像
  • 若调入失败,则直接跳至2050行,抛出错误
  • 否则释放盘交换区空间
2045     rp->p_addr = a;

2046     rp->p_flag =| SLOAD;

2047     rp->p_time = 0;

  • 更新进程proc结构的相关信息
    • ppda区首址置为a
    • 标志位置上SLOAD
    • 内存滞留时间清零
2048     goto loop;

2049

2050 swaper:

2051     panic("swap error");

  • 抛出错误
2052 }

2053 /* ------------------------- */

Extend

附图

Ref

Caller

⚠️ **GitHub.com Fallback** ⚠️