惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

游戏玩后感:ReLief:献给亲爱的你 我的周边(谷子)分享 游戏玩后感:Kanon 简谱:致真实的你 《Rust中常见的有关生命周期的误解》学习笔记 简谱:StarMap 简谱:かく咲きたらばいと恋ひめやも 简谱:东风 简谱:无法诉说的思念 简谱:Girlish 游戏玩后感:时钟机关的Layline 简谱:风之琶音 简谱:星空的记忆 简谱:因为遇见了你 简谱:月童 番茄简谱脚本转调器 游戏玩后感:青空下的约定:Refine 游戏玩后感:在这苍穹展翅 书籍读后感:控制论与科学方法论 游戏玩后感:恋爱表达式 游戏玩后感:樱之诗 MLIR-tutorial学习笔记 游戏玩后感:潜伏之赤途 游戏玩后感:纯爱咖啡厅:帕露菲重制版 游戏玩后感:智以泪聚 游戏玩后感:初雪樱 游戏玩后感:告别回忆:从今以后 游戏玩后感:梦灯花 游戏玩后感:金辉恋曲四重奏 游戏玩后感:五彩斑斓的世界 昇腾310P使用记录 游戏玩后感:AIR 游戏玩后感:弹丸论破 游戏玩后感:流景之海的艾佩莉亚 Xilinx_HLS上板过程记录 游戏玩后感:告别回忆2 游戏玩后感:恋爱绮谭 Faiss和Rapidsai_Raft使用记录 游戏玩后感:近月少女的礼仪 游戏玩后感:樱色之云,绯色之恋 游戏玩后感:幸运草的约定 游戏玩后感:星之梦、候鸟和丸子与银河龙 游戏玩后感:白色相簿2 Windows上使用VTune分析PyTorchExtension调用的Cpp程序 SpinalHDL上板过程记录 游戏玩后感:仰望夜空的星辰 最简单的算卦方法之一:梅花易数法 游戏玩后感:苍之彼方的四重奏 krkr引擎解包工具介绍 自定义CUDA实现PyTorch算子的四种简单方法 游戏玩后感:星空的记忆 游戏玩后感:9nine 游戏玩后感:AtriMyDearMoments 游戏玩后感:极限脱出 游戏玩后感:魔女的夜宴 SSH实现多跳代理 动漫观后感:向山进发 flv重封装H264、AAC流 动漫观后感:夏日重现 CSP模板 游戏玩后感:海沙风云 动漫观后感:灵能百分百 游戏玩后感:交响乐之雨 游戏玩后感:爱上火车LastRun 游戏玩后感:LittleBustersEX 游戏玩后感:SummerPockets 游戏玩后感:逆转裁判 Ultra96V2开发板简单使用 SpinalWorkshop实验笔记(三) SpinalWorkshop实验笔记(二) SpinalWorkshop实验笔记(一) PYNQ开发板上使用USB声卡+OSS兼容层播放音频 TestOS移植K210开发板 rCore-Tutorial-Book-v3学习笔记(七) 动漫观后感:凉宫春日的忧郁 rCore-Tutorial-Book-v3学习笔记(♭七) rCore-Tutorial-Book-v3学习笔记(六) rCore-Tutorial-Book-v3学习笔记(五) rCore-Tutorial-Book-v3学习笔记(四) rCore-Tutorial-Book-v3学习笔记(三) rCore-Tutorial-Book-v3学习笔记(二) rCore-Tutorial-Book-v3学习笔记(一) 游戏玩后感:RewritePlus MIT-6.S081-2020实验(xv6-riscv64)十一:net MIT-6.S081-2020实验(xv6-riscv64)十:mmap MIT-6.S081-2020实验(xv6-riscv64)九:fs MIT-6.S081-2020实验(xv6-riscv64)八:lock MIT-6.S081-2020实验(xv6-riscv64)七:thread MIT-6.S081-2020实验(xv6-riscv64)六:cow MIT-6.S081-2020实验(xv6-riscv64)五:lazy MIT-6.S081-2020实验(xv6-riscv64)四:traps MIT-6.S081-2020实验(xv6-riscv64)三:pgtbl MIT-6.S081-2020实验(xv6-riscv64)二:syscall 动漫观后感:吹响吧上低音号 快速生成网络mp4视频缩略图技术 用plantuml画图示例 QQ缩略图和大图不同实现 Python制作字符图片 动漫观后感:命运石之门 Unity3D+Post Processing Stack V2自定义后处理效果研究
MIT-6.S081-2020实验(xv6-riscv64)一:util
VnYzm · 2020-12-29 · via

实验文档

概述

实验一主要涉及调用系统调用函数,这些系统调用函数基本都是符合POSIX规范的,和操作系统本身关系较小,在调试的时候也可以先把程序在外部的Linux下跑通然后再放进xv6中运行。

内容

sleep

基本没什么特别的内容,按说明的做就行了。

#include "kernel/types.h"
#include "user/user.h"

int main(int argc, char *argv[]) {
    int i;
    if (argc < 2) {
        printf("sleep: tick number is not specified\n");
        exit(0);
    }
    i = atoi(argv[1]);
    if (i <= 0) {
        printf("sleep: tick number is invalid\n");
        exit(0);
    }
    sleep(i);
    exit(0);
}

pingpong

涉及进程创建和管道,当一个进程在read的时候会挂起直至读到内容,所以进程的执行顺序也是非常清晰的。

#include "kernel/types.h"
#include "user/user.h"

int main() {
    int parent_fd[2], child_fd[2];
    char buf[16];
    pipe(parent_fd); pipe(child_fd);
    if (fork() == 0) {
        read(parent_fd[0], buf, 4);
        buf[4] = '\0'; printf("%d: received %s\n", getpid(), buf);
        write(child_fd[1], "pong", 4);
    } else {
        write(parent_fd[1], "ping", 4);
        read(child_fd[0], buf, 4);
        buf[4] = '\0'; printf("%d: received %s\n", getpid(), buf);
    }
    exit(0);
}

primes

这个算是管道比较高级的应用,有点流水线那味道。根据实验文档所给的参考链接里的图片

给人一种每个进程都是筛完合数然后将筛完的数一股脑传给下一级进程的感觉,其实不然,这样一方面需要多一个缓冲区来存储筛完的数,另一方面也不方便并行。实际上应该更好地利用管道的队列性质。对于每个进程,从输入管道得到第一个质数后就创建子进程,然后对输入管道剩下的数进行筛选,如果合法就放入输出管道,这样多个进程同时操作,也不用缓冲区了。子进程中创建子进程这种操作很难直接表示,需要用到递归思想。

#include "kernel/types.h"
#include "user/user.h"

void f(int pp) {
    int prime;
    if (read(pp, (char *)&prime, 4) != 0) {
        printf("prime %d\n", prime);
        int p[2]; pipe(p);
        if (fork() == 0) {
            close(p[1]); f(p[0]);
        } else {
            int t;
            while (read(pp, (char *)&t, 4) != 0) {
                if (t % prime != 0) write(p[1], (char *)&t, 4);
            }
            close(p[1]); close(p[0]); close(pp); wait(0);
        }
    } else close(pp);
}
int main() {
    int i, p[2]; pipe(p);
    if (fork() == 0) {
        close(p[1]); f(p[0]);
    } else {
        for (i = 2; i < 36; i++) write(p[1], (char *)&i, 4);
        close(p[1]); close(p[0]); wait(0);
    }
    exit(0);
}      

注意每次fork以后会给当前的管道添加一个引用,而想要关闭一个管道必须将它的所有引用都关闭才行。因此每次在fork之后关闭不用的管道是一个好习惯,防止忘关导致其他进程读不到eof。

find

基本上套用ls.c里的内容。

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"

const char *now = ".", *par = "..";

char* fmtname(char *path) {
    char *p;
    for(p = path + strlen(path); p >= path && *p != '/'; p--);
    p++;
    return p;
}

void find(char *path, char *pattern) {
    char buf[128], *p;
    int fd;
    struct dirent de;
    struct stat st;

    if((fd = open(path, 0)) < 0){
        printf("find: cannot open %s\n", path);
        return;
    }

    if(fstat(fd, &st) < 0){
        printf("find: cannot stat %s\n", path);
        close(fd);
        return;
    }

    switch(st.type){
        case T_FILE:
            if (strcmp(pattern, fmtname(path)) == 0) printf("%s\n", path);
            break;

        case T_DIR:
            if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
                printf("ls: path too long\n");
                break;
            }
            strcpy(buf, path);
            p = buf + strlen(buf);
            *p++ = '/';
            while(read(fd, &de, sizeof(de)) == sizeof(de)){
                if(de.inum == 0) continue;
                if (strcmp(de.name, now) == 0 || strcmp(de.name, par) == 0) continue;
                memmove(p, de.name, DIRSIZ);
                p[DIRSIZ] = 0;
                find(buf, pattern);
            }
            break;
    }
    close(fd);
}

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("find: argument is less than 2\n");
        exit(0);
    }
    find(argv[1], argv[2]); exit(0);
}

xargs

也没啥好说的,基本就是对命令行参数和标准输入的字符串处理。

#include "kernel/types.h"
#include "kernel/param.h"
#include "user/user.h"

int main(int argc, char *argv[]) {
    char line[256], *p[MAXARG], ch;
    int lines = 0, linen, ps = 0, pn, i, j;
    for (i = 0; i < argc - 1; i++) {
        p[ps++] = line + lines;
        for (j = 0; j < strlen(argv[i + 1]); j++)
            line[lines++] = argv[i + 1][j];
        line[lines++] = '\0';
    }
    linen = lines; pn = ps; p[pn++] = line + linen;
    while (read(0, &ch, 1) > 0) {
        if (ch == '\n') {
            line[linen++] = '\0'; p[pn++] = 0;
            if (fork() == 0) exec(argv[1], p);
            else {
                wait(0); linen = lines; pn = ps; p[pn++] = line + linen;
            }
        } else if (ch == ' ') {
            line[linen++] = '\0'; p[pn++] = line + linen;
        } else line[linen++] = ch;
    }
    exit(0);
}