20165322 第七周 mybash 的实现
mybash的实现
要求
- 使用fork,exec,wait实现mybash
- 写出伪代码,产品代码和测试代码
- 发表知识理解,实现过程和问题解决的博客
相关函数的作用
-
fork
- fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程不共享这些存储空间。linux将复制父进程的地址空间内容给子进程,因此,子进程由了独立的地址空间。),也就是这两个进程做完全相同的事。
- 在父进程中,fork返回新创建子进程的进程ID;
- 在子进程中,fork返回0;
- 如果出现错误,fork返回一个负值
-
exec
- exec函数族可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完后,原调用进程的内容除了进程号外,其它全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
- exec函数族可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完后,原调用进程的内容除了进程号外,其它全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
-
wait
- wait()会暂时停止现在进程的执行,直到有信号来到或子进程结束。假如在调用wait()时子进程已结束,则wait()会立即返回子进程结束状态值。
- wait()会暂时停止现在进程的执行,直到有信号来到或子进程结束。假如在调用wait()时子进程已结束,则wait()会立即返回子进程结束状态值。
伪代码
while(1)
{
输出用户信息
读取用户输入命令存入数组和文件
调用fork()函数,若返回值不为0,则调用wait()
若返回值为0,调用exec()
}
产品代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/wait.h>
#define N 100
#define order_length 128
#define order_num 64
#define empty 0
#define chars 1
void main()
{
while(1) {
struct passwd *my_info;
char path[N];
my_info = getpwuid(getuid());
getcwd(path, sizeof(path));
printf("[%s@%s]$ ", my_info->pw_name, path);//输出用户及路径
char str[N];
char a[N];
char *argv[N]={NULL};
char *envp[]={0,NULL};
int i,j = 0, flag=1;
fgets(str,N,stdin); //读取输入的命令
str[N - 1] = '\0';
if(feof(stdin))
{
printf("error");
exit(0);
}
for(i=0;str[i]!='\0'&&i<N&&j<N;i++) {
if(str[i] == ' ' || str[i] == '\n') {
flag=1;
str[i] = '\0';
}
else if(flag==1) {
argv[j++] = &str[i];
flag=0;
}
}
if(fork() != 0) wait(NULL); //调用fork()
else {
execvp(argv[0], argv);
perror("execlp error");
exit(0);
}
}
}
测试结果
测试了ls
,ls -l``tree``clear
指令,测试截图如下:
尚有一部分命令无法实现,例如“cd”等等……