分享

OS Lab 1.6 xargs (moderate)

 菜籽爱编程 2022-04-27
1
实验要求

编写一个简单的 UNIX xargs 程序,从标准输入中读取行并为每一行运行一个命令,将该行作为命令的参数提供。你的解决方案应该放在 user/xargs.c 中。

2
实验提示
  • 使用 fork()exec() 在每一行输入上调用命令。在 parent 中使用 wait() 等待 child 完成命令。
  • 要读取单个输入行,请一次读取一个字符,直到出现换行符('\n')。
  • kernel/param.h 声明了 MAXARG ,如果你需要声明一个 argv 数组,这可能很有用。
  • 将程序添加到 MakefileUPROGS 中。
  • 文件系统的变化在 qemu 的运行中持续存在。使用 make clean 然后再 make qemu 让一个干净的文件系统运行。
3
实验思路
  1. 根据提示,我们需要调用 fork() 创建子进程,和调用 exec() 执行命令。我们知道要从标准输入中读取行并为每行运行一个命令,且将该行作为命令的参数。即把输入的字符放到命令后面,然后调用 exec() 。我们可以依次处理每行,根据空格符和换行符分割参数,调用子进程执行命令。
  2. 首先,我们定义一个字符数组,作为子进程的参数列表,其大小设置为 kernel/param.h 中定义的 MAXARG ,用于存放子进程要执行的参数。而后,建立一个索引便于后面追加参数,并循环拷贝一份命令行参数,即拷贝 xargs 后面跟的参数。创建缓冲区,用于存放从管道读出的数据。
  3. 然后,循环读取管道中的数据,放入缓冲区,建立一个新的临时缓冲区存放追加的参数。把临时缓冲区追加到子进程参数列表后面。并循环获取缓冲区字符,当该字符不是换行符时,直接给临时缓冲区;否则创建一个子进程,把执行的命令和参数列表传入 exec() 函数中,执行命令。当然,这里一定要注意,父进程一定得等待子进程执行完毕。
4
实验代码
// Lab Xv6 and Unix utilities
// xargs.c

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"

#define MAXN 1024

int
main(int argc, char *argv[])
{
    // 如果参数个数小于 2
    if (argc < 2) {
        // 打印参数错误提示
        fprintf(2"usage: xargs command\n");
        // 异常退出
        exit(1);
    }
    // 存放子进程 exec 的参数
    char * argvs[MAXARG];
    // 索引
    int index = 0;
    // 略去 xargs ,用来保存命令行参数
    for (int i = 1; i < argc; ++i) {
        argvs[index++] = argv[i];
    }
    // 缓冲区存放从管道读出的数据
    char buf[MAXN] = {"\0"};
    
    int n;
 // 0 代表的是管道的 0,也就是从管道循环读取数据
    while((n = read(0, buf, MAXN)) > 0 ) {
        // 临时缓冲区存放追加的参数
  char temp[MAXN] = {"\0"};
        // xargs 命令的参数后面再追加参数
        argvs[index] = temp;
        // 内循环获取追加的参数并创建子进程执行命令
        for(int i = 0; i < strlen(buf); ++i) {
            // 读取单个输入行,当遇到换行符时,创建子线程
            if(buf[i] == '\n') {
                // 创建子线程执行命令
                if (fork() == 0) {
                    exec(argv[1], argvs);
                }
                // 等待子线程执行完毕
                wait(0);
            } else {
                // 否则,读取管道的输出作为输入
                temp[i] = buf[i];
            }
        }
    }
    // 正常退出
    exit(0);
}
5
实验结果

Makefile 文件中, UPROGS 项追加一行 $U/_xargs\ 。编译并运行 xv6 进行测试。

$ make clean
...
$ make qemu
...
init: starting sh
$ echo hello too | xargs echo bye
bye hello too

退出 xv6 ,运行单元测试检查结果是否正确。

./grade-lab-util xargs

通过测试样例。

make: 'kernel/kernel' is up to date.
== Test xargs == xargs: OK (1.8s) 

你不赞👍,我不赞👍,up推文没人看

你关注👇,我关注👇,下次再来不迷路

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多