第五周 mybash的实现

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

1. fork() 函数:

1. 一个进程,包括代码、数据和分配给进程的资源。
2. fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
3. 一个进程调用fork() 函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。
fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值; 我们可以通过fork返回的值来判断当前进程是子进程还是父进程

有如下代码:

#include <unistd.h>
#include <stdio.h>
int main(void)
{
int i=0;
printf("i son/pa ppid pid fpid/n");
//ppid指当前进程的父进程pid
//pid指当前进程的pid,
//fpid指fork返回给当前进程的值
for(i=0;i<2;i++){
pid_t fpid=fork();
if(fpid==0)
printf("%d child %4d %4d %4d/n",i,getppid(),getpid(),fpid);
else
printf("%d parent %4d %4d %4d/n",i,getppid(),getpid(),fpid);
}
return 0;
}

运行结果如下:

分析:

第一次fork后,p3224(父进程)的变量为i=0,fpid=3225(fork函数在父进程中返向子进程id)p3225(子进程)的变量为i=0,fpid=0(fork函数在子进程中返回0)

第二步创建了两个进程p3226,p3227,这两个进程执行完printf函数后就结束了,因为这两个进程无法进入第三次循环,无法fork,该执行return 0;了,其他进程也是如此。

2. exec函数:

1. fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。
2. 它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。
3. 这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。

exec函数族使用注意点:

在使用exec函数族时,一定要加上错误判断语句。因为exec很容易执行失败,其中最常见的原因有:

① 找不到文件或路径,此时errno被设置为ENOENT。

② 数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT。

③ 没有对应可执行文件的运行权限,此时errno被设置为EACCES。

在Linux中使用exec函数族主要有以下两种情况

如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生。
当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec 函数族让自己重生。

execlp.c文件如下:

#include <stdio.h>
#include <unistd.h>
int main()
{
if(fork()==0){
if(execlp("/usr/bin/env","env",NULL)<0)
{
perror("execlp error!");
return -1 ;
}
}
return 0 ;
}

执行结果如图:

由执行结果看出,execlp函数使执行码重生时继承了Shell进程的所有环境变量,其他三个不以e结尾的函数同理。

3. wait()函数:

1. wait()会暂时停止目前进程的执行, 直到有信号来到或子进程结束.
2. 如果在调用wait()时子进程已经结束, 则wait()会立即返回子进程结束状态值.
3. 子进程的结束状态值会由参数status 返回, 而子进程的进程识别码也会一快返回

4使用fork,exec,wait实现mybash:

部分代码展示,全部代码在码云里

int main()
{
char cmdline[MAX]; while(1){
printf("bsetixx@besrixx-VirtualBox:~/XINAN/mybash/$ ");
fgets(cmdline,MAX,stdin);
if(feof(stdin))
{
printf("error");
exit(0);
}
eval(cmdline);
}
} void eval(char *cmdline)
{
char *argv[MAX];
char buf[MAX];
int bg;
pid_t pid;
strcpy(buf,cmdline);
bg = parseline(buf,argv);
if(argv[0]==NULL)
return;
if(!builtin_command(argv))
{
if((pid=fork()) == 0)
{
if(execvp(argv[0],argv) < 0) {
printf("%s : Command not found.\n",argv[0]);
exit(0);
}
} if(!bg){
int status;
if(waitpid(-1,&status,0) < 0)
printf("waitfg: waitpid error!");
}
else
printf("%d %s",pid, cmdline);
return;
}
}

代码提交截图



代码提交连接

第五周 mybash的实现的更多相关文章

  1. 20155322 2017-2018-1 《信息安全系统设计》第五周 MyBash实现

    #20155322 2017-2018-1<信息安全系统设计>第五周 MyBash实现 [博客目录] 实现要求 相关知识 bash fork exec wait 相关问题 fork返回两次 ...

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

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

  3. 20155326 第五周加分题--mybash的实现

    第五周加分题--mybash的实现 题目要求 1.使用fork,exec,wait实现mybash 2.写出伪代码,产品代码和测试代码 3.发表知识理解,实现过程和问题解决的博客(包含代码托管链接) ...

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

    第五周加分题--mybash的实现 题目要求 1.使用fork,exec,wait实现mybash 2.写出伪代码,产品代码和测试代码 3.发表知识理解,实现过程和问题解决的博客(包含代码托管链接) ...

  5. 2017-2018-1 20155239 《信息安全系统设计基础》第五周学习总结+mybash的实现

    2017-2018-1 20155239 <信息安全系统设计基础>第五周学习总结+mybash的实现 mybash的实现 使用fork,exec,wait实现mybash 写出伪代码,产品 ...

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

    第五周 加分题-mybash的实现 使用fork,exec,wait实现mybash 产品代码 #include <stdio.h> #include <stdlib.h> # ...

  7. 20155308 加分题-mybash的实现(第五周)

    20155308 加分题-mybash的实现(第五周) 实验要求 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客(包含代码托管 ...

  8. 2017-2018-1 20155320 第五周 加分题-mybash的实现

    2017-2018-1 20155320 第五周 加分题-mybash的实现 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解,实现过程和问题解决的博客( ...

  9. 20145213《Java程序设计》第五周学习总结补充

    20145213<Java程序设计>第五周学习总结补充 教材学习内容总结 欠的账都是要还的!第九章的内容躲过对酒当歌的夜,躲不过四下无人的街.由于第五周贪玩,疏忽冷落了Collection ...

随机推荐

  1. redis几种加锁的实现

    1. redis加锁分类 redis能用的的加锁命令分表是INCR.SETNX.SET 2. 第一种锁命令INCR 这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执 ...

  2. BZOJ3697:采药人的路径(点分治)

    Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...

  3. Kali-linux服务的指纹识别

    为了确保有一个成功的渗透测试,必须需要知道目标系统中服务的指纹信息.服务指纹信息包括服务端口.服务名和版本等.在Kali中,可以使用Nmap和Amap工具识别指纹信息.本节将介绍使用Nmap和Amap ...

  4. ethereumjs/ethereumjs-block-3-tests

    之前可以先了解一下另一个模块,看本博客的ethereumjs/ethereumjs-common部分内容 通过tests测试文件能够帮助更好了解API的使用 ethereumjs-block/test ...

  5. PAT——1042. 字符统计

    请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过1000的字符串.字符串由ASCII码表中任意可见字符及空格组成,至少包含1个英文字母,以回车结束( ...

  6. NodeJS平台下的前后端文件共享

    一.前后端文件共享的需要背景——为什么需要共享? 项目基本JS/NodeJS全端开发,有部分代码前后端都需要用得到 有一些配置是在前后端都需要用得到的 区别其他开发平台,NodeJS平台下的前后端文件 ...

  7. Vue学习—组件的学习

    1.什么是组件? 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能 ...

  8. CABasicAnimation使用总结

    CABasicAnimation使用总结 实例化 使用方法animationWithKeyPath:对 CABasicAnimation进行实例化,并指定Layer的属性作为关键路径进行注册. //围 ...

  9. 常用 超全局数组$_server

    $_SERVER 是一个包含了诸如头信息(header).路径(path).以及脚本位置(script locations)等等信息的数组.这个数组中的项目由 Web 服务器创建.不能保证每个服务器都 ...

  10. Scala相关笔记

    一.Scala概述以及安装 1.   什么是Scala Scala 是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性.Scala 运行于 Java 平台(Java 虚拟机 ...