在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命令的实现即可。
实现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添加到编译队列之后,按流程进行编译,运行即可。实验结果如下: