操作系統源碼閱讀 - 3 : 自定義命令
閱讀源碼,幫助理解操作系統。
上一篇:操作系統源碼閱讀 - 2 : 基礎命令與操作系統接口
head命令
在xv6系統上實現head命令。head命令用來顯示開頭某個數量的文字區塊。在自定義實現中,head命令一共有三種形式。
head filename
head [-number] filename
head [-n] number filename
函數實現
具體實現上,考慮抽象爲一個函數head(int fd, int number),用來實現讀取文件描述符爲fd的文件的前number行內容並輸出。同時,在main()函數中,分別分析head命令的三種模式,並依次調用head()函數。實現文件爲head.c,核心代碼如下:
char buf[512];
void head(int fd,int line)
{
int n, i;
int tag = 0;
while((n = read(fd,buf, sizeof(buf))) > 0)
{
for(i = 0;i < n;i ++)
{
if(buf[i] == '\n')
{
tag = tag + 1;
if(tag == line)
{
i = i + 1;
break;
}
}
}
if(write(1,buf, i) != i)
{
printf(1, "head: write error\n");
exit();
}
if(tag == line)
{
break;
}
}
if(n < 0)
{
printf(1,"head: read error\n");
exit();
}
}
int main(int argc, char * argv[])
{
int fd;
int line;
if(argc < 2)
{
printf(1,"head: no parameters\n");
exit();
}
else if (argc == 2)
{
if((fd = open(argv[1],0)) < 0)
{
printf(1,"head: cannot open %s\n", argv[1]);
exit();
}
line = 10;
head(fd,line);
close(fd);
exit();
}
else if (argc == 3)
{
if(argv[1][0]!= '-')
{
printf(1,"head: wrong parameters\n");
exit();
}
else
{
line = 0;
for(int i = 1;argv[1][i] != '\0';i ++)
{
int tem = (argv[1][i] - '0');
line = line*10 + tem;
}
if((fd = open(argv[2],0)) < 0)
{
printf(1,"head: cannot open %s\n", argv[2]);
exit();
}
head(fd,line);
close(fd);
}
exit();
}
else
{
if(argv[1][0]!= '-'||argv[1][1]!='n'||argv[1][2]!='\0')
{
printf(1,"head: wrong parameters\n");
exit();
}
else
{
line = 0;
for(int i = 0;argv[2][i] != '\0';i ++)
{
int tem = (argv[2][i] - '0');
line = line*10 + tem;
}
if((fd = open(argv[3],0)) < 0)
{
printf(1,"head: cannot open %s\n", argv[3]);
exit();
}
head(fd,line);
close(fd);
}
exit();
}
}
參考cat命令的實現即可。
修改Makefile文件
實現head.c文件之後,需要將該文件添加到Makefile文件的編譯序列中,具體修改如下:
UPROGS=\
_cat\
_echo\
_forktest\
_grep\
_head\
_init\
_kill\
_ln\
_ls\
_mkdir\
_rm\
_sh\
_stressfs\
_usertests\
_wc\
_zombie\
## 添加_head\。當os運行時,通過ls命令可以找到head程序。
EXTRA=\
mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c head.c kill.c\
ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\
printf.c umalloc.c\
README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\
.gdbinit.tmpl gdbutil\
## 添加head.c。將head.c添加到編譯隊列
之後,按流程進行編譯,運行即可。實驗結果如下: