实现sleep
输入数字,使系统睡眠ms
代码实现
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int main(int argc, char *argv[]){
if(argc < 2){
fprintf(2, "argument 1 must sleep\n");
exit(1);
}
for(int i = 1; i < argc; i++){
int t = atoi(argv[i]);
printf("sleeping\n");
sleep(t);
printf("not sleep\n");
}
exit(0);
}
实现pingpong
写一个程序,实现字符串在两个进程间来回传递1次
实现思路
代码实现
#include "kernel/types.h"
#include "user/user.h"
int main(){
// p1 写端父进程,读端子进程
// p2 写段子进程,读端父进程
int p1[2], p2[2];
// 传输的字符
char buf[] = {"zhaoxinhao\n"};
// 传输字符的长度
int len_buf = sizeof(buf);
// 创建管道
pipe(p1);
pipe(p2);
// 创建子进程
int pid = fork();
if(pid < 0){
printf("fork error");
exit(1);
}
else if(pid == 0){ // 子进程
// p1的读端 p2的写端
// 关闭 p1的写端 p2的读端
close(p1[1]);
close(p2[0]);
printf("This is child\n");
int child_read_n = read(p1[0], buf, len_buf);
if(child_read_n == 0){
printf("child read error");
exit(1);
}
write(1, buf, len_buf); // 向标准输出 打印读到的数据
printf("%d: received ping\n", getpid());
if((write(p2[1], buf, len_buf)) != len_buf){
printf("child write error");
exit(1);
}
exit(0);
}
else{ // 父进程
// p2的读端 p1的写端
// 关闭 p2的写端 p1的读端
close(p1[0]);
close(p2[1]);
printf("This is parent\n");
if(write(p1[1], buf, len_buf) != len_buf){
printf("parent write error");
exit(1);
}
if(read(p2[0], buf, len_buf) == 0){
printf("parent read error");
exit(1);
}
write(1, buf, len_buf);
printf("%d: received pong\n", getpid());
exit(0);
}
}o
实现primes(素数)
打印2~35之间的素数,利用管道
实现思路
- 找素数:对每个素数,乘以k倍所得到的数都不是素数——哈希去掉不是素数的数
- 管道实现:
- 主进程将素数写入,子进程读出
- 子进程递归继续找下一个素数
- 重复1和2
write
和read
使用的都是地址,传入4个字节的地址,正好int
代码实现
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void func(int *input, int cnt){
if(cnt >= 36) return;
int p[2];
pipe(p);
int i = cnt;
for(; i < 36; i++){
if(input[i] == 1) continue;
int k = 1;
while(k * i < 36 ){
input[k++ * i] = 1;
}
break;
}
if(i >= 36) return;
int pid = fork();
if(pid < 0){
printf("fork error\n");
exit(1);
}
else if(pid == 0){
int buf;
close(p[1]); // 关闭写端
// close(0);
// dup(p[0]);
if(read(p[0], &buf, 4) <= 0){
printf("read error\n");
exit(1);
}
printf("primes: %d\n", buf);
close(p[0]);
func(input, i);
exit(0);
}
else{
close(p[0]);
if(write(p[1], &i, 4) <= 0){
printf("write error\n");
exit(1);
}
close(p[1]);
wait(0);
exit(0);
}
}
int main(){
int p[36] = {0};
func(p, 2);
exit(0);
}
实现find
实现find功能,查找当前目录下,所有的复合名字的文件名
实现思路
- 参考ls
- 利用
kernel/stat.h
下的stat
结构体,获取当前目录下所有文件和文件夹的类型 - 利用
kernel/fs.h
下的dirent
结构体,获取当前文件或文件夹的名字和inode
号 - 利用递归遍历文件夹下的所有文件
代码实现
#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fs.h"
#include "user/user.h"
char* fmt_name(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++;
memmove(buf, p, strlen(p)+1);
return buf;
}
void campare(char *fileName, char *findName){
char *file_name = fmt_name(fileName);
// printf("%s\n", file_name);
if(strcmp(file_name, findName) == 0){
printf("find: %s\n", fileName);
}
}
void find(char *path, char *file_name){
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
if((fd = open(path, 0)) < 0){
printf("open %s failure\n", path);
return;
}
// st:传出参数,获取文件描述符的状态
if(fstat(fd, &st) < 0){
printf("stat %s failure\n", path);
}
switch (st.type)
{
case T_FILE:
campare(path, file_name);
break;
case T_DIR:
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof(buf)){
printf("path too long");
break;
}
strcpy(buf, path);
p = buf + strlen(buf);
*p++ = '/';
// 读取当前目录下所有文件和文件夹
while(read(fd, &de, sizeof(de)) == sizeof(de)){
// printf("de.name:%s, de.inum:%d\n", de.name, de.inum);
if(de.inum == 0 || de.inum == 1 || strcmp(de.name, ".") == 0 ||
strcmp(de.name, "..") == 0)
continue;
memmove(p, de.name, strlen(de.name));
p[strlen(de.name)] = 0;
find(buf, file_name);
}
break;
default:
break;
}
close(fd);
}
int main(int argc, char *argv[]){
if(argc < 3){
printf("find errorL: find [path] [fileName]");
exit(1);
}
find(argv[1], argv[2]);
exit(0);
}
实现xargs
类似于:echo hello too | xargs echo bye => bye hello too
代码实现
#include "kernel/types.h"
#include "user/user.h"
#include "kernel/param.h"
int main(int argc, char* argv[])
{
char buf[32];
int n;
// 没有参数读到什么输出什么(没有必要)
if (argc < 2) {
while((n = read(0, buf, sizeof buf)) > 0) {
write(1, buf, n);
}
exit(0);
}
char* args[32];
int numArg;
for (int i = 1; i < argc; ++i) {
args[i-1] = argv[i];
}
numArg = argc - 1;
char* p = buf;
// 读取管道xargs 之前的命令
while ((n = read(0, p, 1)) > 0) {
if (*p == '\n') {
*p = 0;
if (fork() == 0) {
args[numArg] = buf;
exec(args[0], args);
exit(0);
} else {
wait(0);
}
p = buf;
} else {
++p;
}
}
exit(0);
}
= ‘\n’) {
*p = 0;
if (fork() == 0) {
args[numArg] = buf;
exec(args[0], args);
exit(0);
} else {
wait(0);
}
p = buf;
} else {
++p;
}
}
exit(0);
}