首先我们得知道Linux下产生新进程的过程是--->先复制---->再替换子进程(fork + exec)
来看代码 代码中都有解释的
下面代码实现的主要功能就是内置命令cd的简单操作和exit的作用
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pwd.h>
#include <dirent.h>
char * get_cmd(char buff[],char * myargv[])
{
if(buff == NULL || myargv == NULL)
{
return NULL;
}
int i = 0;
char * s = strtok(buff," ");//对命令进行分割 例如ps -f这种
while( s!= NULL)
{
myargv[i++] = s;
s = strtok(NULL," ");
}
return myargv[0];//识别输入的命令 作出对应的举动
}
void printf_info() //这个函数的作用就是在执行mybash的时候前面那一行话
{
int id = getuid();//获取用户uid
char* s = "$";
if (id == 0)//当是管理员权限的时候 getuid()返回值是0
{
s = "#";
}
struct passwd * ptr = getpwuid(id);//根据uid返回用户真实信息
if (ptr == NULL) //获取失败
{
printf("$");
fflush(stdout);
return;
}
char hostname[64] = {0};
if(gethostname(hostname,64) == -1)
{
printf("$");
fflush(stdout);
return;
}
char pwd_buff[128] = {0};
if(getcwd(pwd_buff,128) == NULL)
{
printf("$");
fflush(stdout);
return;
}
printf("%s@%s %s:%s",ptr->pw_name,hostname,pwd_buff,s);
fflush(stdout);
}
int main()
{
while(1)
{
char buff[128] = {0}; //存放键盘输入命令和参数
printf_info();
fgets(buff,128,stdin);//fgets会把\n也给读进去
buff[strlen(buff)-1] = 0; //这行就是将\n这个东西给去掉
char * myargv[10] = {0};//这行相当于是命令库
char * cmd = get_cmd(buff,myargv);
if(cmd == NULL)//像原来系统的bash也是 没命令回车时会继续
{
continue;
}
else if(strcmp(cmd,"exit") == 0) //exit是内置命令 不需要产生新进程 也就不需要fork复制然后exec替换
{
break;
}
//这里说一下 内置命令和外部命令的区别 先说外部命令:需要产生一个新进程,所以就会fork+exec
//内置命令就每这么麻烦 效率也更高 更快
else if(strcmp(cmd,"cd") == 0) //cd也是内置命令
{
if (myargv[1] == NULL) //单纯的输入cd
{
continue;
}
if (chdir(myargv[1]) == -1)//chdir错误之后的返回值就是-1 成功是0
{
printf("cd err");
}
continue;
}
else //到这块else的话 就是外部命令了 需要fork+exec产生新进程
{
pid_t pid = fork();
if(pid == -1)
{
printf("fork err \n");
continue;
}
if(pid == 0)//这块就是运行mybash需要先对进程进行复制fork 然后exec进行替换 因为这是我们自己写的程序 需要产生新进程
{
execvp(cmd,myargv);
printf("execvp err\n");//替换成功的话 不会执行到这一行的
exit(0);
}
wait(NULL);//将父进程阻塞住 并且也可以让子进程变成僵死进程
}
}
}
在实现外部命令的时候是系统直接调用/usr/bin下的
也就是说在bash中执行外部命令的话 是和bash没什么关系的 都是从系统中调用的
下面再来自己编写个程序实现两个外部命令
pwd的程序实现:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
char buff[128] = {0};
if (getcwd(buff,128) != NULL)
{
printf("%s \n",buff);
}
return 0;
}
ls的程序实现
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
int main()
{
char buff[128] = {0};
if (getcwd(buff,128) == NULL)
{
return 0;
}
DIR * p = opendir(buff);
if ( p == NULL)
{
return 0;
}
struct dirent * s = NULL;
while((s = readdir(p)) != NULL)
{
if(strncmp(s->d_name,".",1)==0)
{
continue;
}
printf("%s \n",s->d_name);
}
closedir(p);
return 0;
}