当前位置: 首页 > news >正文

网站开发建设中unity做网站

网站开发建设中,unity做网站,沈阳建设网站费用,网站做备案需要多久2023MIT6.828 lab-1 官方地址 一、sleep 实验内容 调用sleep#xff08;系统调用#xff09;编写用户级别程序能暂停特定时常的系统滴答程序保存在user/sleep.c 实验过程 xv6的参数传递 查看官方文档提示的文件中#xff0c;多采用如下定义#xff1a; int main(in…2023MIT6.828 lab-1 官方地址 一、sleep 实验内容 调用sleep系统调用编写用户级别程序能暂停特定时常的系统滴答程序保存在user/sleep.c 实验过程 xv6的参数传递 查看官方文档提示的文件中多采用如下定义 int main(int argc, char *argv[])在xv6操作系统中 1、argc 是一个常见的参数用于表示传递给程序的命令行参数的数量。 2、argvargument vector是一个指向字符指针数组的指针该数组中的每个元素都是一个指向命令行参数的字符串的指针。 3、程序的内部可通过argc和argv来访问外界输入的参数 注意 1、argc指示出程序执行时传入的参数个数常可用来判断输入是否符合要求 2、argv[]为存放字符指针的数组我们需要的是其指向地址存放的数据若要当整型数据使用还需进行相应转换实现代码 #include kernel/types.h //调用相应的头文件 #include kernel/stat.h #include user/user.h int main( int argc ,char *argv[]) //通过argc和argv传入参数 {if(argc!2) //传入参数数量不符合{fprintf(2,usage:sleep time\n);exit(1);} sleep(atoi(argv[1])); //由于argc[]指向字符型数据调用atoi()进行转换 fprintf(2,nothing happens for a little while\n); exit(0); //退出程序 }编译准备 在make qemu之前还需进行将编写的sleep()程序加入编译文件中 1、进入lab目录下 vi Makefile //打开文件 : ?UPROGS //vim下搜索关键词2、定位到UPROGS在最后一处按格式补入sleep(): UPROGS\$U/_cat\$U/_echo\$U/_forktest\$U/_grep\$U/_init\$U/_kill\$U/_ln\$U/_ls\$U/_mkdir\$U/_rm\$U/_sh\$U/_stressfs\$U/_usertests\$U/_grind\$U/_wc\$U/_zombie\$U/_sleep\3、保存退出编译运行 make qemuxv6 kernel is booting hart 1 starting hart 2 starting init: starting sh $ sleep 10 nothing happens for a little while //停顿后显示达到实验效果工具测试 在lab目录下执行 $ ./grade-lab-util sleep 或 $ make GRADEFLAGSsleep grade输出 测试通过 二、pingpong 实验内容 在父进程中创建子进程编写用户级程序调用系统调用通过一对pipes在两个进程间实现’‘ping-pong’’ 一个字节父进程给子进程发送一字节子进程收到后print pid: received ping 这里的pid is its process ID并通过pipes给父进程传递一字节然后exit父进程读取来自子进程的字节并print pid: received pong然后exit程序保存在user/pingpong.c 实验过程 fork用法 打开/kernel/proc.c查看fork()源码 // Create a new process, copying the parent. // Sets up child kernel stack to return as if from fork() system call. int fork(void) {int i, pid;struct proc *np;struct proc *p myproc();// Allocate process.if((np allocproc()) 0){return -1;}// Copy user memory from parent to child.if(uvmcopy(p-pagetable, np-pagetable, p-sz) 0){freeproc(np);release(np-lock);return -1;}np-sz p-sz;// copy saved user registers.*(np-trapframe) *(p-trapframe);// Cause fork to return 0 in the child.np-trapframe-a0 0;// increment reference counts on open file descriptors.for(i 0; i NOFILE; i)if(p-ofile[i])np-ofile[i] filedup(p-ofile[i]);np-cwd idup(p-cwd);safestrcpy(np-name, p-name, sizeof(p-name));pid np-pid;release(np-lock);acquire(wait_lock);np-parent p;release(wait_lock);acquire(np-lock);np-state RUNNABLE;release(np-lock);return pid; }该函数的作用 1、创建一个新进程并复制父进程的内容 2、为子进程child process设置内核栈kernel stack以便在子进程执行完毕后其行为表现得就像是从 fork() 系统调用返回一样 3、父子进程内容相同除个别数据但内存空间不同修改互不影响 4、在父进程中fork()返回新创建的子进程的进程ID在子进程中fork()返回0如果发生错误则返回-1 结构体proc的声明 该结构体存储了每一个进程的信息 // Per-process state struct proc {struct spinlock lock;// p-lock must be held when using these:enum procstate state; // Process statevoid *chan; // If non-zero, sleeping on chanint killed; // If non-zero, have been killedint xstate; // Exit status to be returned to parents waitint pid; // Process ID// wait_lock must be held when using this:struct proc *parent; // Parent process// these are private to the process, so p-lock need not be held.uint64 kstack; // Virtual address of kernel stackuint64 sz; // Size of process memory (bytes)pagetable_t pagetable; // User page tablestruct trapframe *trapframe; // data page for trampoline.Sstruct context context; // swtch() here to run processstruct file *ofile[NOFILE]; // Open filesstruct inode *cwd; // Current directorychar name[16]; // Process name (debugging) };pipes用法 pipe()函数定义 int pipe(int p[]) Create a pipe, put read/write file descriptors in p[0] and p[1]. 1、调用pipe函数来创建一个新的管道。如果成功pipe函数返回0并将两个文件描述符分别存放在p[0]和p[1]中。如果失败返回-1。 2、pipe为半双工通信要根据实际指定通信方向关闭管道的读或写保留另一功能 3、可采用两条pipe实现互通 getpid用法 获取当前进程PIDint getpid() Return the current process’s PID. 实现代码 注意读写顺序#include kernel/types.h #include user/user.hint main(int argc,int *argv[]) {int ptc_pipe[2];int ctp_pipe[2];pipe(ptc_pipe); //父to子pipe(ctp_pipe);//子to父int pid;pid fork(); //新建子进程if(pid0) //处于子进程{//设定管道通信方向close(ptc_pipe[1]); //子读取close(ctp_pipe[0]); //子写入char buff[16];if( read( ptc_pipe[0],buff,1) 1 ) //子进程收到父进程的一字节{printf(%d: received ping\n,getpid() );}write( ctp_pipe[1],p,1 ); //往父进程发送一字节exit(0);}else //处于父进程{//设置管道方向close( ptc_pipe[0] );// 父写入close( ctp_pipe[1] );// 父读取write( ptc_pipe[1],p,1 ); //往子进程发送一字节char buff[16];if( read( ctp_pipe[0],buff,1)1 )//父进程读取到一字节{printf(%d: received pong\n,getpid() );}} exit(0); }编译准备 往Makefile中UPROGS\项目添加 $U/_pingpong\运行结果 工具测试 make GRADEFLAGSpingpong grade测试通过 三、primes 实验内容 1、在xv6中使用pipe编写一个并发的素数筛选程序 2、使用pipe和fork来建立管道 3、第一个进程向管道内输入数字2到35 4、对于每个素数创建一个进程来从管道左侧读取并传输给另一条管道右侧 5、受限于xv6的有限文件描述符和进程第一个进程将在35处停止 6、程序位于user/primes.c 实验过程 过程分析 1、采用pipe进行数字传递用fork创建下一级直到结束 2、每级中挑选出一个素数把剩余经过此素数处理过的传递到下一级 3、传递后父进程要执行等待子进程结束的操作 实现代码 注意 1、仔细关闭程序不需要的文件描述符否则在35前xv6的资源会耗尽 2、pipe用完关闭避免拥塞 3、注意pipe和fork执行顺序 #include kernel/types.h #include user/user.hint children( int ptc_pipe[]) {//设置管道方向close( ptc_pipe[1] );//子读取不需要写入//对父到子管道进行检查int num;if( read( ptc_pipe[0] ,num,sizeof(num)) 0 ) //管道空{close( ptc_pipe[0]);exit(0);}else{printf(prime %d\n,num); //打印素数}//创建孙进程int pid;int ctg_pipe[2];pipe( ctg_pipe );//子进程到孙进程管道pidfork();if( pid0 ) //孙子进程{children( ctg_pipe ); //递推}else //子进程{//设置子到孙管道方向close( ctg_pipe[0] );//子写孙读int i;while( read( ptc_pipe[0],i,sizeof(i))0 ) //管道还有数据{if( i % num !0 )//有余数write( ctg_pipe[1],i,sizeof(i) );//发送到下一级}close( ctg_pipe[1]);//关闭写避免读拥塞wait(0); //等待孙进程结束}exit(0);//结束返回} int main(int argc,int *argv[]) {int ptc_pipe[2];//建立第一个管道pipe(ptc_pipe);int pid;pid fork(); //创建子进程if( pid0 ) //位于子进程{children(ptc_pipe); //函数反复调用}else //位于父进程{//管道设置close(ptc_pipe[0]); //父写入不需要读取for(int i2;i35;i) //往管道输入数字{write(ptc_pipe[1],i,sizeof(i));}close( ptc_pipe[1]);//关闭写避免读拥塞wait(0);//等待子进程} exit(0); }编译准备 往Makefile中UPROGS\项目添加 $U/_primes\运行结果 工具测试 make GRADEFLAGSprimes grade测试通过 四、find 实验内容 为Xv6编写一个简单版本的UNIX查找程序通过目录树的形式找到特定的名称程序保存在user/find.c 实验过程 线索提示 查看user/ls.c如何实现读目录使用递归操作时find能深入子目录使用make clean去获得干净的文件系统然后make qemu使用C语言的字符串使用strcmp()对比字符串而不是 ls.c源码 fmtname用于格式化文件名char* fmtname(char *path) {static char buf[DIRSIZ1];char *p;// Find first character after last slash.for(ppathstrlen(path); p path *p ! /; p--);p;// Return blank-padded name.if(strlen(p) DIRSIZ)return p;memmove(buf, p, strlen(p));memset(bufstrlen(p), , DIRSIZ-strlen(p));return buf; }ls为主要部分void ls(char *path) {char buf[512], *p;int fd;struct dirent de;struct stat st;if((fd open(path, O_RDONLY)) 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_DEVICE:case T_FILE:printf(%s %d %d %l\n, fmtname(path), st.type, st.ino, st.size);break;case T_DIR:if(strlen(path) 1 DIRSIZ 1 sizeof buf){printf(ls: path too long\n);break;}strcpy(buf, path);p bufstrlen(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(ls: cannot stat %s\n, buf);continue;}printf(%s %d %d %d\n, fmtname(buf), st.type, st.ino, st.size);}break;}close(fd); }int main(int argc, char *argv[]) {int i;if(argc 2){ls(.);exit(0);}for(i1; iargc; i)ls(argv[i]);exit(0); }ls函数中使用的结构体信息//用于表示一个目录项 struct dirent { ushort inum; // 本目录下该文件所在的inode号 char name[DIRSIZ]; // 该文件的文件名 };struct stat { short type; // 文件类型 int dev; // 设备号 uint ino; // inode编号 short nlink; // 链接数 uint size; // 文件大小字节 time_t atime; // 最后访问时间 time_t mtime; // 最后修改时间 time_t ctime; // 最后状态改变时间 int uid; // 用户ID int gid; // 组ID short rdev; // 特殊设备类型 uint flags; // 文件标志 uint pad[4]; // 填充字段确保结构大小对齐 };memmove函数void *memmove(void *dest, const void *src, size_t n); //dest指向目标内存区域的指针即要将数据移动到的位置。 //src指向源内存区域的指针即要从中复制数据的起始位置。 //n要复制的字节数。open函数int open(const char *path, int flags); //path要打开的文件或设备的路径名。 //flags指定打开文件的方式例如 O_RDONLY只读、O_WRONLY只写、O_RDWR读写等。 //返回值非负文件描述符 // 失败返回-1fstat函数int fstat(int fd, struct stat *buf); //fd文件描述符即之前通过 open 系统调用获得的用于标识文件的整数。 //buf一个指向 stat 结构体的指针该结构体用于存储获取到的文件状态信息。 //返回值0成功-1失败实现代码 实现思路 通过层层搜索遇到文件则判断输出遇到目录则延长到子目录采用递归搜寻在ls.c基础上修改 #include kernel/types.h #include kernel/stat.h #include user/user.h #include kernel/fs.h //#include kernel/fcntl.hchar* fmtname(char *path) {static char buf[DIRSIZ1];char *p;// Find first character after last slash.for(ppathstrlen(path); p path *p ! /; p--) //从后往前查找/;p; //1为/后第一个字符// Return blank-padded name.if(strlen(p) DIRSIZ)return p;memmove(buf, p, strlen(p)1); //注意结束符return buf; }void findname(char *path,char *findName) {char buf[512], *p; //buf用于存储绝对路径p用于指向buf操作int fd; //存储文件标识符struct dirent de; //表示目录项struct stat st; //存储文件信息//只读打开path路径if((fd open(path, 0)) 0)return; //打开错误if(fstat(fd, st) 0) //打开错误{close(fd);return;}switch(st.type) //顺利开启{case T_DEVICE:case T_FILE: //path路径为文件if( strcmp( fmtname(path),findName)0) //抽取名称并对比名称一致{printf(%s\n, path); //打印路径}break;case T_DIR: //path路径为目录//目录名过长if(strlen(path) 1 DIRSIZ 1 sizeof buf){printf(find: path too long\n);break;}//复制path到buf//buf记录此刻path的绝对路径strcpy(buf, path);p bufstrlen(buf);*p /; //末尾加分隔符//注意此处指针p的指向buf末尾while(read(fd, de, sizeof(de)) sizeof(de)) //读取path路径目录内容//read会遍历一遍此目录下的文件{if(de.inum 0) //inode0continue;//不正常的inode跳出//跳过. ..目录if(strcmp(de.name, .) 0 || strcmp(de.name, ..)0 )continue;//复制名称到p头地址的空间 //即在buf后面补名字memmove(p, de.name, DIRSIZ);p[DIRSIZ] 0; //地址结束标识符findname(buf,findName); //递归查询}break;}close(fd); }int main(int argc, char *argv[]) {//参数不符合if(argc 2){printf(err\n);exit(0);}findname(argv[1],argv[2]);exit(0); }编译准备 往Makefile中UPROGS\项目添加 $U/_find\运行结果 make qemu echo b mkdir a echo a/b mkdir a/aa echo a/aa/b find . brootQQQ:/home/MIT6.828/xv6-labs-2023# make qemu qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -global virtio-mmio.force-legacyfalse -drive filefs.img,ifnone,formatraw,idx0 -device virtio-blk-device,drivex0,busvirtio-mmio-bus.0xv6 kernel is bootinghart 1 starting hart 2 starting init: starting sh $ echo b mkdir a echo a/b mkdir a/aa echo a/aa/b find . b$ $ $ $ $ ./b ./a/b ./a/aa/b $符合预期工具测试 make GRADEFLAGSfind gradeno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -marchrv64g -nostdinc -I. -Ikernel -c user/initcode.S -o user/initcode.o riscv64-unknown-elf-ld -z max-page-size4096 -N -e start -Ttext 0 -o user/initcode.out user/initcode.o riscv64-unknown-elf-objcopy -S -O binary user/initcode.out user/initcode riscv64-unknown-elf-objdump -S user/initcode.o user/initcode.asm riscv64-unknown-elf-ld -z max-page-size4096 -T kernel/kernel.ld -o kernel/kernel kernel/entry.o kernel/kalloc.o kernel/string.o kernel/main.o kernel/vm.o kernel/proc.o kernel/swtch.o kernel/trampoline.o kernel/trap.o kernel/syscall.o kernel/sysproc.o kernel/bio.o kernel/fs.o kernel/log.o kernel/sleeplock.o kernel/file.o kernel/pipe.o kernel/exec.o kernel/sysfile.o kernel/kernelvec.o kernel/plic.o kernel/virtio_disk.o kernel/start.o kernel/console.o kernel/printf.o kernel/uart.o kernel/spinlock.o riscv64-unknown-elf-objdump -S kernel/kernel kernel/kernel.asm riscv64-unknown-elf-objdump -t kernel/kernel | sed 1,/SYMBOL TABLE/d; s/ .* / /; /^$/d kernel/kernel.sym make[1]: Leaving directory /home/MIT6.828/xv6-labs-2023Test find, in current directory find, in current directory: OK (3.1s)Test find, recursive find, recursive: OK (0.9s)测试通过五、xargs 实验内容 为xv6编写一个简单版本的uinx xargs程序它的参数描述了要运行的命令它从标准输入中读取行它运行每一行的命令将此行文本添加到命令参数中程序存放在user/xargs.c一个实例 $ echo hello too | xargs echo byebye hello too$ 实验过程 实现方法 从标准输入中读取命令并执行设置两个数组一个用于从标准输入中获取每一行的命令及其参数一个用于将获取的一行指令传递给子程序执行不断读取标准输入遇到换行符就执行一次命令直到标准输入中无数据 exec函数 int exec(char *file, char *argv[]) Load a file and execute it with arguments; only returns if error.加载一个文件并按给定参数执行 实现代码 #include kernel/types.h #include kernel/stat.h #include user/user.h #include kernel/param.h#define MAXN 1024int main(int argc, char *argv[]) {if (argc 2){fprintf(2, usage: xargs command\n);exit(1);}char *argv_c[MAXARG]; // 存放子进程exec的参数//MAXARG是一个宏定义用于限制一个进程可以从其命令行参数中获取的最大字节for (int i 1; i argc; i) //去除xargs,保留余下部分argv_c[i - 1] argv[i];char buf[MAXN]; // 存放从标准输入转化而来的参数char c 0;int stat 1; // 从标准输入read返回的状态while (stat) // 标准输入中还有数据{int buf_tail 0; // buf尾指针int arg_begin 0; // 当前这个参数在buf中开始的位置int argv_tail argc - 1;//argv本身还有参数while (1) // 读取一行 //每行执行一次{stat read(0, c, 1); //从标准输入中读取一个字符//标准输入的文件描述符通常为0if (stat 0) // 标准输入中没有数据exitexit(0);if (c || c \n) //此字符为空格或换行//意味着单个参数输入结束或开始换行{buf[buf_tail] 0; //最后一个参数必需为0否则会执行失败//先0后自增argv_c[argv_tail] buf[arg_begin]; //往argv_c中拼接一个参数//字符串操作arg_begin buf_tail; //更新下一个参数的起点位置if (c \n) //每此换行执行一次break;}else //拼接读取的单个字符{buf[buf_tail] c;}}argv_c[argv_tail] 0; //结束标志if (fork() 0){exec(argv_c[0], argv_c); //加载命令并执行}else{wait(0);}}exit(0); }编译准备 往Makefile中UPROGS\项目添加 $U/_xargs\运行结果 rootQQQ:/home/MIT6.828/xv6-labs-2023# make qemu qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -global virtio-mmio.force-legacyfalse -drive filefs.img,ifnone,formatraw,idx0 -device virtio-blk-device,drivex0,busvirtio-mmio-bus.0xv6 kernel is bootinghart 2 starting hart 1 starting init: starting sh $ echo hello too | xargs echo bye bye hello too $ find . b | xargs grep hello hello hello hello $ sh xargstest.sh $ mkdir: a failed to create $ $ mkdir: c failed to create $ $ $ hello hello hello $ $工具测试 riscv64-unknown-elf-ld -z max-page-size4096 -N -e start -Ttext 0 -o user/initcode.out user/initcode.o riscv64-unknown-elf-objcopy -S -O binary user/initcode.out user/initcode riscv64-unknown-elf-objdump -S user/initcode.o user/initcode.asm riscv64-unknown-elf-ld -z max-page-size4096 -T kernel/kernel.ld -o kernel/kernel kernel/entry.o kernel/kalloc.o kernel/string.o kernel/main.o kernel/vm.o kernel/proc.o kernel/swtch.o kernel/trampoline.o kernel/trap.o kernel/syscall.o kernel/sysproc.o kernel/bio.o kernel/fs.o kernel/log.o kernel/sleeplock.o kernel/file.o kernel/pipe.o kernel/exec.o kernel/sysfile.o kernel/kernelvec.o kernel/plic.o kernel/virtio_disk.o kernel/start.o kernel/console.o kernel/printf.o kernel/uart.o kernel/spinlock.o riscv64-unknown-elf-objdump -S kernel/kernel kernel/kernel.asm riscv64-unknown-elf-objdump -t kernel/kernel | sed 1,/SYMBOL TABLE/d; s/ .* / /; /^$/d kernel/kernel.sym make[1]: Leaving directory /home/MIT6.828/xv6-labs-2023Test xargs xargs: OK (4.2s) rootQQQ:/home/MIT6.828/xv6-labs-2023#测试通过
http://www.zqtcl.cn/news/243341/

相关文章:

  • 餐饮加盟网站建设字体怎么安装wordpress
  • 网站建设与维护培训凡科和有赞哪个好用
  • 景区网站的作用长春新冠最新情况
  • 个人网站上传有啥要求wordpress 浏览记录
  • appcan 手机网站开发wordpress首页音乐
  • 杭州响应式网站案例建筑工程网站建站方案
  • 网站访客抓取国内网站搭建
  • 凡科网站做的好不好太原网页
  • 十堰商城网站建设国外效果图网站
  • 怎么登陆建设工程网站泉州网红
  • 哈尔滨队网站网页美工跨境电商是什么意思
  • 网站规划与建设课程推广型网站建设软件
  • 山东网站建设系统网站设计哪家更好
  • 网络推广有哪些网站网络推广公司联系昔年下拉
  • 长沙专业外贸建站公司百度提交网站入口网站
  • 西安网站搭建建设定制市场营销推广策略
  • 用户等待网站速度公司网站怎么做站外链接
  • 设计新闻发布网站模板wonder audio wordpress
  • 教育与培训网站建设wordpress侧栏文章
  • 四川做网站的公司哪家好信誉好的赣州网站建设
  • seo外包网站网站的备案流程图
  • 学网站建设好么免费网页制作有哪些
  • 宁波公司网站开发招聘最便宜的视频网站建设
  • 找人做网站大概多少钱永州企业网站建设
  • 免费备案网站空间网站怎么做组织图
  • 四川省和城乡建设厅网站怎么做网站淘宝转换工具
  • 网站单页支付宝支付怎么做的排名优化公司口碑哪家好
  • 淄博网站制作服务推广做网站服务器配置
  • ppt做的好的有哪些网站有哪些广州品牌型网站建设
  • 怎么学做一件完整衣服网站网站 相对路径