MIT6.s081 lab utilities
lab utilities
1、sleep
//
// Created by silly on 23-9-5.
//
#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 <number>\n");
exit(1);
}
int number = atoi(argv[1]);
sleep(number);
exit(0);
}
2、pingpong
//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../user/user.h"
int main() {
int fd1[2], fd2[2];
pipe(fd1);
pipe(fd2);
char buf[1] = {'p'};
int pid = fork();
if (pid == 0) {
int child_pid = getpid();
close(fd1[1]);
close(fd2[0]);
read(fd1[0], buf, 1);//read会阻塞在收到byte之前
printf("%d: received ping\n", child_pid);
write(fd2[1], buf, 1);
exit(0);
} else {
int parent_pid = getpid();
close(fd1[0]);
close(fd2[1]);
write(fd1[1], buf, 1);
read(fd2[0], buf, 1);
printf("%d: received pong\n", parent_pid);
exit(0);
}
}
一条pipe只能进行单向的数据传输,且在传输时应关闭掉无用的剩下两个端口
3.primes
As another example, which Hoare credits to Doug McIlroy, consider the generation of all primes less than a thousand. The sieve of Eratosthenes can be simulated by a pipeline of processes executing the following pseudocode:
p = get a number from left neighbor
print p
loop:
n = get a number from left neighbor
if (p does not divide n)
send n to right neighbor
A generating process can feed the numbers 2, 3, 4, ..., 1000 into the left end of the pipeline: the first process in the line eliminates the multiples of 2, the second eliminates the multiples of 3, the third eliminates the multiples of 5, and so on:
//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../user/user.h"
void primes(int readfd) {
int now_num = 0;
int my_num = 0;
int fork_num = 0;
int pipes[2];
while (1) {
int read_num = read(readfd, &now_num, 4);
// 1.first receive left number
if (!my_num) {
my_num = now_num;
printf("prime %d\n", my_num);
}
// 2.left number is prime
if (now_num % my_num != 0) {
if (!fork_num) {
pipe(pipes);
fork_num = 1;
if (fork() == 0) {
close(pipes[1]);
primes(pipes[0]);
exit(0);
}
close(pipes[0]);
}
//为什么要写到if(!fork_num)外面
//因为只要不是能整除my_num的数,都要往后传
write(pipes[1], &now_num, 4);
}
// 3.left has not number
if (read_num == 0) {
close(readfd);
if (fork_num) {
close(pipes[1]);
int child_status;
wait(&child_status);
}
// 运行到此处说明是最后一个线程,它的fork_num = 0;
exit(0);
}
}
}
int main() {
int pipes[2];
pipe(pipes);
for (int n = 2; n <= 35; n++) {
write(pipes[1], &n, 4);
}
close(pipes[1]);
primes(pipes[0]);
exit(0);
}
4.find
//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "kernel/fcntl.h"
#include "../kernel/stat.h"
#include "../user/user.h"
#include "../kernel/fs.h"
/*
* fmtname:将path(绝对路径)中最后的文件名获取出来
* eg:fmtname("./a/b") = "b";
*/
char* fmtname(char *path)
{
char *p;
// Find first character after last slash.
for(p=path+strlen(path); p >= path && *p != '/'; p--)
;
p++;
return p;
}
void finds(char *path, char *target) {
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, O_RDONLY)) < 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(target, fmtname(path)) == 0) {
printf("%s\n", path);
}
break;
case T_DIR:
memset(buf, 0, sizeof(buf));
int path_len = strlen(path);
memcpy(buf, path, path_len);
buf[path_len] = '/';
p = buf + path_len + 1;
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
if (de.inum == 0 || strcmp(de.name, ".") == 0 ||
strcmp(de.name, "..") == 0)
continue;
memcpy(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
finds(buf, target);
}
break;
}
close(fd);
}
int main(int argc, char *argv[]) {
finds(argv[1], argv[2]);
exit(0);
}
5、xargs
# $ echo hello too | xargs echo bye
管道 | 是xv6已经设置好的,我们通过main函数读取的argv列表内容只是{{echo}, {bye}},而{{hello}, {too}}参数是通过读取标准输入获得,因为管道的作用就是把echo hello too的输出通过管道发给了xargs
//
// Created by silly on 23-9-6.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../kernel/param.h"
#include "../user/user.h"
int main(int args, char *argv[]) {
char buf[64] = {0};//通过buf到标准输入读取需要加上的额外参数
char *new_argv[MAXARG] = {0};
for (int i = 1; i < args; i++) {
new_argv[i - 1] = argv[i];
}
while (1) {
int i = 0;
while (read(0, buf + i, 1) > 0) {
if (buf[i] == '\n') break;
i++;
}
if (i == 0) break;//read no data
buf[i] = 0;
new_argv[args - 1] = buf;
if (fork() == 0) {
exec(new_argv[0], new_argv);
exit(0);
} else {
wait(0);
}
}
exit(0);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通