iT邦幫忙

0

[6.1810][code] xv6 的 Processes (四)

  • 分享至 

  • xImage
  •  

系列文章 : [6.1810] 跟著 MIT 6.1810 學習基礎作業系統觀念

大綱

  • kernel/sysproc.c/sys_exit
  • kernel/sysproc.c/sys_getpid
  • kernel/sysproc.c/sys_fork
  • kernel/sysproc.c/sys_wait
  • kernel/sysproc.c/sys_pause
  • kernel/sysproc.c/sys_kill
  • kernel/sysproc.c/sys_uptime
  • kernel/sysproc.c/sys_sbrk

kernel/sysproc.c/sys_exit

uint64
sys_exit(void)
{
  int n;
  argint(0, &n);
  kexit(n);
  return 0;  // not reached
}
  • argint(0, &n);
    • 把 syscall 的第 0 個參數當作 int,並當作 kexit 的參數
    • 這代表了這個 process 的 exit status。當 parent-process 使用 wait 回收這個 process 的時候,這個 exit status 會交給 parent-process。


kernel/sysproc.c/sys_getpid

uint64
sys_getpid(void)
{
  return myproc()->pid;
}

取得當前 process 的 process ID ( PID )。



kernel/sysproc.c/sys_fork

uint64
sys_fork(void)
{
  return kfork();
}

直接去呼叫 kfork。



kernel/sysproc.c/sys_wait

uint64
sys_wait(void)
{
  uint64 p;
  argaddr(0, &p);
  return kwait(p);
}
  • 把第 0 個參數視為 address,這個 address 會成為 kwait 的參數
  • 這個參數代表 child-process 的 exit status 要複製到哪個地方。


kernel/sysproc.c/sys_pause


uint64
sys_pause(void)
{
  int n;
  uint ticks0;

  argint(0, &n);
  if(n < 0)
    n = 0;
  acquire(&tickslock);
  ticks0 = ticks;
  while(ticks - ticks0 < n){
    if(killed(myproc())){
      release(&tickslock);
      return -1;
    }
    sleep(&ticks, &tickslock);
  }
  release(&tickslock);
  return 0;
}
  • this function
    • 這個 function 可以讓 process 陷入睡眠,並且可以指定想要睡多少 ticks。
  • return value
    • -1 : 失敗
    • 0 : 成功
  • argint(0, &n);
    • 從 syscall 第 0 個參數視為 integer。
    • 這裡的 n 代表這次的 pause 想要睡多少 ticks
  • acquire(&tickslock);
    • 想要 access ticks 這個全域變數,就需要先拿這個鎖
  • ticks0
    • 代表進入 pause 的時間點。
  • while(ticks - ticks0 < n){
    • 查看度過的時間有沒有達到 n 個 ticks
  • if(killed(myproc())){
    • 假如這個 process 已經被 kill 要被 kill 掉的話,就不繼續 pause 了,直接退出並 return -1,表示這次的 pause 失敗。
  • sleep(&ticks, &tickslock);
    • 將這個 process 睡在 ticks channel 上,也就是說,所有呼叫 pause 這個 function 的 process,不論想要睡多久,都睡在同一個 channel 上,並且也會同時被喚醒。
    • 在 kernel/trap.c/clockintr,也就是 timer interrupt 的時候,會嘗試去喚醒。


kernel/sysproc.c/sys_kill

uint64
sys_kill(void)
{
  int pid;

  argint(0, &pid);
  return kkill(pid);
}

  • 把 syscall 第 0 個參數視為 int
  • 在這裡的意思是想要 kill 掉的 process 的 PID


kernel/sysproc.c/sys_uptime

// return how many clock tick interrupts have occurred
// since start.
uint64
sys_uptime(void)
{
  uint xticks;

  acquire(&tickslock);
  xticks = ticks;
  release(&tickslock);
  return xticks;
}
  • this function
    • 這個 function 會回傳,從開機到目前為止,總共發生了多少次的 timer interrupt。
  • acquire(&tickslock);
    • 因為想要取用 global ticks value,所以需要先取用 tickslock
  • xticks = ticks
    • 把 global 的 ticks value 複製到 xticks


kernel/sysproc.c/sys_sbrk

uint64
sys_sbrk(void)
{
  uint64 addr;
  int t;
  int n;

  argint(0, &n);
  argint(1, &t);
  addr = myproc()->sz;

  if(t == SBRK_EAGER || n < 0) {
    if(growproc(n) < 0) {
      return -1;
    }
  } else {
    // Lazily allocate memory for this process: increase its memory
    // size but don't allocate memory. If the processes uses the
    // memory, vmfault() will allocate it.
    if(addr + n < addr)
      return -1;
    myproc()->sz += n;
  }
  return addr;
}
  • this function
    • 當一個 process 想要 增加 或是 減少 該 process 正在使用的 virtual memory ( 也就是 struct-proc->sz ) 大小的時候,可以使用這個系統呼叫。
    • 這個系統呼叫支援 立即分配記憶體 ( SBRK_EAGER ),或是 先不分配記憶體 ( Lazily allocate memory )
    • 立即分配記憶體,就是呼叫這個系統呼叫的當下,馬上會用 kalloc 分配記憶體,並將該記憶體的 physical address <-> virtual address 的映射設置在該 process 的 page table。
    • Lazily allocate memory 則只新增該 struct-proc->sz ( 虛擬記憶體使用量 ),並等到 user 使用這個還未分配的部分,發生 page fault 的時候,才會真正分配物理記憶體給該 process。
      • kernel/vm.c/vmfault : 會在這裡真正分配記憶體。
  • return value
    • 失敗 : -1
    • 成功 : 該 process 在呼叫這個 function 之前,舊有的 virtual memory 使用量 ( old struct-proc->sz )
  • argint(0, &n);
    • 假如 n > 0,表示該 process 想使用更多的 virtual address
    • 假如 n < 0,表示該 process 想使用更少的 virtual address
  • argint(1, &t);
    • 此次 allocate 的類型。
    • SBRK_EAGER
      • 代表我們這次 不想要 Lazily allocate memory,呼叫該 function 的當下就要真正的去配置記憶體給該 process。
    • SBRK_LAZY
      • 代表這次是 Lazily allocate memory。等到真的使用到這個區段的 virtual address,並發生 page fault 時候,才會進行真正的記憶體配置。
  • growproc(n)
    • 呼叫這個 function 的話,會立刻 allocate 記憶體 ( n > 0 ),或是立刻 deallocate 記憶體 ( n < 0 )
  • if(addr + n < addr)
    • 表示發生 overflow 了,需要避免。一旦發生就 return -1,表示該 function 執行失敗。
  • myproc()->sz += n;
    • 真正去修改當前 process 的 virtual memory 使用量



圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言