6.s081 lab1 util
lab1
选择分支
git checkout util
Boot xv6
环境参考 lab0
sleep
为shell 添加一个可执行的 sleep 程序
在 xv6-labs-2020/usr 添加一个 sleep.c 的文件,作为 sleep 工具代码(用户态)
然后使用 user/user.h 的系统调用来执行 sleep 操作
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc, char* argv[])
{
if (argc != 2)
{
fprintf(0, "usage: sleep <number>\n");
exit(1);
}
int number = atoi(argv[1]);
sleep(number);
exit(0);
}
最后要 exit(0); 不能 return
在 Makefile 添加
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
$U/_init\
$U/_kill\
$U/_ln\
$U/_ls\
$U/_mkdir\
$U/_rm\
$U/_sh\
$U/_stressfs\
$U/_usertests\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_sleep\
pingpong
为shell 添加一个可执行的 pingpong 程序
父进程 通过管道发送 ping
子进程通过管道收到ping之后 给父进程发送 pong
管道是单向的,为了实现父子进程双边通信,需要使用两个管道
#include "user/user.h"
int main(int argc, char const *argv[])
{
int cp[2];
int fp[2];
pipe(cp);
pipe(fp);
int pid = fork();
if (pid==0)
{
close(fp[1]);
char ping[20];
read(fp[0],ping,20);
printf("%d: %s\n",getpid(),ping);
close(cp[0]);
char pong[20]="received pong";
write(cp[1],pong,20);
int status;
wait(&status);
}else{
close(fp[0]);
char ping[20]="received ping";
write(fp[1],ping,20);
close(cp[1]);
char pong[20];
read(cp[0],pong,20);
printf("%d: %s\n", getpid(),pong);
}
exit(0);
//return 0;
}
primes
递归筛选素数,findPrimes(int *array, int len) ,为递归方法,参数是一个数组和长度。
findPrimes 有一个父进程和子进程执行任务。
主进程->打印最小的数,过滤,用管道给子进程发送 新数组
子进程->收到新数组 递归调用 findPrimes()
#include "user/user.h"
#define NUMS 34
void findPrimes(int *array, int len);
int main(int argc, char const *argv[])
{
int* array = (int*)malloc(NUMS * sizeof(int));
for (int i = 0; i < NUMS + 2; i++)
{
array[i]=i+2;
}
findPrimes(array,NUMS);
wait(0);
free(array);
exit(0);
}
void findPrimes(int *array, int len){
if (len == 0){
exit(0);
//return;
}
if (len == 1 ){
printf("prime %d\n",array[0]);
exit(0);
}
int p[2];
pipe(p);
int pid = fork();
if (pid == 0)
{
close(p[1]);
// 2.1读取数组长度
int curLen = 0;
read(p[0], &curLen, sizeof(int));
//2.2读取管道array
int* curArray = (int*)malloc(curLen * sizeof(int));
if (curArray==0)
{
printf("error curArray malloc\n");
}
if (read(p[0],curArray,curLen * sizeof(int)) != curLen * sizeof(int)) {
printf("error read array\n");
exit(-1);
}
close(p[0]); // 关闭读端
findPrimes(curArray,curLen);
free(curArray);
exit(0);
}else{
close(p[0]);
int min = array[0];
printf("prime %d\n",min);
int nextLen = 0;
int* newArray = (int*)malloc(len * sizeof(int));
if (newArray == 0) {
printf("error newArray malloc\n");
exit(-1);
}
for (int i = 1; i < len; i++)
{
if (array[i] % min != 0) {
newArray[nextLen] = array[i];
nextLen++;
}
}
if (nextLen!=0)
{
//1.1管道发送array长度
if (write(p[1], &nextLen, sizeof(int)) != sizeof(int)) {
printf("error write length\n");
exit(-1);
}
//1.2管道发送array
if (write(p[1], newArray, nextLen * sizeof(int)) != nextLen * sizeof(int)) {
printf("error write array\n");
exit(-1);
}
}
close(p[1]);
//等待子进程
wait(0);
free(newArray);
}
}
find
参考 ls.c 代码,ls是查询当前目录的所有文件
find.c 只需要在ls的基础上,找到输入的文件,如果是目录递归调用find
#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;
}
//findName可能是目录名 或 文件名
void findFile(char *findName,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){
//输入的path是文件直接打印出来
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;
}
//path 复制到 buf
strcpy(buf, path);
p = buf+strlen(buf);
//buf 最后加一个/ -> path/
*p++ = '/';
//读目录下面所有文件
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
// 给 path/ 后面加上这个文件- > path/filename
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("ls: cannot stat %s\n", buf);
continue;
}
//buf 是 path/filename
//只取最后的filename
char *tmpfilename = buf;
for (char *curP = buf; *curP != '\0'; curP++) {
if (*curP == '/') {
tmpfilename = curP + 1;
}
}
//如果buf path/filename 是目录那么递归
if (st.type==T_DIR){
if (strcmp(tmpfilename,".")==0 || strcmp(tmpfilename,"..")==0)
{
continue;
}
//目录名比较
if (strcmp(tmpfilename, findName)==0){
//printf("%s %d %d %d\n",buf , st.type, st.ino, st.size);
printf("%s\n",buf);
}
//递归
findFile(findName,buf);
}else if (st.type==T_FILE){
//文件名比较
if (strcmp(tmpfilename, findName)==0){
//printf("%s %d %d %d\n",buf , st.type, st.ino, st.size);
printf("%s\n",buf);
}
}
}
break;
}
close(fd);
return;
}
int main(int argc, char *argv[])
{
if(argc < 3){
printf("miss parameters\n");
exit(0);
}
char *findName = argv[2];
char *findPath = argv[1];
findFile(findName,findPath);
exit(0);
}
实验结果
