第五周加分题--mybash的实现

题目要求

1.使用fork,exec,wait实现mybash

2.写出伪代码,产品代码和测试代码

3.发表知识理解,实现过程和问题解决的博客(包含代码托管链接)

exec函数组

一个程序如何运行另一个程序呢?

我们得搞清楚需要调用什么函数来完成这个过程。如果想使用man -k xxx这个命令进行搜索.

试试man -k program | grep execute 如下图:

再进一步使用man -k execute搜索,通过观察说明,我们找到了一系列相关的函数:

它们的命名是有规律的:

exec[l or v][p][e]

exec函数里的参数可以分成3个部分:执行文件部分,命令参数部分,和环境变量部分。

假如要执行:ls -l /etc

  • 执行文件部分就是:"/usr/bin/ls"

  • 命令参数部分就是:"ls","-l","/etc",NULL

  • 环境变量部分:这是1个数组,最后的元素必须是NULL 例如:char * env[] = {"PATH=/etc", "USER=vivian", "STATUS=testing", NULL};

    命名规则如下:

  • e:参数必须带环境变量部分,环境变量部分参数会成为执行exec函数期间的环境变量;

  • l:命令参数部分必须以"," 相隔, 最后1个命令参数必须是NULL;

  • v:命令参数部分必须是1个以NULL结尾的字符串指针数组的头部指针。例如char * pstr就是1个字符串的指针, char * pstr[] 就是数组了, 分别指向各个字符串;

  • p:执行文件部分可以不带路径, exec函数会在$PATH中找。

我们主要来学习execvp函数

代码如下

#include <unistd.h>  

int main()
{
char *argv[] = {"ls", "-l", ".", (char *)0};
printf("···Begin to Show ls -l···\n");
execvp("ls", argv);
printf("···ls -l is done! ···");
return 0;
}

结果如下图所示:

遇到的问题:execvp后面的那一条printf打印的消息没有输出?
  • 解决方案:一个程序在一个程序中运行时,内核将新程序载入到当前进程,替代当前进程的代码和数据。如果执行成功,execvp没有返回值。当前程序从进程中清除,新的程序在当前进程中运行。类比execv函数组,系统调用从当前进程中把当前程序的机器指令清除,然后在空的进程中载入调用时指定的程序代码,最后运行这个新的程序。exec调整进程的内存分配使之适应新的程序对内存的要求。相同的进程,不同的内容。

fork()

通过man -k fork命令进行搜索,可以看到,fork函数位于manpages的第二节,与系统调用有关。

如图1

使用man 2 fork命令查看fork函数,可以看到关于fork函数的所有信息:



fork函数的结构大致如下:

#include <sys/types.h>
#include <unistd.h> pid_t fork(void); //返回:子进程返回0,父进程返回子进程的PID,如果出错,则返回-1。

一般来说,运行一个C程序直到该程序全部结束,系统只会分配一个PID给这个程序,也就是说,系统里只有一条关于这个程序的进程。但执行了fork函数就不同了。fork()的作用是复制当前进程(包括进程在内存的堆栈数据),然后这个新的进程和旧的进程一起执行下去。而且这两个进程是互不影响的。如下图的逻辑所示。


#include <sys/types.h>
#include <unistd.h>
int main(){
printf("step 1\n\n"); fork();//创建一个新的进程 printf("after fork()\n\n"); int i; scanf("%d",&i);//防止程序退出 return 0;
}

得到结果如下图:

wait()

一个进程可以通过调用wait函数来等待它的子进程终止或者停止。

使用man -k wait查看与“wait”相关的信息

如下图:

再使用man 2 wait命令查看详细信息:

wait()的使用方法可以用下面的代码表示:

#include <sys/types.h>
#include <unistd.h> pid_t wait(int *status); //返回:如果成功,则返回子进程的PID,如果出错,则返回-1。

父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

需要注意的几点是:

  • 当父进程忘了用wait()函数等待已终止的子进程时,子进程就会进入一种无父进程的状态,此时子进程就是僵尸进程。

  • wait()要与fork()配套出现,如果在使用fork()之前调用wait(),wait()的返回值则为-1,正常情况下wait()的返回值为子进程的PID。

  • 如果先终止父进程,子进程将继续正常进行,只是它将由init进程(PID 1)继承,当子进程终止时,init进程捕获这个状态。

编程实现mybash

伪代码如下:

int main(){
读取要执行的命令
使用fork()函数产生子进程进行执行
如果exec函数产生了返回值,表明没有正常执行命令,输出perro()
父进程等待子进程结束,并输出值wait(&rtn) }

产品代码链接

输出结果如下

20155219 mybash的实现的更多相关文章

  1. Mybash的实现

    Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客(包含代码托管链接) 背景知识 1. fork 使用 ...

  2. 2017-2018-1 20155215 第五周 mybash的实现

    题目要求 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客(包含代码托管链接) 学习fork,exec,wait fork ma ...

  3. 2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现

    2017-2018-1 20155306 <信息安全系统设计基础>Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解 ...

  4. 20165223 《信息安全系统设计基础》 实现mybash

    一.了解 mybash 1. 简介   bash 是 Bourne Again Shell 的缩写,是linux默认的标准shell(也是大家常说的系统内核),bash也是Unix/Linux上常见的 ...

  5. 20165220 mybash

    使用fork,exec,wait实现mybash - 写出伪代码,产品代码和测试代码 - 发表知识理解,实现过程和问题解决的博客(包含代码托管链接) 1.fork 功能:创建一个新的进程 一个现存进程 ...

  6. 20155219付颖卓 《网络对抗技术》 Exp9 Web安全基础

    实验后回答问题 1.SQL注入攻击原理,如何防御 ·SQL攻击的原理很简单,就是在用户名输入框里输入SQL语句,来欺骗数据库服务器进行恶意操作 ·防御可以从以下几个方面下手: (1)在web网页设计的 ...

  7. 20155219付颖卓 Exp3 免杀原理与实践

    1.基础问题回答 (1)杀软是如何检测出恶意代码的? 杀毒软件有一个病毒的特征码库,通过识别恶意代码的特征码或者特征片段检测恶意代码 杀毒软件通过动态检测对象文件的行为来识别恶意代码,如果他的行为在一 ...

  8. 实现mypwd和mybash

    一.pwd 1.学习pwd命令 man pwd查看pwd功能 可以得知pwd功能是打印当前目录 2.研究pwd实现需要的系统调用(man -k; grep),写出伪代码 (1)man -k direc ...

  9. 实现mybash

    任务内容 1.使用fork,exec,wait实现mybash 查找资料: fork函数 通过fork()系统调用我们可以创建一个和当前进程印象一样的新进程.我们通常将新进程称为子进程,而当前进程称为 ...

随机推荐

  1. SSM-网站后台管理系统制作(4)---Ajax前后端交互

    前提:Ajax本身就为前后端交互服务的,实现功能:用户输入信息,实时判断用户的情况,这也是现在登录界面普遍流行的做法.前端js通过注释识别Controller层,该层查询返回,和之前Google验证码 ...

  2. 关于redis集群的问题no reachable node in cluster

    重新启动redis集群时启动失败 n context with path [] threw exception [Request processing failed; nested exception ...

  3. org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'null' to required type 'double' for property 'band'; nested exception is org.springframework.core.convert.Con

    本文为博主原创,未经允许不得转载: 先将异常粘贴出来: 20:37:26,909 ERROR [com.suning.fucdn.controller.ProductDataStaticsContro ...

  4. ETCD集群安装实验

    目录 [1.下载二进制程序] [2.安装etcd集群] [3.查询集群状态] [4.存入读取数据] [5.注意事项] [6.参考链接] 简介:     Etcd的官网文档及其在GitHub上的文档,已 ...

  5. 清理SuperMap三维缓存

    一.iclient三维插件浏览器端缓存 方法1:遍历users子文件夹,发现指定目录有supermap,即删除 @echo offtitle 清理三维缓存@echo 开始清理三维缓存...for /f ...

  6. 无头浏览器phantomJS

    selenium: 有头浏览器的代表(selenium+python也可实现静默运行 引入python的一个包,包叫:虚拟屏幕pyvirtualdisplay) PhantomJS : 无头浏览器的代 ...

  7. spring-data-redis HashOperations

    spring-data-redis HashOperations /** * 从散列中删除给定的多个元素 * @param key 不能为null 散列的名称 * @param hashKeys 需要 ...

  8. Practical Node.js (2018版) 第8章:Building Node.js REST API Servers

    Building Node.js REST API Servers with Express.js and Hapi Modern-day web developers use an architec ...

  9. Bilinear CNN与 Randomly Wired Neural Network

    最近主要学习了两篇论文以及相关的代码. 1.Bilinear CNN 这篇论文主要是在细粒度分类上应用的,在全连接层之前,在所有的卷积计算完成之后,进行的Bilinear计算,关键的代码如下: def ...

  10. Matlab:五点差分方法求解椭圆方程非导数边值问题

    差分格式脚本文件: tic; clear clc M=32;%x的步数 N=16;%y的步数 h1=1/M;%x的步长 h2=1/N;%y的步长 x=0:h1:1; y=0:h2:1; u=zeros ...