6.S081:5.xargs命令实现


6.S081:5.xargs命令实现

xargs (moderate)

Write a simple version of the UNIX xargs program: read lines from the standard input and run a command for each line, supplying the line as arguments to the command. Your solution should be in the file user/xargs.c.

The following example illustrates xarg's behavior:

$ echo hello too | xargs echo bye
bye hello too
$

Note that the command here is "echo bye" and the additional arguments are "hello too", making the command "echo bye hello too", which outputs "bye hello too".

Please note that xargs on UNIX makes an optimization where it will feed more than argument to the command at a time. We don't expect you to make this optimization. To make xargs on UNIX behave the way we want it to for this lab, please run it with the -n option set to 1. For instance

$ echo "1\n2" | xargs -n 1 echo line
line 1
line 2
$

Some hints:

  • Use fork and exec to invoke the command on each line of input. Use wait in the parent to wait for the child to complete the command.
  • To read individual lines of input, read a character at a time until a newline ('') appears.
  • kernel/param.h declares MAXARG, which may be useful if you need to declare an argv array.
  • Add the program to UPROGS in Makefile.
  • Changes to the file system persist across runs of qemu; to get a clean file system run make clean and then make qemu.

xargs, find, and grep combine well:

$ find . b | xargs grep hello

will run "grep hello" on each file named b in the directories below ".".

To test your solution for xargs, run the shell script xargstest.sh. Your solution is correct if it produces the following output:

$ make qemu
...
init: starting sh
$ sh < xargstest.sh
$ $ $ $ $ $ hello
hello
hello
$ $   

You may have to go back and fix bugs in your find program. The output has many $ because the xv6 shell doesn't realize it is processing commands from a file instead of from the console, and prints a $ for each command in the file.

思考

需要用到管道命令,但不需要在xargs里面创建管道,只需从标准输出中读取前一条命令的结果即可,若又多个结果,则遇到一个换行符就停止读取。xargs后是命令 参数,显然需要父进程fork出一个子进程来执行后面的命令,并且将读取的结果附加到命令参数中。

值得注意的是,从标准输出中读取字符串时,本题推荐一个字符顺序读取(直接读取一个字符串,似乎会产生一些问题,暂时未解决)

然后就是一些字符串的简单处理,这里就直接放上代码了

Code

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

int main(int argc, char *argv[]){
    char buf[MAXARG];
    char *parse[MAXARG];

    while(1){
        memset(parse, 0, MAXARG);
        for(int i = 0; i < argc; i++) parse[i] = argv[i];
        int idx = argc, cnt = 0;
        while(read(0, &buf[cnt], sizeof(char))){
            if(buf[cnt] == '\n') break;
            cnt++;
        }
        //printf("cnt = %d, buf = %s\n", cnt, buf);
        if(cnt == 0) break;
        buf[cnt] = '\0';
        parse[idx++] = buf;
        int i = 1;
        while(i < strlen(buf)){
            if(buf[i] == ' '){
                buf[i] = '\0';
                parse[idx++] = buf + i + 1;
            }
            i++;
        }

        int pid = fork();
        if(pid == 0) exec(parse[1], parse + 1);

        wait(0);
    }
    exit(0);
}

Author: Paranoid
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Paranoid !
评论
  TOC