几十行代码轻松实现shell外壳程序(基础版)

本文介绍了如何使用C语言在Linux环境下实现一个简单的shell外壳程序。通过fork函数创建子进程,结合exec*系列函数,实现用户命令的执行。同时,文章讨论了环境变量在父子进程间的继承特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SHELL外壳的简易实现

1.什么是shell外壳?

shell外壳是连接用户和操作系统的一种中间层软件,负责将用户输入的指令经过处理后提交给操作系统。shell外壳本身也是一个进程,它最主要的职责就是创建子进程并让子进程完成某些任务,但有时shell外壳也会自己执行任务,在linux系统下shell外壳称为bash。

2.如何实现shell外壳

shell外壳的简易实现先依靠fork函数创建子进程,再利用exec*系列函数把子进程替换成某些已经存在于磁盘的可执行程序,最后利用循环实现子进程的持续创建和替换,而父进程shell则不受影响。

以下是shell外壳的模拟实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>

#define SUM 1024
#define SIZE 32
#define SEP " "

char cmd_line[SUM];
char* g_argv[SIZE];

int main()
{
  while(1)
  {
  printf("[root]");
  fflush(stdout);
  memset(cmd_line,'\0',sizeof(cmd_line));
  if(fgets(cmd_line,sizeof(cmd_line),stdin)==NULL)//从标准输入流获取字符串数据
  {
    continue;
  }
  cmd_line[strlen(cmd_line)-1]='\0';//把fgets最后输入的回车覆盖掉
  g_argv[0]=strtok(cmd_line,SEP);
  int index=1;
  if(strcmp(g_argv[0],"ls")==0)//以下是两种特殊命令,单独处理
  {
    g_argv[index++]="--color=auto";
  }
  if(strcmp(g_argv[0],"ll")==0)
  {
    g_argv[0]="ls";
    g_argv[index++]="-a";
    g_argv[index++]="-l";
    g_argv[index++]="--color=auto";
  }
  while(g_argv[index++]=strtok(NULL,SEP));//把strtok返回的多个指针存入指针数组中
  if(strcmp(g_argv[0],"cd")==0)//cd命令不能由子进程进行,否则销毁后不影响父进程,应该由父进程进行
  {
    if(g_argv[1]!=NULL)
    {
      chdir(g_argv[1]);
    }
    continue;
  }
  pid_t id=fork();
  if(id==0)
  {
    printf("指令执行中\n");
    execvp(g_argv[0],g_argv);//进程替换为已经存在的环境变量指令
    exit(-1);
  }
  int status=0;
  pid_t ret=waitpid(id,&status,0);
  printf("父进程标记\n");
  printf("exit code:%d\n",WEXITSTATUS(status));//取得子进程退出码
  }
}

总结模拟实现就是利用while循环实现循环往复执行,父进程永不退出,就像一个真正的shell一样,再利用字符数组存储输入命令,利用strtok函数分割字符串存入指针数组中,再交由子进程的exec函数取指定元素后进行替换,完成任务后子进程退出,父进程再次创建新的子进程。

附录:

为什么说环境变量是全局的,被子进程继承的?

//myproc.c
const char* const _env[1024]={"NUMBER=100","NULL"};
int main()
{
  execle("./mytmp","mytmp",NULL,_env);
  return 0;
}

//mytmp.c
int main()
{
  printf("%s",getenv("NUMBER"));
  return 0;
}

这里我们自定义的环境变量-env通过exec函数传递到子进程中,并由子进程利用getenv接收,假如这里传递的是myproc的main函数中的env参数,就可以实现环境变量在父子进程之间的传递了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值