xv6
Ctrl-Cブレークの実装 - xv6 †
概要 †
xv6のシェルにはCtrl-Cで実行中のプロセスを落とす機能がない。さすがに不便なので、console.cとproc.cを編集して、Ctrl-Cブレークを実装することにする。
実装方針 †
xv6には、Ctrl-Pによる割り込み(プロセスリストのダンプ)がはじめから実装されている。console.c中のconsoleintr関数がそれにあたる。よく読むと、Ctrl-P以外にもCtrl-Uによる入力内容クリア、Ctrl-Hによるバックスペースも実装されている。ここにCtrl-Cを押した場合の処理を記述する。
処理の内容は以下のようにする。
- プロセスリストから、状態がRUNNINGであるプロセスを選ぶ
- プロセス名がinitでなければkillして、"aborted process id: (pid)"を表示する
- killした場合、1を返し、killしなかった場合0を返す
- 1が返ってきた場合、breakしてシェルに戻す
- 0が返ってきた場合、そのままスルーしてCtrl+Uと同じ処理を行う
プロセスに関するコードは、proc.cの中に書かれている。Ctrl-Pから呼び出されるprocdump関数を参考に、プロセスを殺すabortproc関数を実装する。
コード例 †
- proc.c:
int
abortproc(void)
{
struct proc *p;
int killed=0;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->state == RUNNING){
if(!(p->name[0]=='i' && p->name[1]=='n' && p->name[2]=='i' && p->name[3]=='t')&&!p->killed){
cprintf("aborted process id: %d\n",p->pid);
kill(p->pid);
killed=1;
}
}
}
return killed;
}
- console.c:
void
consoleintr(int (*getc)(void))
{
int c;
acquire(&input.lock);
while((c = getc()) >= 0){
switch(c){
case C('P'): // Process listing.
procdump();
break;
case C('C'): // Kill current process.
if(abortproc()){
break;
}
case C('U'): // Kill line.
while(input.e != input.w &&
input.buf[(input.e-1) % INPUT_BUF] != '\n'){
input.e--;
consputc(BACKSPACE);
}
break;
case C('H'): case '\x7f': // Backspace
if(input.e != input.w){
...
これで実装できた。
実行 †
$ ls
. 1 1 512
.. 1 1 512
README 2 2 1927
cat 2 3 10602
echo 2 4 10063
forktest 2 5 6696
grep 2 6 11886
init 2 7 10440
kill 2 8 10075
ln aborted process id: 3
$
$ cat hogehoge
ここで、Ctrl-Cを押すと、↓
$