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

Table of Contents

Source

  • exec调用
  • 为当前进程 分配共享正文区
  • 传入1个参数 ip
    • ip : 程序代码 正文文件inode
  • 使用1个隐式参数

4417

4418 /* Attach to a shared text segment.

4419  * If there is no shared text, just return.

4420  * If there is, hook up to it:

4421  * if it is not currently being used, it has to be read

4422  * in from the inode (ip) and established in the swap space.

4423  * If it is being used, but not currently in core,

4424  * a swap has to be done to get it back.

4425  * The full coroutine glory has to be invoked--

4426  * see slp.c-- because if the calling process

4427  * is misplaced in core the text image might not fit.

4428  * Quite possibly the code after "out:" could check to

4429  * see if the text does fit and simply swap it in.

4430  *

4431  * panic: out of swap space

4432  */

4433 xalloc(ip)

  • 警告 :本函数相当含蓄
  • 本函数并不符合函数规范,其造成的影响要由exec来扫尾
  • 只可视为从exec抽取的代码段
4434 int *ip;

4435 {

4436     register struct text *xp;

4437     register *rp, ts;

4438

4439     if(u.u_arg[1] == 0) return;

  • 若 正文大小为0,函数直接返回
4440     rp = NULL;

4441     for(xp = &text[0]; xp < &text[NTEXT]; xp++)

4442          if(xp->x_iptr == NULL) {

4443           if(rp == NULL)

4444                rp = xp;

4445          } else

4446           if(xp->x_iptr == ip) {

4447                xp->x_count++;

4448                u.u_procp->p_textp = xp;

4449                goto out;

4450           }

  • 找到text数组中 与ip对应的元素xp
  • 若找到,则
    • 增加 xp 的引用数
    • 当前进程 正文控制块指针 指向xp
    • 转向4475,进行善后
  • 以下开始创建正文块/正文控制块
4451     if((xp=rp) == NULL) panic("out of text");

4452     xp->x_count = 1;

4453     xp->x_ccount = 0;

4454     xp->x_iptr = ip;

4455     ts = ((u.u_arg[1]+63)>>6) & 01777;

4456     xp->x_size = ts;

  • 设置xp的参数
  • ts ← 正文段 占用 的内存块数(64字节/块)
4457     if((xp->x_daddr = malloc(swapmap, (ts+7)/8)) == NULL)

4458          panic("out of swap space");

  • 分配 交换区空间
4459     expand(USIZE+ts);
  • 扩展 进程图像 = PPDA区 + 正文大小的临时区
  • 分配的临时区,用来读取代码文件中的代码
  • 在4473释放分配的临时区
4460     estabur(0, ts, 0, 0);
  • UISA/UISD 地址管理 设置为 数据区大小为ts,其他区为0
  • 即 数据区大小从 虚拟地址0开始,大小为ts
  • 这里对 UISA/UISD 的修改 需要在exec消除影响,十分不符合函数规范...
4461     u.u_count = u.u_arg[1];

4462     u.u_offset[1] = 020;

4463     u.u_base = 0;

4464     readi(ip);

  • 从 ip 读取正文到 虚拟地址0
  • 文件偏移量 为 020 ,文件正文段从020偏移开始
参考 man a.out
4465     rp = u.u_procp;

4466     rp->p_flag =| SLOCK;

4467     swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0);

4468     rp->p_flag =& ~SLOCK;

  • 将 刚读入的正文 交换到 盘交换区
  • 进程置锁 防止 写盘交换区中 该进程被切换上台
4469     rp->p_textp = xp;

4470     rp = ip;

4471     rp->i_flag =| ITEXT;

  • ip 置 ITEXT,防止被写
4472     rp->i_count++;

4473     expand(USIZE);

  • 释放 4459 分配的临时区
4474 out:

4475     if(xp->x_ccount == 0) {

4476          savu(u.u_rsav);

4477          savu(u.u_ssav);

4478          xswap(u.u_procp, 1, 0);

4479          u.u_procp->p_flag =| SSWAP;

4480          swtch();

4481          /* no return */

4482     }

  • 若 正文段 不被 图像在内存中的进程 引用,则将进程交换到盘交换区(诡异的做法,参看说明)
4483     xp->x_ccount++;

4484 }

4485 /* ------------------------- */

Extend

说明

该函数相当诡异,以下做以说明

  • 在4449产生分支
    • 若 已存在对应的正文控制块,则跳转到4474
    • 否则,开始创建 正文块/正文控制块
  • 诡异的问题
    • 创建的 正文控制块 创建在盘交换区上
    • 然后,将现行进程 交换到盘交换区上
    • 这个操作看似没有效率,而且很诡异,原因如下
      • 进程调度切换程序(sched)上台时 总是先将 正文段交换到内存,再将图像交换到内存
      • 若 图像在内存,正文段在交换区,且满足条件rp->x_ccount == 0 (2033),则会引起错误
      • 所以需要将 图像交换到盘交换区
    • 从4449转过来的情况,也会出现如此情况

Ref

Caller

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