目录
前言
一、预备知识
二、实现步骤
1.思路
2.实现
总结
前言
提示:这里可以添加本文要记录的大概内容:
学习的本质就是变现
提示:以下是本篇文章正文内容,下面案例可供参考
一、预备知识
char * fgets ( char * str, int num, FILE * stream ); // 用于获取一整行的数据
参数:
char *str
:指向用于存储读取到的数据的字符数组的指针。
int num
:指定str
指向的数组的最大长度,最多会读取num-1
个字符,以便为字符串的结尾空字符留出空间。
FILE *stream
:指向FILE
对象的指针,该对象标识了要从中读取数据的输入流。返回值:
成功返回str,失败返回NULL
注意事项
fgets 会读取字符直到遇到换行符(\n)、文件结束符(EOF)或已读取了 num-1 个字符为止。
int execvp(const char *file, char *const argv[]); // 是一个系统调用函数,用于在当前程序中执行一个新的程序
参数:
const char *file:要执行的文件的名称或路径,不包含路径则在环境变量PATH中查找
char *const argv[]:以NULL结尾的字符串数组,表示要传递给执行文件的命令行参数
返回值:
成功没有返回值,失败返回-1
注意事项:
argv[0] 通常表示命令本身(file参数指定的文件名)
char *strtok(char *str, const char *delimiters); //用于分割字符串
参数:
char *str:第一次调用指向要分割字符串的指针,在后序调用中是NULL
const char *delimiters:确定边界
int main(int argc, char* argv[], char* env[])
{
return 0;
}
参数:
int argc:保存的是当前程序运行参数的个数
char* argv[]:保存了所有运行参数--字符形式进程保存
char* env[]:保存所有环境变量地址
一个main函数保存了三个参数,这三个参数可以不在代码中显示
二、实现步骤
1.思路
目标:实现一个shell
实现思想:
1:捕捉用户的输入
2:对用户输入进行解析
3:创建子进程
3.1:对子进程进行替换,替换为对应的指令
3.2:替换失败子进程退出
4:父进程等待子进程退出--避免僵尸进程
2.实现
代码如下(示例):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int main()
{
//整个进程应当是个循环
while(1){
//捕捉用户输入
printf("[user@sxh]$ ");
fflush(stdout); //刷新标准输出文件的缓冲区
char input[1024] = {0};
fgets(input, 1023, stdin);//stdin表示从键盘中捕捉输入
input[strlen(input) -1] = '\0';//将末尾的换行替换为结尾
//对输入进行解析
char *argv[32] = {NULL};//保存了所有的运行参数
int argc = 0; //保存当前程序运行参数的个数
argv[argc] = strtok(input, " ");//分割第一个命令
while(argv[argc] != NULL){
argv[++argc] = strtok(NULL, " ");
}
//创建子进程,进行程序替换
pid_t pid = fork();
if (pid < 0){
perror("fork error");
}
else if(pid == 0){
execvp(argv[0], argv);//程序替换,其中argv[0]表示要运行的指令名称,argv指运行>的参数
perror("execvp error");
exit(-1);//退出程序
}
wait(NULL);//等待任意子进程退出
}
return 0;
}