MIT6.S081 ---- Lab Utilities
Lab Utilities
本章实验学习xv6的一些softerware tools的实现,学习系统调用。
学习进程、文件相关的系统调用使用。
sleep
使用sleep系统调用,暂停指定的ticks(一个tick代表两次时钟中断的时间间隔)。
使用exit系统调用终止当前进程。
#include "kernel/types.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
if(argc <= 1){
fprintf(2, "usage: sleep clock ticks\n");
exit(1);
}
sleep(atoi(argv[1]));
exit(0);
}
pingpong
使用read和write系统调用利用管道进行进程间通信。
使用close系统调用关闭不用的管道端。
管道read是阻塞式的,除非对端有数据写入,或者所有指向对端的文件描述符被close掉然后read返回0。
#include "kernel/types.h"
#include "user/user.h"
int
main(int argc, char *argv[])
{
int pipe1[2], pipe2[2];
char buf[1];
if(pipe(pipe1) < 0 || pipe(pipe2) < 0){
fprintf(2, "pingpong: pipe failed\n");
exit(1);
}
if(fork() == 0){
close(pipe1[1]);
close(pipe2[0]);
read(pipe1[0], buf, 1);
printf("%d: received ping\n", getpid());
write(pipe2[1], "1", 1);
} else {
close(pipe1[0]);
close(pipe2[1]);
write(pipe1[1], "1", 1);
read(pipe2[0], buf, 1);
printf("%d: received pong\n", getpid());
}
exit(0);
}
primes
参考素数筛在论文中的实现。
地址的理解:write时,将i的地址传入,长度设为4,则write写入的是从i所在地址的长度为4字节的字符串,本质是将i的值以字符串形式传出。
在pipeline中,可以借鉴xv6的shell设计的思路(Chapter1 1.3),做I/O重定向,这样做的好处是将main和pipeline做了解耦,不需要将管道作为参数传递并且处理,直接使用fd=0的描述符进行读取。
使用dup系统调用和wait系统调用。
及时close不用的管道端口,否则程序会有问题(我这里是不停的打印0,很难调试出原因,应该是内存有限)。
#include "kernel/types.h"
#include "user/user.h"
void
pipeline()
{
int p[2];
int prime;
if (read(0, &prime, 4) == 0) {
exit(0);
}
printf("prime %d\n", prime);
pipe(p);
if (fork() == 0) {
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
pipeline();
} else {
close(p[0]);
int number;
while (read(0, &number, 4) == 4) {
if (number % prime != 0) {
write(p[1], &number, 4);
}
}
close(p[1]);
wait((int*)0);
}
exit(0);
}
int
main(int argc, char *argv[])
{
int p[2];
pipe(p);
if (fork() == 0) {
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
pipeline();
} else {
close(p[0]);
for (int i = 2; i <= 35; i++) {
write(p[1], &i, 4);
}
close(p[1]);
wait((int *)0);
}
exit(0);
}
find
目录本质上是一个文件,type是T_DIR,该文件对应的数据是一系列目录项,每个目录项dirent由名称和inode索引组成。
找该给定目录下的所有目录项,除了当前目录和上级目录,如果目录项是目录,递归查找(给定目录找文件);如果目录项是文件,对比文件名称,相同则输出。
inode number为0的目录项不可用(Chapter 8.11)。
使用fstat系统调用,熟悉dirent和stat结构体。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
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
find(char path[], char file[])
{
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;
}
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", path);
close(fd);
return;
}
switch(st.type)
{
case T_FILE:
if (strcmp(fmtname(path), file) == 0)
printf("%s\n", path);
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
fprintf(2, "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, file);
}
break;
}
close(fd);
}
int
main(int argc, char *argv[])
{
if(argc < 3){
fprintf(2, "Usage: find path file\n");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
xargs
从标准输入读取行,并每行运行一次命令。
之所以从标准输入读,是因为shell实现了pipelines,通过创建管道链接pipelines左端和右端。来自左端的结果,输出至fd=1,这里管道的写端重定向到fd=1。右端的读端重定向到fd=0。
所以左端的结果需要成为右端的参数。
使用exec系统调用,失败才回到xargs的main。
#include "kernel/types.h"
#include "user/user.h"
#include "kernel/param.h"
int
main(int argc, char *argv[])
{
char *arguments[MAXARG], buf[512];
if(argc < 2) {
fprintf(2, "Usage: xargs command\n");
exit(1);
}
if (argc + 1 > MAXARG) {
fprintf(2, "xargs: argument too much\n");
exit(1);
}
for (int i = 1; i < argc; i++)
arguments[i-1] = argv[i];
char *p = buf;
while (read(0, p, 1) == 1) {
if (*p == '\n') {
*p = '\0';
arguments[argc-1] = buf;
if (fork() == 0) {
exec(argv[1], arguments);
fprintf(2, "exec %s failed\n", argv[1]);
exit(0);
} else {
wait((int*)0);
}
p = buf;
} else {
p++;
}
}
exit(0);
}
Code
作者:seaupnice
出处:https://www.cnblogs.com/seaupnice/p/15775089.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!