2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现
要求:
- 使用fork,exec,wait实现mybash
- 写出伪代码,产品代码和测试代码
- 发表知识理解,实现过程和问题解决的博客(包含代码托管链接)
知识基础:
1.shell
shell命令分为 内建命令 & 外部命令
内建命令(builtin command) 是shell解释程序内建的,由shell直接执行,不需要派生新的进程。
外部命令分为两种: 二进制代码 或 shell脚本。shell执行外部命令时,会创建一个新的进程来执行命令。默认shell将等待直到该进程结束。
常见的外部命令:
grep more cat mkdir rmdir ls sort ftp telnet ssh ps `
2.fork()
- fork()用来创建一个子进程,该子进程是执行该函数的父进程的一个复制的映像.
- 注意:fork()函数有一个特点是一次调用返回两个值;
如果返回值为0,则是子进程;如果返回值大于0,则是父进程(此时返回值就是子进程的PID);(如果返回值为-1,则创建子进程失败).
1.用曼命令查找系统内可调用的具有创建新进程的函数:
2.用man fork 查看函数要用的头文件以及其他用法:
3.编写代码验证函数基本功能:
pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
}
else{
if(fork==0)
printf(" ID childs: %d\n", getpid());
else
printf(" ID parent : %d\n", getpid() );
}
3.exec()
- 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
- 注意:exec函数只有出错的返回值而没有成功的返回值。
用 man -k execute|grep 3查看C中用于执行进程的函数,有哪些:
用man命令查看这些函数有什么不同:在[exec函数用法总结]中有非常详细的介绍(http://blog.csdn.net/zjwson/article/details/53337212)
3.验证exce()的功能:
char *const argv[] ={"hello", NULL};
execv("hello", argv);
printf("123456789\n");
return 0;
//调用之后,不再显示printf中的内容,直接执行“hello”。
4.wait()
- wait系统调用会使父进程暂停执行,直到它的等待的子进程结束为止。也就是说wait是阻塞的。
- wait可以返回两个信息,直接返回子进程的PID,还有status(注意这个值不是在子进程中调用exit函数中的退出码,下面有专门的宏使用该status)。用man命令查看其头文件和用法,用代码验证如下:
pr=wait(NULL);
printf("child ID : %d \n",pr);
//wait成功后,接收到子进程的ID
5.Mybash()
代码托管
伪代码:
1.定义命令数组,读入用户输入的指令;
2.定义一个结束条件,满足条件结束;否则调用wait()保证在未输入结束命令前,一直提示输入commond;
3.调用fork函数生成一个子进程;
4.判断fork返回值pid是否为零,如果为零调用execlp函数;如果不为零,结束;
产品代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
int main() {
char commond[50];//定义命令数组
int pid;
int ret;
while (1) {//保证循环不断输入命令
printf("commond:");
scanf("%s", commond);
if (strcmp(commond, "exit") == 0)//结束标志
exit(0);
else {
pid = fork();
if (pid == -1) {//创建进程失败,退出
printf("error ocurred!");
exit(0);
} else if (pid == 0) {//创建成功,读入命令并执行
ret= execlp(commond, commond, NULL);
if (ret == -1) {//执行失败返回-1,退出,成功没有返回值
exit(0);
}
} else {
wait(NULL);//等待子程序终止,防止子程序成为僵尸程序
}
}
}
return 0;
}