1、sleep
实现sleep函数,读取参数并调用sleep系统调用。
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char* argv[])
{
int time;
if(argc < 2){
fprintf(2, "Usage: <sleep time>");
exit(1);
}
time = atoi(argv[1]);
if(time <= 0){
fprintf(2, "Sleep: invalid sleep time");
exit(1);
}
sleep(time);
exit(0);
}
2、pingpong
管道的应用,使用管道在父子进程之间通信,像打乒乓球一样。注意关闭用不到的文件描述符。
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char* argv[])
{
int child_to_parent[2], parent_to_child[2];
char* child_buf = 0, *parent_buf = 0;
char byte = 'a';
pipe(child_to_parent);
pipe(parent_to_child);
int pid = fork();
if(pid == -1){
fprintf(2, "fork() failed");
exit(1);
}
if(pid == 0){
close(child_to_parent[0]);
close(parent_to_child[1]);
read(parent_to_child[0], child_buf, 1);
fprintf(1, "<%d>: received ping\n", getpid());
write(child_to_parent[1], child_buf, 1);
close(child_to_parent[1]);
close(parent_to_child[0]);
}
else{
close(child_to_parent[1]);
close(parent_to_child[0]);
write(parent_to_child[1], &byte, 1);
read(child_to_parent[0], parent_buf, 1);
fprintf(1, "<%d>: received pong\n", getpid());
close(child_to_parent[0]);
close(parent_to_child[1]);
wait(0);
}
exit(0);
}
3、primes
使用管道实现一个质数筛子,筛选出1-35中所有的质数。
#include "kernel/types.h"
#include "user/user.h"
// 子进程调用函数
void process(int left_to_right[])
{
int prime, curNum;
int new_left_to_right[2];
pipe(new_left_to_right);
// 留在left_to_right中的都是质数,此质数作为本进程的被除数
if(read(left_to_right[0], &prime, sizeof(int)) <= 0)
return;
fprintf(1, "prime %d\n", prime);
// 子进程作为右邻居,关闭写管道文件描述符
if(fork() == 0){
close(new_left_to_right[1]);
process(new_left_to_right);
close(new_left_to_right[0]);
}
else{
close(new_left_to_right[0]);
// 筛选,能被prime整除的淘汰,否则输入到右邻居进行处理
while(read(left_to_right[0], &curNum, sizeof(int)) > 0){
if(curNum % prime != 0){
write(new_left_to_right[1], &curNum, sizeof(int));
}
}
close(new_left_to_right[1]);
wait(0);
}
close(left_to_right[0]);
close(left_to_right[1]);
}
int main(int argc, char* argv[])
{
int left_to_right[2], i;
pipe(left_to_right);
if(fork() == 0){
close(left_to_right[1]);
process(left_to_right);
close(left_to_right[0]);
}
else{
close(left_to_right[0]);
// 读入数据,2就是质数,因此不需要处理
for(i = 2; i <= 35; ++i){
write(left_to_right[1], &i, sizeof(int));
}
close(left_to_right[1]);
wait(0);
}
exit(0);
}
4、find
参考ls,命令行参数分别为查找路径和待查找关键字。
#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 *filename)
{
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(fmtname(path), filename) == 0){
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;
if(strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("ls: cannot stat %s\n", buf);
continue;
}
find(buf, filename);
}
break;
}
close(fd);
}
int
main(int argc, char *argv[])
{
if(argc < 3){
fprintf(2, "Usage: find <path> <filename>\n");
exit(0);
}
find(argv[1], argv[2]);
exit(0);
}
5、xargs
编写一个简单版本的 UNIX xargs 程序:从标准输入读取行并为每一行运行一个命令,将该行作为参数提供给命令。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"
int main(int argc, char* argv[])
{
int len = 0, idx = 0;
char* exec_argv[MAXARG], buf[512];
for(int i = 1; i < argc; ++i)
exec_argv[i - 1] = argv[i];
while(1){
idx = 0;
// 读取单行输入,一次读取一个字符,直到出现换行符 ('\n')。
while((len = read(0, buf + idx, sizeof(char))) > 0){
// 替换'\n'为'\0'
if(buf[idx] == '\n'){
buf[idx] = '\0';
break;
}
++idx;
}
// 没有命令需要读取了,退出循环
if(len == 0 && idx == 0)
break;
exec_argv[argc - 1] = buf;
// 使用fork和exec对每一行输入调用命令
if(fork() == 0){
exec(exec_argv[0], exec_argv);
exit(0);
}
// 在父级中使用wait等待子级完成命令
else{
wait(0);
}
}
exit(0);
}