1. 使用fork,exec,wait实现mybash 2. 写出伪代码,产品代码和测试代码 3. 发表知识理解,实现过程和问题解决的博客(包含代码托管连接)
fork()
函数:1. 一个进程,包括代码、数据和分配给进程的资源。 2. fork() 函数经过系统调用建立一个与原来进程几乎彻底相同的进程,也就是两个进程能够作彻底相同的事,但若是初始参数或者传入的变量不一样,两个进程也能够作不一样的事。 3. 一个进程调用fork() 函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。而后把原来的进程的全部值都复制到新的新进程中,只有少数值与原来的进程的值不一样。至关于克隆了一个本身。
在fork函数执行完毕后,若是建立新进程成功,则出现两个进程,一个是子进程,一个是父进程。 fork调用的一个奇妙之处就是它仅仅被调用一次,却可以返回两次,它可能有三种不一样的返回值: 1)在父进程中,fork返回新建立子进程的进程ID; 2)在子进程中,fork返回0; 3)若是出现错误,fork返回一个负值; 咱们能够经过fork返回的值来判断当前进程是子进程仍是父进程
有以下代码:git
#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;了,其余进程也是如此。bash
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文件以下:ui
#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 ; }
执行结果如图:
3d
由执行结果看出,execlp函数使执行码重生时继承了Shell进程的全部环境变量,其余三个不以e结尾的函数同理。code
wait()
函数:1. wait()会暂时中止目前进程的执行, 直到有信号来到或子进程结束. 2. 若是在调用wait()时子进程已经结束, 则wait()会当即返回子进程结束状态值. 3. 子进程的结束状态值会由参数status 返回, 而子进程的进程识别码也会一快返回
部分代码展现,所有代码在码云里blog
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; } }
代码提交截图
代码提交链接继承