2018-2019-1 20165226《信息安全系统设计基础》 bash的实现
目录
一、学习fork,exec,wait
1、fork
- 格式
//头文件#include//函数定义pid_t fork( void );
返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1函数说明:一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。
- 举例
#include#include void main(){ int i; printf("hello, %d\n",getpid()); i=2; fork(); printf("var %d in %d\n", i, getpid());}
结果:
2、exec
exec家族
只有
)int execve(const char *path, char *const argv[], char *const envp[]);
是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。书写格式:
先定义一个指针数组:
用execv调用ls:char *argv[]={“ls”,”-l”,(char *)0}
execv(“/bin/ls”,argv)
如果用execvp
execvp(“ls”,argv)
//直接写ls就可以了
3、wait
- 函数原型
#include#include pid_t wait(int *status)
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程, wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
二、实现bash
- 伪代码
while(1){ fgets(命令行输入); if(内置的shell命令) { 解释命令; } else if(可执行文件) { 新的子进程加载并运行文件; }}
- 代码
#include#include #include #include #include #include #define MAX 128void eval(char *cmdline);int parseline(char *buf, char **argv);int builtin_command(char **argv);int main(){ char cmdline[MAX]; printf("This is 20165226's bash!\n"); while(1) { printf("> "); fgets(cmdline, MAX, stdin); if(feof(stdin)) 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; }}int builtin_command(char **argv){ if(!strcmp(argv[0], "quit")) exit(0); if(!strcmp(argv[0],"&")) return 1; return 0;}int parseline(char *buf,char **argv){ char *delim; int argc; int bg; buf[strlen(buf)-1]=' '; while(*buf && (*buf == ' ')) buf++; argc=0; while( (delim = strchr(buf,' '))) { argv[argc++] = buf; *delim= '\0'; buf = delim + 1; while(*buf && (*buf == ' ')) buf++; } argv[argc] = NULL; if(argc == 0) return 1; if((bg=(*argv[argc-1] == '&')) != 0) argv[--argc] = NULL; return bg;}
- 测试代码
lsls -agit --version
- 结果
[]