sleep
argc表示命令行参数个数,sleep应该为2个参数,第一个参数为路径(大概是这样),argv为指向参数的指针数组,atoi为系统提供的将字符串转为整数的函数,最后用exit退出。
#include "/kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[])
{
if(argc != 2){
fprintf(2,"you must input sleep time");
exit(0);
}
sleep(atoi(argv[1]));
exit(0);
}pingpong
学习使用pipe管道,pipe函数接受一个数组指针,将其初始化为一对文件标识符,默认数组第一位是读标识符,第二位是写标识符,当用fork创建子进程时,会复制父进程一模一样的标识符,指向同一位置共享偏移,所以根据需要使用close关闭相应的标识符
学习使用read和write系统函数进行读写,第一个参数为文件标识符,第二个参数为读写位置,第三个参数为字节数
#include "kernel/types.h"
#include "user/user.h"
int main(int argc, char *argv[])
{
int p0[2], p1[2];
char buf[8];
pipe(p0[2]);
pipe(p1[2]);
if(fork()==0)
{
close(p0[1]);
close(p1[0]);
if(read(p0[1], buf, 8)!=8)
{
printf("read error");
exit(0);
}
printf("%d: received ping\n", getpid());
if(write(p1[0], buf, 8)!=8)
{
printf("write error");
exit(0);
}
exit(0);
}
else
if(read(p1[0], buf, 8)!=8)
{
printf("read error");
exit(0);
}
printf("%d: receive pong\n", getpid());
wait(0);
exit(0);
}primes
利用管道筛素数,首先输入2到35,每次输入的第一个数一定是素数,其余的数如果是这个数的倍数就筛掉,然后再进入下一个进程继续筛,最后输出所有素数
学习迭代的思想,建立一个迭代函数进行执行筛的命令
当写通道关闭时,read会返回0,利用这个进行读取管道内所有数
#include "kernel/types.h"
#include "user/user.h"
void process(int p[])
{
close(p[1]);
int prime;
if(read(p[0], &prime, 4)>0)
{
printf("prime %d\n", prime);
int pp[2];
pipe(pp);
if(fork()==0)
{
process(pp);
}
else
{
close(pp[0]);
int i;
while(read(p[0], &i, 4)>0)
{
if(i%prime!=0)
write(pp[1], &i, 4);
}
close(pp[1]);
wait(0);
}
}
}
int main(int argc, char *argv[])
{
int p[2];
pipe(p);
if(fork()==0)
{
process(p);
}
else
{
close(p[0]);
for(int i=2; i<36; ++i)
{
write(p[1], &i, 4);
}
close(p[1]);
wait(0);
}
exit(0);
}findargv保存命令行参数,第一个为argv[0]保存调用命令名,后面的一般为用户提供的参数
当从路径的标识符中读取字符时,读取到的是目录下的文件信息,这也是为什么ls可以显示文件信息的原因,实际上只是做了读取的工作
一般目录内容为., .., 文件名
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
char* filename(char *path)
{
char *p;
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)
{
printf("find: cannot open %s\n", path);
return;//调用open打开path的输出口,打不开函数返回
}
if(fstat(fd, &st) < 0)
{
printf("find: cannot stat %s\n", path);
close(fd);
return;//调用fstat把文件信息放进st,失败就返回
}
switch(st.type)
{
case T_FILE://是文件
if(strcmp(filename(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;
}
strcpy(buf, path);//buf==path
p = buf+strlen(buf);//p位于buf结尾
*p++ = '/';//buf最后面添加/
while(read(fd, &de, sizeof(de)) == sizeof(de))//读path目录下的文件
{
if(de.inum == 0)
{
continue;
}
if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)//跳过子目录的.和..
{
continue;
}
memmove(p, de.name, DIRSIZ);//读到真正的文件就加在p后面,也就是buf末尾
p[DIRSIZ] = 0;//在字符串最后加0表示结束
find(buf, target);
}
break;
}
close(fd);
}
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf("error");
exit(0);
}
find(argv[1], argv[2]);
exit(0);
}
京公网安备 11010502036488号