阅读源码,帮助理解操作系统。
echo命令实现
从简单的命令开始理解。echo命令,在下一行输出echo后面输入的文字。在xv6操作系统中,有单独的echo.c文件,实现echo命令,文件核心代码如下:
int main(int argc, char *argv[])
{
int i;
for(i = 1; i < argc; i++)
printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n");
exit();
}
实现代码特别简单,主要是讲参数传递到printf函数,实现输出。需要注意的是,echo程序入口是main()函数,表明这是一个完成的进程,入口为main(),exit()结束进程。因此,当执行echo命令的时候,操作系统实际上涉及到了系统中断和进程切换。
printf()函数,在printf.c文件中实现。printf.c文件中有三个函数,printf(),printint(),putc()。实际上,printf()调用printint(),putc()函数,printint()函数也调用putc()函数。因此,printf()函数主要以来putc()函数来实现。putc()函数代码如下:
static void putc(int fd, char c)
{
write(fd, &c, 1);
}
putc()函数实际上有调用系统接口write()(也叫系统调用,system call)。接口具体说明可以见xv6系统调用。
cat命令实现
cat命令比echo命令要复杂一点,需要调用的系统接口函数也要多一点。由单独的cat.c文件来实现函数功能。核心代码如下:
void cat(int fd)
{
int n;
while((n = read(fd, buf, sizeof(buf))) > 0) {
if (write(1, buf, n) != n) {
printf(1, "cat: write error\n");
exit();
}
}
if(n < 0){
printf(1, "cat: read error\n");
exit();
}
}
int main(int argc, char *argv[])
{
int fd, i;
if(argc <= 1){
cat(0);
exit();
}
for(i = 1; i < argc; i++){
if((fd = open(argv[i], 0)) < 0){
printf(1, "cat: cannot open %s\n", argv[i]);
exit();
}
cat(fd);
close(fd);
}
exit();
}
具体来说,cat功能,首先调用open()函数,返回一个文件描述符,将该文件描述符号传递到read()函数,依次读出512字节的文件内容,将该内容通过write()函数输出到终端,知道文件内容全部读完。再调用close()函数,关闭文件读取。算是一个相对复杂的命令实现。