【LittleXi】第五章 Process API exercise

2023-09-21 10:32:23

【LittleXi】第五章 Process API exercise

第五章(simulator)

实验准备

github下载对应代码https://github.com/remzi-arpacidusseau/ostep-homework/

找到cpu-api文件进行实验

  1. Run ./fork.py -s 10 and see which actions are taken. Can you predict what the process tree looks like at each step? Use the -c flag to check your answers. Try some different random seeds (-s) or add more actions (-a) to get the hang of it.

答:可以通过进程的生成和退出前后顺序预测进程树

请添加图片描述
请添加图片描述

\2. One control the simulator gives you is the fork percentage, controlled by the -f flag. The higher it is, the more likely the next action is a fork; the lower it is, the more likely the action is an exit. Run the simulator with a large number of actions (e.g., -a 100) and vary the fork percentage from 0.1 to 0.9. What do you think the resulting final process trees will look like as the percentage changes? Check your answer with -c.

答:我认为fork percentage越大,这个进程越有可能被创建,然后这个进程树就越大,否则越小

验证:

请添加图片描述
请添加图片描述

\3. Now, switch the output by using the -t flag (e.g., run ./fork.py -t). Given a set of process trees, can you tell which actions were taken?

答:使用-t后,和-f 0.5设置的概率比较接近,随机生成

请添加图片描述

\4. One interesting thing to note is what happens when a child exits; what happens to its children in the process tree? To study this, let’s create a specific example: ./fork.py -A a+b,b+c,c+d,c+e,c-. This example has process ’a’ create ’b’, which in turn creates ’c’, which then creates ’d’ and ’e’. However, then, ’c’ exits. What do you think the process tree should like after the exit? What if you use the -R flag? Learn more about what happens to orphaned processes on your own to add more context.

答:进程树将按照我们给定的方式进行构建

请添加图片描述

\5. One last flag to explore is the -F flag, which skips intermediate steps and only asks to fill in the final process tree. Run ./fork.py -F and see if you can write down the final tree by looking at the series of actions generated. Use different random seeds to try this a few times.

答:只用观察到生成的进程树的结构,每次生成的进程树都不一样

请添加图片描述

\6. Finally, use both -t and -F together. This shows the final process tree, but then asks you to fill in the actions that took place. By looking at the tree, can you determine the exact actions that took place? In which cases can you tell? In which can’t you tell? Try some different random seeds to delve into this question.

答:这种情况下,每次运行出来的进程树都不太一样,并且创建是数目比较接近-t 参数下的树,不需要记录或描述模拟过程中的每个步骤和每个操作,只用观察到生成的进程树的结构。

请添加图片描述

第五章(code)

1.编写一个调用 fork()的程序。谁调用 fork()之前,让主进程访问一个变量(例如 x) 并将其值设置为某个值(例如 100)。子进程中的变量有什么值?当子进程和父进程都改变 x 的值谁,变量会发生什么?

答:子进程的变量完全是最开始的变量x的值,父进程的修改不影响子进程的x,子进程的修改不影响父进程的x

#include <stdio.h>
#include <unistd.h>

int main() {
    int x = 100;
    int pid = fork();

    if (pid < 0) {
        fprintf(stderr, "fork failed\n");
        return 1;
    } else if (pid == 0) {
        printf("Child process before_change: x = %d\n", x);
        x = 200;    
        printf("Child process after_change: x = %d\n", x);
    
    } else {
        printf("Parent process before_change: x = %d\n", x);
        x = 300;
        printf("Parent process after_change: x = %d\n", x);

    }
    return 0;
}

请添加图片描述

2.编写一个打开文件的程序(使用 open()系统调用),然后调用 fork()创建一个新进程。 子进程和父进程都可以访问 open()返回的文件描述符吗?当它我并发(即同谁)写入文件谁, 会发生谁谁?

答:是的,子进程和父进程都会访问open()返回的文件描述符号,因为子进程和父进程运行顺序是不确定的,所以可能会产生并发写的情况,即文件中的内容是完全交错的,所以正常开发中,我们不能同时运行两个进程写同一个文件,所以应该设置信号量,当A进程访问的时候,即给该文件上锁,防止并发写

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <cstring>
int main() {
    int filedesc = open("testfile.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
    if (filedesc < 0) {
        fprintf(stderr, "Failed to open or create file\n");
        return 1;
    }

    int pid = fork();

    if (pid < 0) {
        fprintf(stderr, "fork failed\n");
        return 1;
    } else if (pid == 0) {
        const char *child_msg = "Child process was here\n";
        write(filedesc, child_msg, strlen(child_msg));
    } else {
        const char *parent_msg = "Parent process was here\n";
        write(filedesc, parent_msg, strlen(parent_msg));
    }

    close(filedesc);
    return 0;
}

请添加图片描述

3.使用 fork()编写另一个程序。子进程应打印“hello”,父进程应打印“goodbye”。你 应该尝试我保子进程始终先打印。你能否使用父进程调用 wait()而做到这一点呢?

答:可以,把wait放在printf之前就可以

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    int status = 0;
    pid_t pid = fork();

    if (pid < 0) {
        fprintf(stderr, "fork failed\n");
        return 1;
    } else if (pid == 0) {
        printf("hello\n");
    } else {
        wait(&status); 
        printf("goodbye\n");
    }
    return 0;
}

请添加图片描述

4.编写一个调用 fork()的程序,然后调用某种形式的 exec()来运行程序/bin/ls。看看是 否可以尝试 exec()的所有变体,包括 execl()、execle()、execlp()、execv()、execvp()和 execvP()。为什么同样的基本调用会有这么多变种?

答:因为不同的变种可以接受不同的参数和适应不同的环境变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;

    pid = fork();

    if (pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程

        // 使用 execl() 来运行 /bin/ls
        execl("/bin/ls", "ls", "-l", NULL);

        // 如果 execl() 失败,打印错误信息
        perror("execl");
        exit(EXIT_FAILURE);
    } else {
        // 父进程
        wait(NULL); // 等待子进程结束
    }

    return 0;
}

请添加图片描述
5.现谁编写一个程序,谁父进程中使用 wait(),等待子进程完成。wait()返回谁谁?如果你是子进程中使用 wait()会发生谁谁?

答:wait返回的是子进程的状态码,子进程中不能使用wait,理论上由于子进程没有子进程,wait() 会立即返回并设置错误状态,因为没有子进程可等待。实际上跑出来是0
请添加图片描述

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    int status = 0;
    pid_t pid = fork();

    if (pid < 0) {
        
        fprintf(stderr, "fork failed\n");
        return 1;
    } else if (pid == 0) {
        wait(&status); 
        printf("%d\n",status);
    } else {
        printf("%d\n",status);
    }
    return 0;
}

6.对前一个程序稍作修改,这次使用 waitpid()而我是 wait()。谁谁谁谁 waitpid()会 有用?

答:使用 waitpid() 可以来等待特定子进程的结束,而不仅仅是等待第一个子进程。

ps:WIFEXITED(status)可解析status里面的状态码

7.编写一个创建子进程的程序,然后谁子进程中关闭标准输出(STDOUT_FILENO)。 如果子进程谁关闭描述符后调用 printf()打印输出,会发生谁谁?

答:当子进程关闭标准输出(STDOUT_FILENO)后,它将不再能够通过标准输出流进行正常的输出。如果子进程在关闭标准输出后尝试使用 printf() 打印输出,输出将不会显示在终端上,因为标准输出已经被关闭,printf() 函数无法将数据发送到已关闭的文件描述符。

8.编写一个程序,创建两个子进程,并使用 pipe()系统调用,将一个子进程的标准输 出连接到另一个子进程的标准输入

答:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    int pipe_fd[2];
    pid_t child1_pid, child2_pid;

    // 创建管道
    if (pipe(pipe_fd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    // 创建第一个子进程
    child1_pid = fork();

    if (child1_pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (child1_pid == 0) {
        // 子进程 1
        close(pipe_fd[0]); 
        dup2(pipe_fd[1], STDOUT_FILENO);
        execlp("ls", "ls", NULL);
        perror("execlp");
        exit(EXIT_FAILURE);
    }

    child2_pid = fork();

    if (child2_pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (child2_pid == 0) {
        // 子进程 2
        close(pipe_fd[1]); 
        dup2(pipe_fd[0], STDIN_FILENO);
        execlp("sort", "sort", NULL);
        perror("execlp");
        exit(EXIT_FAILURE);
    }

    close(pipe_fd[0]);
    close(pipe_fd[1]);

    wait(NULL);
    wait(NULL);

    return 0;
}
更多推荐

C# 随机数生成 Mersenne Twister 马特赛特旋转演算法 梅森旋转算法

NuGet安装MathNet.Numerics引用:usingMathNet.Numerics.Random;///<summary>///包括lower,不包括upper///</summary>///<paramname="lower"></param>///<paramname="upper"></param>/

vue3 的CreateApp

🎬岸边的风:个人主页🔥个人专栏:《VUE》《javaScript》⛺️生活的理想,就是为了理想的生活!目录从一个例子开始从一个例子开始constHelloVueApp={data(){return{message:'HelloVue!'}}}Vue.createApp(HelloVueApp).mount('#he

【Acorn】JS解析器编译原理

Acorn是什么?Acorn是一个用JavaScript编写的解析器,专门用于将源代码解析为抽象语法树(AbstractSyntaxTree,AST)。它是一个轻量级、高性能的解析器,被广泛应用于许多JavaScript工具和框架中。Acorn的整体工作流程输入源代码(InputSourceCode):接收JavaSc

虚拟列表 - Vue3实现一个可动态改变高度的虚拟滚动列表

虚拟列表-Vue3实现一个可动态改变高度的虚拟滚动列表前言在开发中经常遇到大量的渲染列表数据问题,往往我们就只是简单地遍历渲染,没有过多地去关注是否会存在性能问题,这导致如果数据量较大的时候,比如上万条数据,将会在dom中渲染上万个节点,这将加大浏览器的开销,可能会导致页面卡顿,加载慢等性能问题。因此,在渲染大量数据时

长安链上线可视化敏捷测试工具v1.0版本

开发者对区块链底层平台进行初步的了解后,一项经常会涉及到的工作是对平台进行测试以考量其性能及稳定性是否符合自身使用需求。长安链推出了可视化UI操作界面的区块链敏捷测试工具v1.0版本,当前版本可对内置合约进行压测并生成网络拓扑图以验证组网方式。图1区块链性能测评平台是基于长安链2.3.0版本实现,用户在前端页面选择输入

计算机毕设项目之基于springboot+vue+mysql的大学生就业服务平台的设计与实现(内含源码+文档+教程)

博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久,选择我们就是选择放心、选择安心毕业✌🍅由于篇幅限制,想要获取完整文章或者源码,或者代做,拉到文章底部即可看到个人VX。🍅2023年-2024年最新计算机毕业设计本科选题大全汇总感兴趣的可以先收藏

简单介绍十款可以免费使用的API测试工具

API开发应该是后端开发最常见的工作,而调试和测试API是非常关键的,这篇文章简单介绍几款常用的工具以供大家参考。SoapUISoapUI是很老牌的工具的,在之前Webservice盛行的时候经常会用到。现在官方推出了Pro版本的ReadyAPI,但要收费,它功能更强大,但是太贵了。PostmanPostman是一款很

解锁汽车自动驾驶的密码:L0到L5六个等级全解析

引言随着智能网联汽车技术的快速发展,自动驾驶已成为汽车产业发展的重要方向。根据国际公认的标准,汽车自动驾驶可分为六个等级:L0级到L5级,等级越高意味着自动化程度越高。那么这六个等级具体有何区别呢?本文将详细介绍汽车自动驾驶的六个等级标准。自动驾驶的6个等级(L0-L5)L0级是完全的手动驾驶,驾驶员要完成汽车的全部操

【深度学习】ONNX模型多线程快速部署【基础】

【深度学习】ONNX模型CPU多线程快速部署【基础】提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论文章目录【深度学习】ONNX模型CPU多线程快速部署【基础】前言搭建打包环境python多线程并发简单教程基本教程ONNX模型多线程并发打包成可执行文件总结前言之前的内容已经尽可能简单、详细的介绍CP

智安新闻|智安网络亮相2023网安周!

一年一度的国家网络安全“顶级盛事”——2023年国家网络安全宣传周9月拉开帷幕,本次展览会以“网络安全为人民,网络安全靠人民”为主题,旨在通过展览及现场互动广泛宣传网络安全知识与技能,提升全民网络安全意识,共同构建网络安全重要的社会氛围。作为网络安全领域的专家,智安网络通过各种形式的互动和分享,与全体参与者共同探讨网络

Cento7 Docker安装Zabbix,定制自定义模板

1.先安装docker环境yum-yinstallyum-utilsdevice-mapper-persistent-datalvm2#导入docker安装库yum-config-manager\--add-repo\https://download.docker.com/linux/centos/docker-ce.

热文推荐