OS
[xv6] Lab: Xv6 and Unix utilities
포뇨링
2023. 2. 1. 05:38
Sleep
Implement the UNIX program sleep for xv6; your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your solution should be in the file user/sleep.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc, char *argv[]){
if(argc < 2){
fprintf(2, "Usage: sleep time...\n");
exit(1);
}
sleep(atoi(argv[1]));
exit(0);
}
Pingpong
Write a program that uses UNIX system calls to ''ping-pong'' a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print "<pid>: received ping", where <pid> is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print "<pid>: received pong", and exit. Your solution should be in the file user/pingpong.c
pipe, fork, getuid 이용해 child가 ping하면 parent가 pong하는 것 구현.
→ pipe를 이용해 parent/child 프로세스간 공유 가능. child 프로세스가 종료된 후 parent 프로세스가 실행되어야하므로 wait 필요
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(){
char buf[3];
int p[2];
pipe(p);
if(fork()==0){ //child
close(p[0]);
strcpy(buf, "hh");
write(p[1], buf, strlen(buf));
printf("%d: received ping\n",getpid());
}
else{
wait(0);
close(p[1]);
read(p[0], buf, 3);
printf("%d: received pong\n",getpid());
}
exit(0);
}
primes
Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, inventor of Unix pipes. The picture halfway down this page and the surrounding text explain how to do it. Your solution should be in the file user/primes.c
fork, pipe로 에라토스테네스 체 구현
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int filter(int p, int prime){
int fd[2];
int n;
pipe(fd);
if(fork()==0){
close(fd[0]);
printf("prime %d\n", prime);
while(read(p,&n,sizeof(int))){
if(n%prime!=0){
write(fd[1],&n,sizeof(int));
}
}
exit(0);
}
else{
wait(0);
close(fd[1]);
close(p);
return fd[0];
}
}
int main(void){
int p[2];
pipe(p);
int prime;
if(fork() == 0){
close(p[0]);
for(int i=2;i<36;i++){
write(p[1],&i,sizeof(int));
}
}
else{
wait(0);
close(p[1]);
while(read(p[0],&prime, sizeof(int))){
p[0] = filter(p[0], prime);
}
}
exit(0);
}
find
Write a simple version of the UNIX find program: find all the files in a directory tree with a specific name. Your solution should be in the file user/find.c
유닉스 find의 간단한 버전을 작성하라? 해당 디렉토리 트리에 있는 특정이름을 가진 파일을 찾아라.
뭔가 흠 막막하다. ls참고하라고 해서 열어봤더니 이거 좀만 변형하면 될 것 같다.
아래가 ls 코드.
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
char*
fmtname(char *path)
{
static char buf[DIRSIZ+1];
char *p;
// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;
// Return blank-padded name.
if(strlen(p) >= DIRSIZ)
return p;
memmove(buf, p, strlen(p));
memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
return buf;
}
void
ls(char *path)
{
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
fprintf(2, "ls: cannot open %s\n", path);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "ls: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type){
case T_DEVICE:
case T_FILE:
printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size);
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("ls: path too long\n");
break;
}
strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("ls: cannot stat %s\n", buf);
continue;
}
printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
}
break;
}
close(fd);
}
int
main(int argc, char *argv[])
{
int i;
if(argc < 2){
ls(".");
exit(0);
}
for(i=1; i<argc; i++)
ls(argv[i]);
exit(0);
}
fmtname이 ‘/’이후(경로제외) 이름을 간략화해서 return함
이게 파일이면 출력하는거고 디렉토리면 파일 나올떄까지 계속 path에서 읽어온다. C 오랜만에 읽으니까.. 어지럽네?
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
fmtname(char *path){
static char buf[DIRSIZ+1];
char *p;
// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--);
p++;
return p;
}
void
find(char *path, char *filename){
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
fprintf(2, "ls: cannot open %s\n", path);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "ls: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type){
case T_DEVICE:
case T_FILE:
if(strcmp(fmtname(path), filename)==0){
printf("%s\n", path);
}
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("find: path too long\n");
break;
}
strcpy(buf, path);
p = buf+strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
if(strcmp(".",de.name)==0||strcmp("..", de.name)==0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
find(buf, filename);
if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
}
}
break;
}
close(fd);
}
int main(int argc, char *argv[]){
find(argv[1],argv[2]);
exit(0);
}
ls와 비교해서 바꾼건 얼마 없다.
if(strcmp(fmtname(path), filename)==0){
printf("%s\n", path);
}
파일이 해당 이름을 가질 경우 경로 출력&종료
if(strcmp(".",de.name)==0||strcmp("..", de.name)==0)
continue;
.이랑 ..있음 얘네는 건너뛰는 코드
find(buf, filename);
재귀를 통해 하위 디렉토리를 찾는 코드
fmtname을 좀 간략하게 바꾸니까 됨.. 왜?
(굳이 padding안하고 걍 바로 return p함)
xargs
Write a simple version of the UNIX xargs program: 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 .
help me..이게 뭐여…
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/param.h"
#include "user/user.h"
int main(int argc, char *argv[]){
char *para[MAXARG];
char buf[1024];
int para_idx=0;
int buf_idx=0;
char ch;
char* p = buf;
for(int i=1;i<argc;i++){
para[para_idx++]=argv[i];
}
while(read(0,&ch,1)){
if(ch==' '){
buf[buf_idx++]=0;
para[para_idx++]=p;
p=buf+buf_idx;
}
else if(ch=='\n'){
para[para_idx++] = p;
p = buf+buf_idx;
if(fork()==0){
exec(argv[1], para);
exit(0);
}
else{
wait(0);
para_idx = argc-1;
}
}
else{
buf[buf_idx++]=ch;
}
}
exit(0);
}