code:sched - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki
- 进程图像 调入调出 的主循环,由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
- 置runin
- 在runin上睡眠,参看睡眠原因
1957 loop:
1958 spl6();
1959 n = -1;
- 处理机优先级设为6
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 }
1966 if(n == -1) {
- 遍历proc数组,寻找处于盘交换区上的就绪态进程中,在盘交换区呆了时间最长的进程
1967 runout++;
1968 sleep(&runout, PSWP);
1969 goto loop;
- 若未能搜到盘交换区上的就绪态进程,则
- 置runout
- 在runout上睡眠,参见睡眠原因
1970 }
1971
1972 /*
1973 * see if there is core for that process
1974 */
1975
1976 spl0();
1977 rp = p1;
1978 a = rp->p_size;
1979 if((rp=rp->p_textp) != NULL)
- 置a为进程图像的大小(暂不包含共享正文段)
1980 if(rp->x_ccount == 0)
1981 a =+ rp->x_size;
1982 if((a=malloc(coremap, a)) != NULL)
- 若该进程图像有共享正文段,且该正文段还未被载入内存,则将a再加上共享正文段大小
1983 goto found2;
1984
1985 /*
- 为待调入的进程图像分配空间,若分配成功,则转到2031行
- 否则继续
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))
1994 goto found1;
- 遍历proc数组,寻找内存中状态为SWAIT或SSTOP 且 不含SSYS或SLOCK标志 的进程
- 若能找到,则转到2021行
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;
2005 n = -1;
- 若之前选中的待调入进程在硬盘的驻留时间没有到3秒
- 则跳转至1953行
- 置runin标志
- 在runin上睡眠,参看睡眠原因
- 否则继续
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 }
2013 if(n < 2)
- 从内存 找到 状态为SRUN或SSLEEP 且 不含SSYS或SLOCK标志 且 驻留时间最长 的进程
2014 goto sloop;
2015 rp = p1;
- 若找不到符合上述条件且在内存驻留时间超过2秒的进程
- 则跳转至1953行
- 置runin标志
- 在runin上睡眠,参看睡眠原因
- 否则将找到的进程调出
2016
2017 /*
2018 * swap user out
2019 */
2020
2021 found1:
2022 spl0();
2023 rp->p_flag =& ~SLOAD;
2024 xswap(rp, 1, 0);
2025 goto loop;
- 去SLOAD标志
- 将进程调出到盘交换区
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;
2038 }
- 若要调入的进程有共享正文段,且尚未被调入内存,则将其先调入内存
- 若调入失败,则直接跳至2050行,抛出错误
- 否则更新相应信息
- 共享正文段起始地址置为1982行分配所得的开始地址a
- 将共享正文段的结尾地址赋给a
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);
2045 rp->p_addr = a;
- 调入除共享正文段外的进程图像
- 若调入失败,则直接跳至2050行,抛出错误
- 否则释放盘交换区空间
2046 rp->p_flag =| SLOAD;
2047 rp->p_time = 0;
2048 goto loop;
- 更新进程proc结构的相关信息
- ppda区首址置为a
- 标志位置上SLOAD
- 内存滞留时间清零
2049
2050 swaper:
2051 panic("swap error");
2052 }
- 抛出错误
2053 /* ------------------------- */