Write a simple version of the UNIX xargs program for xv6: its arguments describe a command to run, it reads lines from the standard input, and it runs the command for each line, appending the line to the command's arguments. Your solution should be in the file user/xargs.c.
0. xargs..?
↑ ↑ xargs 명령어를 아주아주 잘 설명한 글이 있어 소개한다.
1. find.c -> find() 변경
'Exercise 1-4. find'에서 작성한 코드대로 실행하면, 0번 fd(== stdin)에 결괏값이 잘 담기지 않는 문제가 있어 user/find.c를 다음과 같이 수정하였다.
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
void find(char* InitDir, char* FileName) {
int fd_dir; // fd for Directory
char Buf[512] = { 0, };
char *p;
struct stat st;
struct dirent de;
if ((fd_dir = open(InitDir, 0)) < 0) {
fprintf(2, "[!] failed to open %s\n", InitDir);
close(fd_dir);
exit(1);
}
if (fstat(fd_dir, &st) < 0) {
fprintf(2, "[!] fstat() failed\n");
close(fd_dir);
exit(1);
}
if (st.type != T_DIR) {
fprintf(2, "[!] %s is not a directory\n", InitDir);
fprintf(2, "Usage: find [target_dir] [file_name]\n");
close(fd_dir);
exit(1);
}
strcpy(Buf, InitDir);
p = Buf+strlen(Buf);
*p++ = '/';
while (read(fd_dir, &de, sizeof(de)) == sizeof(de) && de.name[0]) {
if (!strcmp(de.name, ".") || !strcmp(de.name, ".."))
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
stat(Buf, &st);
if(!strcmp(de.name, FileName) && st.type == T_FILE){
printf("%s\n", Buf);
}
if (st.type == T_DIR) {
find(Buf, FileName);
}
}
close(fd_dir);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
fprintf(2, "Usage: find [target_dir] [file_name]\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
- 변경점: Line 50에서 find() 함수를 재귀적으로 호출할 때, fork()를 사용하지 않고 하나의 프로세스에서 호출하도록 변경하였다.
2. xargs.c
[!] exec() 사용 시, fork()와 함께 사용해야 하는 이유
"The exec system call replaces the calling process’s memory with a new memory image loaded from a file stored in the file system." (xv6 pdf 12페이지)
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/param.h"
#include "user/user.h"
#define MAXLEN 512
char CutStr(char* InitStr, char** ArgArr, char TargetChar){
char* StartPtr;
char* EndPtr;
int Idx = 0;
StartPtr = InitStr;
for(int i = 0; InitStr[i] != 0; i++){
if(InitStr[i] == TargetChar){
EndPtr = InitStr+i;
ArgArr[Idx] = (char*)malloc(EndPtr-StartPtr+1); // added 1, for NULL
memset(ArgArr[Idx], 0x0, EndPtr-StartPtr+1+1);
for(int j = 0; j < EndPtr-StartPtr; j++){
ArgArr[Idx][j] = StartPtr[j];
}
Idx++;
StartPtr = EndPtr+1;
}
if(Idx==33){
fprintf(2, "[!] Count of args is larger than MAXARG(32)\n");
return 0;
}
}
return 1;
}
int main(int argc, char* argv[]){
char ExitStatus = 0;
char Buf[2048] = {0,}; // Init String(left side of the pipe's result)
char* LeftArg[MAXARG]; // left side of the pipe's string will be cutted then, stored.
char* XargsArg[MAXARG]; // Args for Xargs will be stored
memset(LeftArg, 0x0, sizeof(char*)*MAXARG);
memset(XargsArg, 0x0, sizeof(char*)*MAXARG);
read(0, Buf, 2048);
if(Buf[2048-1]){
fprintf(2, "[!] left result's length is larger than 2048\n");
exit(1);
}
if(!CutStr(Buf, LeftArg, '\n')){
ExitStatus = 1;
goto clean_up;
}
for(int i = 1; argv[i] != 0; i++){
XargsArg[i-1] = argv[i];
}
for(int i = 0; LeftArg[i] != 0; i++){
XargsArg[argc-1] = LeftArg[i];
if(!fork()){ // child
exec(argv[1], XargsArg);
}
else{ // parent
wait(0);
}
}
clean_up:
for(int i = 0; LeftArg[i] != 0; i++){
free(LeftArg[i]);
}
exit(ExitStatus);
}
'xv6:2024 > Chapter 1' 카테고리의 다른 글
Exercise 1-4. find (0) | 2024.11.18 |
---|---|
Exercise 1-3. primes (0) | 2024.11.16 |
Exercise 1-2. pingpong (0) | 2024.11.16 |
Exercise 1-1. sleep (0) | 2024.11.16 |
xv6's every system call && read() from the pipe (1) | 2024.11.16 |