实现mybash
Posted fenixren
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现mybash相关的知识,希望对你有一定的参考价值。
20165212实现mybash
要求
- 使用fork,exec,wait实现mybash
- 写出伪代码,产品代码和测试代码
- 发表知识理解,实现过程和问题解决的博客(包含代码托管链接)
学习相关知识
fork函数
查看帮助文档可以知道fork函数的头文件,函数原型,以及函数的功能等,如下图
- fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
- 一个进程调用fork()函数后,系统先给新的进程分配资源。
- fork调用一次,却能够返回两次,它可能有三种不同的返回值。
- 在父进程中,fork返回新创建子进程的进程ID;
- 在子进程中,fork返回0;
- 如果出现错误,fork返回一个负值。
我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
源代码:
#include <unistd.h> #include <stdio.h> int main () { pid_t fpid; //fpid表示fork函数返回的值 int count=0; fpid=fork(); if (fpid < 0) printf("error in fork!"); else if (fpid == 0) { printf("i am the child process, my process id is %d ",getpid()); printf("我是子进程 ");// count++; } else { printf("i am the parent process, my process id is %d ",getpid()); printf("我是父进程 "); count++; } printf("统计结果是: %d ",count); return 0; }
问题:为什么count值没有受到影响呢? 解决:因为在创建了新进程之后,所有变量都存在不同的地址中,不是共用的,所有各有各的增减变化,互不影响。
exec函数族
- exec函数族提供了一个在进程中启动另一个程序执行的方法。 - 以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。 - 可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。 - 在该函数族中使用execl、execv、execlp、execvp函数使执行码重生时,Shell进程会将所有环境变量复制给生成的新进程;而使用execle、execve时新进程不继承任何Shell进程的环境变量,而由envp[]数组自行设置环境变量。
ls源代码
#include<unistd.h> main() { char *argv[ ]={"ls", NULL}; char *envp[ ]={"PATH=/bin", NULL}; execve("/bin/ls", argv, envp); }
运行结果
wait函数 wait()会暂时停止现在进程的执行,直到有信号来到或子进程结束。假如在调用wait()时子进程已结束,则wait()会立即返回子进程结束状态值。 waitpid提供了一个 wait的非阻塞版本,有时希望取得一个子进程的状态, 但不想进程阻塞。 mybash实现 伪代码:
while(1) { 输出用户的ID,等数据; 用户输入命令; 将命令分割; 调用fork; 调用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("[%[email protected]%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] = ‘