sleep
#include "kernel/types.h"#include "user/user.h"int main(int argc, char *argv[]){if (argc != 2){fprintf(2, "error input\n");exit(1);}int sec = atoi(argv[1]);sleep(sec);exit(0);}
pingpong
#include <kernel/types.h>#include <user/user.h>int main(){//pipe1(p1):写端父进程,读端子进程//pipe2(p2);写端子进程,读端父进程int p1[2],p2[2];//来回传输的字符数组:一个字节char buffer[] = {'X'};//传输字符数组的长度long length = sizeof(buffer);//父进程写,子进程读的pipepipe(p1);//子进程写,父进程读的pipepipe(p2);//子进程if(fork() == 0){//关掉不用的p1[1]、p2[0]close(p1[1]);close(p2[0]);//子进程从pipe1的读端,读取字符数组if(read(p1[0], buffer, length) != length){printf("a--->b read error!");exit(1);}//打印读取到的字符数组printf("%d: received ping\n", getpid());//子进程向pipe2的写端,写入字符数组if(write(p2[1], buffer, length) != length){printf("a<---b write error!");exit(1);}exit(0);}//关掉不用的p1[0]、p2[1]close(p1[0]);close(p2[1]);//父进程向pipe1的写端,写入字符数组if(write(p1[1], buffer, length) != length){printf("a--->b write error!");exit(1);}//父进程从pipe2的读端,读取字符数组if(read(p2[0], buffer, length) != length){printf("a<---b read error!");exit(1);}//打印读取的字符数组printf("%d: received pong\n", getpid());//等待进程子退出wait(0);exit(0);}
primes
#include <kernel/types.h>#include <user/user.h>void child_pro(int p[]) {int x,y;// 用于与子进程通信的管道int child_p[2];// 从父进程读取,所以关闭与父进程连接管道的写入端close(p[1]);// 从父进程读取成功之后的逻辑if (read(p[0],&x,sizeof(int))) {// 打印读取成功后的素数// 上一层中传递的第一个值一定是素数,并且依据这个值筛选素数fprintf(1,"prime %d\n",x);// 创建与子进程通信的管道pipe(child_p);// 再次使用fork,当自身为父进程时if (fork() != 0) {// 关闭与子进程通信的读取端close(child_p[0]);// 从父进程持续读取,读取的数字不为第一个数字的倍数时,持续向子进程写入while (read(p[0], &y, sizeof(int))) {if (y %x != 0) {write(child_p[1], &y, sizeof(int));}}// 关闭从父进程的读取close(p[0]);// 关闭向子进程的写入close(child_p[1]);// 等待子进程完成wait(0);}// 创建子进程else {child_pro(child_p);}}exit(0);}int main(){int p[2];pipe(p);if (fork()!=0) {close(p[0]);// 关闭第一个管道的读取for(int i = 2;i<=35;i++){write(p[1],&i,sizeof(int));}// 主进程,将2到35写入第一个管道close(p[1]);// 关闭第一个管道的写入wait(0);// 等待子进程完成exit(0);}else {child_pro(p);// 执行子进程}exit(0);}
find
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
char* getfilename(char *path)
{
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* target)
{
char buf[512], *p;
int fd;
// 目录项结构体
struct dirent de;
// 文件统计信息
struct stat st;
// 当打开失败的时候,报错
if((fd = open(path, 0)) < 0){
fprintf(2, "find: cannot open %s\n", path);
return;
}
//fstat()用来将参数fildes所指的文件状态,复制到参数buf所指的结构中(struct stat)执行成功则返回0,失败返回-1,错误代码存于errno
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", path);
close(fd);
return;
}
//判断打开的类型
switch(st.type){
// 打开的是文件
case T_FILE:
// 打开的文件与目标匹配,输出
if (strcmp(getfilename(path), target) == 0) {
printf("%s\n", path);
}
break;
// 打开的是路径
case T_DIR:
// 判断是否溢出
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("find: path too long\n");
break;
}
// 把path拷贝到buf里
strcpy(buf, path);
// 指向buf的末尾
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;
}
// 将de.name中的内容移动到p指针所指向的位置,拼接路径字符串
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
}
find(buf, target);
}
break;
}
close(fd);
}
int main(int argc, char *argv[])
{
// 两个参数,起始路径和目标文件
if(argc < 3){
fprintf(2, "find: need 2 args\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
xargs
- shell中的 ‘|‘ 是将标准输出转换为标准输入
- linux中的xargs命令是将标准输入转换为shell命令行参数(http://www.ruanyifeng.com/blog/2019/08/xargs-tutorial.html)
- exec(filename,params),其中param的第一个参数为命令名称,最后一个参数是0

- 命令行一行最长4095bytes
```c
include “kernel/types.h”
include “kernel/stat.h”
include “user/user.h”
include “kernel/param.h”
int main(int argc, char argv[]) { // 遍历buf,确认读取结束 int buf_idx, read_len; char buf[512]; char exe_argv[MAXARG]; // 跳过存储“xargs”的argv[0] for (int i = 1; i < argc; i++) { exe_argv[i-1] = argv[i]; } while (1) { buf_idx = -1; do { buf_idx++; // 读取并存储到buf中直到换行或到达结尾 read_len = read(0, &buf[buf_idx], sizeof(char)); } while (read_len > 0 && buf[buf_idx] != ‘\n’); // 读到结尾,跳出循环 if (read_len ==0 && buf_idx == 0) { break; } buf[buf_idx] = ‘\0’; exe_argv[argc - 1] = buf;
if (fork()==0) {
exec(exe_argv[0], exe_argv);
exit(0);
}
else {
wait(0);
}
}
exit(0); } ```
