既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
xv6 kernel is booting
hart 1 starting
hart 2 starting
init: starting sh
$ QEMU: Terminated //退出成功
sleep函数实现
流程:
- 在user/目录下,创建一个sleep.c文件;
- 然后调用系统函数sleep和输入参数来实现休眠;
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
//命令格式: sleep time
int main(int argc, char *argv[]){
//判断参数数目,sleep、time两个
if(argc != 2){
fprintf(2,"Usage:%s <num> \n", argv[0]);
exit(1);
}
//将第二个参数time 转换为整形,调用sleep函数
int ticks = atoi(argv[1]);
int ret = sleep(ticks);
exit(ret);
}
- 在Makefile文件里面UPROGS 添加 $U/_sleep\;
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
...
$U/_sleep\ //添加进Makefile
- 直接重新编译make qemu,或者用测试脚本测试,我这里就放一下用脚本测试的方法和结果;
jimmy@ubuntu:~/xv6-labs-2020$ ./grade-lab-util sleep
make: 'kernel/kernel' is up to date.
== Test sleep, no arguments == sleep, no arguments: OK (0.8s)
== Test sleep, returns == sleep, returns: OK (1.0s)
== Test sleep, makes syscall == sleep, makes syscall: OK (1.1s)
pingpong函数
1.让父进程给子进程传一个byte,然后子进程收到,就打印一个received ping
2.子进程再给父进程传一个byte,然后父进程收到,就打印一个received pong
这个实验主要是熟悉fork()、pipe()、read()、write()、getpid() 等函数的使用方法
流程:
- 在user/目录下,创建一个pingpong.c文件;
- 编写代码
#include "kernel/types.h"
#include "user/user.h"
//管道需要一个数组,来存放写入端(第二个元素)和读取端(第一个元素)
int main()
{
//自定义一个父子进程间发送的byte
char buf[] = {'a'};
//定义两个管道数组
int p1[2];
int p2[2];
int pid;
//创建管道
pipe(p1); //父进程发,子进程读
pipe(p2); //子进程发,父进程读
//注意这里的顺序,一定要先创建好管道在创建子进程
//因为子进程要copy父进程的所有内容,如果后创建管道会出现问题
int ret = fork();
if(ret == 0){ //子进程
//获取当前的pid(用来确认打印出来是子进程的pid)
pid = getpid();
//关闭p1的写入端、p2的读取端(这两个不需要用到,最好关闭)
close(p1[1]);
close(p2[0]);
//如果从p1管道读到了内容,长度为1,就说明收到了父进程的byte
if(read(p1[0],buf,1) == 1){
printf("%d: received ping\n", pid);
}
//向p2管道写入一个byte
write(p2[1], buf, 1);
exit(0);
}else{
pid = getpid();
//同上原因
close(p1[0]);
close(p2[1]);
//向管道p1写入一个byte
write(p1[1],buf,1);
//如果读到了p2管道的byte,说明父进程收到了子进程发送的byte
if(read(p2[0],buf,1) == 1) {
printf("%d: received pong\n", pid);
}
exit(0);
}
}
}
- 在Makefile文件里面UPROGS 添加 $U/_pingpong\;
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
...
$U/_sleep\
$U/_pingpong\ //添加进Makefile
- 直接重新编译make qemu,或者用测试脚本测试,我这里就放一下用脚本测试的方法和结果;
jimmy@ubuntu:~/xv6-labs-2020$ ./grade-lab-util pingpong
make: 'kernel/kernel' is up to date.
== Test pingpong == pingpong: OK (1.4s)
primes函数实现
1.写一个素数筛选的程序,需要用到多进程和管道,这道题理解主要靠下面的图。
大概流程就是,输入2-11,然后发现2是素数,然后将能被2整除的素数全部筛掉。然后发现3是素数,在第二个阶段中将能被3整除的筛掉。
(牢记:每个进程的第一个数必定是素数)
2.根据上面的描述,需要写一个递归函数,这个函数要做的就是让父进程判断当前所有的数字中有没有能被第一个数整除的,如果不能整除,就用子进程把它送到下一次递归。然后利用这种链式结构,就像上面的图一样,完成筛选。
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
void* child(int* p)
{
// 关闭上一个进程的写入端
close(p[1]);
int num;
//如果管道为空,说明已经筛选结束,直接关闭读取端,退出即可
if (read(p[0], &num, sizeof(num)) == 0)
{
close(p[0]);
exit(0);
}
//因为筛选规则,管道里面的第一个数一定是质数
printf("prime %d\n", num);
//创建一个管道用来写入这一轮被筛选的数据
int cp[2];
pipe(cp);
//将数据写入子进程中
if (fork() == 0) /
{
//一直递推,形成一种链式结构,让所有不能被当前质数整除的数据(在cp中)传递到下一个进程
child(cp);
}else { //处理从上一个进程收进来的管道数据
close(cp[0]);
int nnum;
//管道数据不会因为读而减少,因此子进程可以循环读,
//将所有不能被当前质数整除的数据传递到孙子进程的管道cp
while(read(p[0], &nnum, sizeof(nnum)))
// process 1 write an number, then process 2 read from the pipe
{
//不能被整除,就放到cp管道
if (nnum % num != 0)
{
write(cp[1], &nnum, sizeof(nnum));
}
}
//关闭cp的写入端
close(cp[1]);
wait(0);
}
exit(0);
}
int main(int argc, char const *argv[])
{
int p[2];
pipe(p);
//父进程初始化管道数据,然后用子进程来处理,并以此形成一种链式结构
if (fork() == 0) // child process
{
child(p);
}
else // parent process
{
close(p[0]);
for (int i = 2; i <= 35; i++)
{
write(p[1], &i, sizeof(i));
}
close(p[1]);
wait(0);
}
exit(0);
}
- 在Makefile文件里面UPROGS 添加 $U/_primes\;
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
...
$U/_sleep\
$U/_pingpong\
$U/_primes\ //添加进Makefile
- 直接重新编译make qemu,或者用测试脚本测试,我这里就放一下用脚本测试的方法和结果;
jimmy@ubuntu:~/xv6-labs-2020$ ./grade-lab-util primes
make: 'kernel/kernel' is up to date.
== Test primes == primes: OK (1.0s)
find函数
1.这个函数主要是用来找文件的路径,这个和ls命令有很多类似的地方,比如要读取目录树,确定当前是目录还是文件等等。因此,参考ls函数的源码来修改即可.
注意:要求不要对’.‘或者’…'进行递归,而且需要使用strcmp()函数来比较两个字符串。
2.首先写一个函数basename,这个函数用来返回一个完整路径下的文件名。(用于这个路径下的文件是不是target文件)
例如:“/home/user/documents/file.txt” -> file.txt
char *basename(char *pathname) {
char *prev = 0;
//分割出以第一个'/'为结尾的字符串
//cur+1就索引到了'/'之后的第一个字符
char *curr = strchr(pathname, '/');
//循环找,直到找到最后的文件名然后返回
while (curr != 0) {
prev = curr;
curr = strchr(curr + 1, '/');
}
return prev;
}
3.接下来写一个find函数,这个函数用于递归查找所有目录里,包含目标字符串的文件,并且打印出来,这个函数就是在ls函数的基础上修改的。
void find(char * curr_path, char * target)
{
char buf[512], *p;
int fd;
struct dirent de;
struct stat st;
//当前路径下已经搜索完了或者文件不存在,就返回
if((fd = open(curr_path, 0)) < 0){
fprintf(2, "find: cannot open %s\n", curr_path);
return;
}
if(fstat(fd, &st) < 0){
fprintf(2, "find: cannot stat %s\n", curr_path);
close(fd);
return;
}
//判断当前类型
switch(st.type){
//如果是文件,说明搜索到底了
case T_FILE:;
char *file_name = basename(curr_path); //找到文件名
int match = 1;
//如果不是要找的文件名或者为空
if(file_name == 0 || strcmp(file_name+1, target) != 0){
match = 0;
}
//匹配成功,就把当前路径答应出来
if(match){
printf("%s\n",curr_path);
}
close(fd);
break;
//如果是一个目录,说明还要接着递归搜索
case T_DIR:
if(strlen(curr_path) + 1 + DIRSIZ + 1 > sizeof buf){
printf("find: path too long\n");
break;
}
strcpy(buf, curr_path);
p = buf+strlen(buf);
*p++ = '/';
while(read(fd, &de, sizeof(de)) == sizeof(de)){
if(de.inum == 0)
continue;
memmove(p, de.name, DIRSIZ);
p[DIRSIZ] = 0;
if(stat(buf, &st) < 0){
printf("find: cannot stat %s\n", buf);
continue;
![img](https://img-blog.csdnimg.cn/img_convert/09091fe0dc3913f37f2d6f975a41b992.png)
![img](https://img-blog.csdnimg.cn/img_convert/fa299f533a2be57ed52e9f5e98bc0e99.png)
![img](https://img-blog.csdnimg.cn/img_convert/10b991af1accf971d11ba11932c37e06.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
0){
printf("find: cannot stat %s\n", buf);
continue;
[外链图片转存中...(img-IzOsMDsG-1715632821384)]
[外链图片转存中...(img-99fR6lXs-1715632821384)]
[外链图片转存中...(img-E38o8pUD-1715632821384)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**