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

网站内置字体好用的视频播放器app

网站内置字体,好用的视频播放器app,厦门网站建设小程序开发,wordpress 附件管理Boot xv6 按照示例切换到 util 分支后#xff0c;看到目录下包含 Makefile 文件#xff0c;执行 make qemu 即可。 sleep 思路 借助系统调用 sleep 实现一个命令行程序#xff0c;关键是要找到封装了系统调用的 C 函数的位置#xff0c;根据提示#xff1a; … user/u…Boot xv6 按照示例切换到 util 分支后看到目录下包含 Makefile 文件执行 make qemu 即可。 sleep 思路 借助系统调用 sleep 实现一个命令行程序关键是要找到封装了系统调用的 C 函数的位置根据提示 … user/user.h for the C definition of sleep callable from a user program … 可知该函数的声明位于 user.h 头文件中声明方式很简单 int sleep(int);将其“拷贝”include到需要编写的代码 user/sleep.c 中调用 sleep(睡眠时间) 即可。 最后按照提示将编写的 sleep 代码添加到 Makefile 的 UPROGS 中添加后如下所示 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\ # here代码 // user/sleep.c#include kernel/types.h // 注意先包含types.h #include user/user.h // 再包含user.huser.h中存在在types.h中定义的别名int main(int argc, char* argv[]) {if (argc ! 2) {fprintf(2, sleep: argument count error\n);exit(1);}int time atoi(argv[1]);sleep(time);exit(0); }pingpong 思路 本题主要是要理解管道的接口设计以及借助该接口实现父进程与子进程之间的通信。这是 xv6 文档中对于 pipe 调用的描述 int pipe(int p[]) // Create a pipe, put read/write file descriptors in p[0] and p[1].pipe 创建一个管道并分别将该管道的读、写端文件描述符置为 p[0] 和 p[1]之后调用 fork 创建一个子进程由于 fork 的作用是将父进程的数据直接拷贝给子进程因此子进程同时继承了父进程的管道文件描述符可以借助该文件描述符进行进程间通信IPC相当于借助一个共享文件进行通信只不过该“文件”存储在内存的内核区域中而不占用实际的磁盘存储空间。 利用管道解决本题的基本流程如下首先需要创建两个管道 pa 和 pb然后 父进程向管道 pa 的写端写入 1 字节数据然后关闭 pa 的写端。子进程从管道 pa 的读端读取 1 字节数据然后关闭 pa 的读端打印信息然后向管道 pb 的写端写入 1 字节数据关闭 pb 的写端。父进程从管道 pb 的读端读取 1 字节数据关闭 pb 的读端最后打印信息。 这里需要解释一下为什么需要两个管道由于进程调度策略的影响父进程和子进程的执行顺序并不确定。可能出现这样一种情况在 fork 创建子进程后父进程先被调度将 1 字节数据写入管道这时理想的情况是子进程被调度然后读取父进程发送的数据但是事实可能并不会如我们所愿子进程可能一直得不到调度父进程继续向下执行从管道中读取自己刚刚发送的 1 字节的数据这样子进程就无法收到父进程发送的数据父子进程之间的通信也就失败了。 通过创建两个管道并分别关闭对应的读端和写端就能够得到两个单向数据流的管道也就不会有上述自己写入的数据被被自己读取的情况出现。 代码 // user/pingpong.c#include kernel/types.h #include user/user.hint main(int argc, char* argv[]) {char buf[2];int pa[2], pb[2];pipe(pa);pipe(pb);int pid fork();if (pid 0) {close(pa[1]);close(pb[0]);// phase_2read(pa[0], buf, 1);close(pa[0]);printf(%d: received ping\n, getpid());write(pb[1], a, 1);close(pb[1]);}else if (pid 0) {close(pa[0]);close(pb[1]);// phase_1write(pa[1], a, 1);close(pa[1]);// phase_3read(pb[0], buf, 1);close(pb[0]);printf(%d: received pong\n, getpid());}else {fprintf(2, pingpong: fork failed\n);exit(1);}exit(0); }primes 思路 实现一个基于管道的并发埃式筛The sieve of Eratosthenes关键是要理解管道的机制以及仔细阅读题干给出的[文章](Bell Labs and CSP Threads (swtch.com))该文章有关该埃式筛方法的介绍图片如下所示 该算法的个人感觉十分精妙以下是基本流程 进程 0主进程发出一系列从 2 开始的整数序列。进程 1 首先接收来自进程 0 发出的第一个整数 primeprime 一定是一个质数将其打印出来。然后继续按顺序接收来自进程 0 发出的其它整数若接收到的某个整数能够被 prime 整除则丢弃它不做处理否则将该整数发送给下一个进程。后续进程的操作与进程 1 类似直到没有任何整数发送给下一个进程程序终止。 算法的思路并不复杂主要问题在于如何使用管道实现上述流程中进程 i 与进程 i 1 之间的通信。我这里只使用了一个 int[2] 来轮换地存放管道的文件描述符并使用一个缓冲区来暂存每次要发送给下一个进程的数在一个进程完成它所做的工作后再将缓冲区中的数据批量写入管道并创建子进程来完成接下来的工作。这里要千万注意管道完成读取或写入后及时关闭否则可能会出现子进程读取管道时阻塞的情况。 我在写下这篇博客的过程中发现虽然我使用的这个方法能够达到预期的效果并成功通过测试用例但是其实是有一定问题的本方法的处理过程是串行的。事实上每个进程都是在将本进程的所有工作全部完成之后再调用 fork 来创建子进程完成后续的工作本质上与放在一个进程中完成所有工作并没有区别与文章中提到的 “Concurrent” 完全相悖。理想的做法应该是创建一个 int[2] 数组来存放管道的文件描述符并及时 fork 子进程来工作以此来实现并发具体的代码实现有待后续改进。 代码 // user/primes.c#include kernel/types.h #include user/user.hint main(int argc, char* argv[]) {int p[2];pipe(p);int buf;int plist[35];for (int i 2; i 35; i) {write(p[1], (char*)i, 4);}close(p[1]);while (read(p[0], (char*)buf, 4)) {int prime buf;printf(prime %d\n, prime);int pcnt 0;while (read(p[0], (char*)buf, 4)) {if (buf % prime) {plist[pcnt] buf;}}close(p[0]);pipe(p); // rotating pipefor (int i 0; i pcnt; i) {write(p[1], (char*)(plist i), 4);}close(p[1]);int pid fork();if (pid 0) {continue;}else if (pid 0) {wait(0);exit(0);}else {fprintf(2, primes: fork error\n);exit(1);}}exit(0); }find 思路 本题是这个 Lab 中我花费时间最长的代码思路虽然不算很复杂但是有很多的细节问题我在写的时候没有考虑到感觉 debug 时间差不多是 coding 的几倍了。。。 题目要求实现一个简易的 find 命令根据提示可以参考 user/ls.c 对目录的读取操作并使用递归来实现对子目录的查找。基本思路就是打开一个指定路径的文件目录也算是特殊的文件并根据文件的类型做不同处理 如果文件是常规文件则判断改文件名是否是目标文件名find 的第二个参数如果是则将其完整路径打印至标准输出。如果文件是目录文件则读取该目录下的所有文件名并在该目录路径尾部加上 /st.name依次构造一个新的文件名继续递归调用 find。注意不要递归进入 . 和 ..否则将导致无限递归。 以上便是基本思路具体实现可以阅读完整代码下面讲一下我遇到的一些问题bug 使用 fstat 获取文件信息时 st.type 始终为 3T_DEVICE 类型。 这个问题其实挺难绷的原因是我把 if ((fd open(path, 0)) 0) 写成了 if ((fd open(path, 0) 0))因为 的优先级大于 所以导致 fd 的值始终为 0 或 1逻辑表达式的值只能为真或假那么后续产生意想不到的结果也就不意外了。。。 出现 find: cannot open file ./sh 之后所有文件均打开失败 在打印出文件描述符的值后问题的起因比较明显了。 文件描述符一直在增大最终文件打开失败open 返回 -1。很明显是因为文件在打开后没有及时关闭并释放文件描述符最终文件描述符被全部占用新的文件无法再被打开。这也解释了既然程序退出后所有打开的文件会自动关闭为什么还要建议手动关闭文件的问题。 读取到空文件名 前面的问题解决之后我发现程序仍然会出现无限递归搜索的情况如下图所示按理说我已经对文件名进行了判断如果是 . 或者 .. 则不做处理。 尝试打印文件名之后我发现目录的最后一个文件名为空这样的空文件名将导致程序不断往其末尾追加斜杠 / 而并没有递归进入该目录中。 事实上使用 read 读取目录时在读取目录的所有条目之后会返回一个空的 dirent 结构体此时 de.name 为空作为循环结束的标志。其实 user/ls.c 有针对这个特性的判断不过当时 coding 的时候没有细看。所以正如 Lab guidance 中所说 Only when you have a firm grasp of the assignment and solution, then start coding. 代码 // user/find.c#include kernel/types.h #include kernel/stat.h #include kernel/fs.h #include user/user.hchar* file_name(char* path) {char* p;for (p path strlen(path); p path *p ! /; --p);p;return p; }void find(char* path, char* target) {int fd;struct dirent de;struct stat st;char buf[512];char* name, * p;if ((fd open(path, 0)) 0) {fprintf(2, find: cannot open file %s\n, path);return;}if (fstat(fd, st) 0) {fprintf(2, find: cannot stat file %s\n, path);close(fd);return;}switch (st.type) {case T_FILE:name file_name(path);if (!strcmp(name, target)) {printf(%s\n, path);}break;case T_DIR:while (read(fd, de, sizeof(de)) sizeof(de)) {// prevent infinite recursionif (!de.inum || !strcmp(de.name, .) || !strcmp(de.name, ..)) {continue;}// generate path of sub directorystrcpy(buf, path);p buf strlen(buf);*p /;memmove(p, de.name, DIRSIZ);p[DIRSIZ] 0;find(buf, target);}break;default:break;}close(fd); }int main(int argc, char* argv[]) {if (argc ! 3) {fprintf(2, find: argument count error\n);exit(1);}find(argv[1], argv[2]);exit(0); }xargs 思路 相较于 findxargs 的实现就简单很多了。由于之前自己实现过一个简单的 shell因此对于 exec 系统调用还算比较熟悉本题的主要内容就是根据 argv 和标准输入构造一个新的参数列表作为指定命令行程序的参数并使用 exec 来进行调用。 程序的流程比较简单这里不过多介绍直接查看完整代码即可。 代码 // user/xargs.c#include kernel/types.h #include user/user.h #include kernel/param.hint main(int argc, char* argv[]) {int i;char buf[512];char* nargv[MAXARG];while (gets(buf, MAXARG)) {buf[strlen(buf) - 1] 0; // remove last \nfor (i 1; argv[i]; i) {nargv[i - 1] argv[i];}nargv[i - 1] buf;nargv[i] 0;int pid fork();if (pid 0) {exec(argv[1], nargv);}else if (pid 0) {wait(0);}else {fprintf(2, xargs: fork error\n);exit(1);}}exit(0); }
http://www.pierceye.com/news/668983/

相关文章:

  • 无为建设局网站安装wordpress xampp
  • 广药网站建设试卷wordpress人力资源模板下载
  • 电商网站规划的开发背景明年做那个网站能致富
  • 网站建设及托管合同wordpress页面批量生成二维码
  • 益阳市住房和建设局 网站哪些网站可做矿机期货
  • 网站开发哪里有html5网站赏析
  • 襄阳网站建设八零后做的网站怎么上传到网上运行
  • 学网站开发培训学校专业集团门户网站建设费用
  • 加快政务公开网站建设知名的摄影网站有哪些
  • 任县网站建设网络公司桐城网站开发
  • linux服务器做网站软装设计图效果图
  • 个人网站可以做商城吗被官方认可赚钱软件
  • 自己可以做网站服务器室内设计整套方案图
  • 网站建设商城网站微信广告代理
  • 创建网站的方案企业营销策划公司
  • 做彩铃的网站个人博客网站建设
  • 正黄集团博弘建设官方网站达州高端网站建设
  • 七台河建设网站wordpress logo制作
  • 怎么设计一个自己的网站番禺网站建设效果
  • 网站哪家做的好淄博网站开发选网泰
  • 网站建设与制作与维护ppt百度广告联盟收益
  • 在线网站建设费用是多少大学生活动策划书模板
  • 动物网站建设wordpress无法跳转正确页面
  • 上海市建设工程 安全协会网站wordpress会员微信支付宝
  • pc网站转换手机网站代码桂林工作网招聘
  • 营销型网站建设的要素怎么建网站赚钱
  • 成都网站建设学习郑州制作网站推荐
  • 网站建设 镇江丹阳php网站开发实例教程代码
  • 佛山外贸网站建设方案专业网站建设系统
  • 做一个网站团队需要哪些人员花钱也可以哪些网站可以做推广广告