Day2
继续lab1~
primes
依旧是看看题目:
- pipe和fork设置管道,第一个进程输入数字2-35,每个素数创建一个进程,左读右写(0读1写),第一个进程可以停在第三十五个?
- 关闭进程不需要的文件描述符,一旦第一个进程达到35,则应该等待整个管道终止。
- 当写入端关闭时,read返回0(写入0)
- 管道里创建流程?
思路:
- 构造一个筛子函数,和一个main函数
- 首先main函数构造一个管道left,第一个进程负责向管道写入2-35的进程,写入后关闭写入窗口。
- fork1:根据fork()的返回值判断是父进程还是子进程还是错误
- 父进程:不做任何事情,等待,关闭
- 子进程:执行sift(left),执行结束后关闭
- sift即筛子函数,用递归的形式输出筛出后的内容。
- 首先传入left管道,关闭left管道的写入端
- 创建n,j,right管道
- Hint:
readreturns zero when the write-side of a pipe is closed.,根据这句话,读取一个数n,加一个判定:若返回0.直接退出 - 输出n,n既是过筛的素数,
- 再根据pid = fork(),判断fork的返回值,去决定是父进程还是子进程
- pid < 0,错误,关闭left,right的读写,退出~
- pid > 0,父进程,即当前进程,进行过筛,写入right
- pid =0,子进程,继续递归sift(right),这次把right 作为left传入
- make qemu,make grade,成功~
这题卡了好久,总共得有个四五个小时吧emmm,看别人的才知道得用两个管道,且需要关闭管道的读写,不然顺序会变化。不过最终还是过了~~~
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
//需要使用开关,且使用两个进程,一个左读右写,一个右写等待子进程读取
void sift(int left[2]){
close(left[1]);
int n,j,right[2];
int pid;
pipe(right);
if(read(left[0],&n,4) == 0 ){
exit(0);
}
printf("prime ");
printf("%d\n",n);
if((pid = fork()) < 0){
fprintf(2, "Error:sift error..\n");
close(left[0]);
close(right[0]);
close(right[1]);
}else if(pid > 0){
//接受left,传递right
close(right[0]);
while(read(left[0],&j,4) > 0){
if(j % n != 0){
// printf("%d",j);
write(right[1],&j,4);
}
}
close(right[1]);
wait(0);
exit(0);
}else{
sift(right);
exit(0);
}
}
int main(){
int left[2];
int i;
int pid;
pipe(left);
for(i = 2; i <= 35; i++){
write(left[1],&i,4);
}
close(left[1]);
pid = fork();
if(pid < 0){
fprintf(2, "Error:main error...\n");
exit(1);
}else if(pid > 0){
wait(0);
exit(0);
}else{
sift(left);
exit(0);
}
return 0;
}
find(moderate)
首先还是来看下题目:
- 写一个unix查找程序,查找目录树中具有特定名称的所有文件
- 这一看就是递归查找,然后比较文件名啊
先创建文件和加入Makefile
思路:
- 创建一个函数,参数:目录名,依次输出目录下的文件名,判断是否和函数对应
- 输出文件名的时候,如果是子文件夹,递归,参数为子文件夹的目录名
- 退出
这题就是把ls改了一下,没什么奇技淫巧,边玩边写,看别人撕逼去了emmm
#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 find(char *name,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_FILE:
if(strcmp(name,fmtname(path)) == -32)
printf("%s\n", path);
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;
}
if(strcmp("..",fmtname(buf)) != -32&&strcmp(".",fmtname(buf)) != -32){
find(name,buf);
}
}
break;
}
close(fd);
}
int main(int argc,char *argv[]){
int i;
if(argc < 2){
exit(0);
}
for(i = 1; i < argc;i++){
find(argv[i+1],argv[i]);
i++;
}
exit(0);
}
xargs(moderate)
首先来看看题目
编写一个简单的xargs,从标准输入中读取行并为每行运行一个命令,改行作为参数提供给命令
-
example1:
- $ echo hello too | xargs echo bye
- bye hello too
-
example2:
echo "1\n2" | xargs -n 1 echo line line 1 line 2 -
这里的xargs好像执行的是一个附加的操作,在之前指令上附加一些指令
-
fork,exec去执行指令,wait去让父亲进程等待子进程完成
-
行与行之间使用\n分割
还是先列一下思路:
- 首先还是argv < 2,发送错误指令
- 然后argv[1]是需要执行的指令
- 当
好吧卡了两小时写不出来,不想写了,去看下一章课去了。