关于一个简单的shell的实现
2013-09-23 14:12
706 查看
题目是操作系统书上的,很无聊,就做了做!
做的时候遇到了一些问题,查了一些资料,现在集中展现一下。
1.关于exec族
execvp
表头文件:
#include<unistd.h>
定义函数:
int execvp(const char *file ,char * const argv []);
函数说明:
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
execl
表头文件:
Windows下头文件:#include <process.h>
Linux下头文件:#include <unistd.h>
函数定义:
int execl(const char *path, const char *arg, ...);
函数说明:
execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针所,指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]... 最后一个参数须用空指针NULL作结束。
返回值 :
成功则不返回值, 失败返回-1, 失败原因存于errno中,可通过perror()打印。
execle
表头文件:
#include<unistd.h>
定义函数:
int execle(const char * path,const char * arg,....,char *const envp[]);
函数说明:
execl()用来执行参数path字符串所代表的文件路径,并为新程序复制最后一个参数所指示的环境变量。接下来的参数代表执行该文件时传递过去的argv(0)、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
execve
定义函数:
int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
函数说明:
execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
2.关于为什么要创建子进程运行输入命令的原因!
先看下面一段代码:
如果我们输入 ls -l的话,会列出该目录的文件夹,但是就结束了,主程序的“扑街!”并未有输出!原因在于:execvp函数,execvp如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。由于执行成功了,这个进程就结束了,也代表这个程序也完了,所以它不会返回至主程序,这就是要创建子进程的原因,子进程用于执行命令,父进程用于返回!
下面是简单shell的代码:
做的时候遇到了一些问题,查了一些资料,现在集中展现一下。
1.关于exec族
execvp
表头文件:
#include<unistd.h>
定义函数:
int execvp(const char *file ,char * const argv []);
函数说明:
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
execl
表头文件:
Windows下头文件:#include <process.h>
Linux下头文件:#include <unistd.h>
函数定义:
int execl(const char *path, const char *arg, ...);
函数说明:
execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针所,指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]... 最后一个参数须用空指针NULL作结束。
返回值 :
成功则不返回值, 失败返回-1, 失败原因存于errno中,可通过perror()打印。
execle
表头文件:
#include<unistd.h>
定义函数:
int execle(const char * path,const char * arg,....,char *const envp[]);
函数说明:
execl()用来执行参数path字符串所代表的文件路径,并为新程序复制最后一个参数所指示的环境变量。接下来的参数代表执行该文件时传递过去的argv(0)、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
execve
定义函数:
int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
函数说明:
execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。
返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
2.关于为什么要创建子进程运行输入命令的原因!
先看下面一段代码:
#include <stdio.h> #include <unistd.h> #include <wait.h> #define MAXLINE 80 void setup (char inputBuffer[], char *argv[]) { int i, j; char *p; i = 0; for (p = inputBuffer; ;p++)/*将字符命令一段一段拆分开来,如输入ls -l,则argv[0]= "ls",argv[1]="-l",argv[2]=NULL*/ { argv[i++] = p; while (*p != ' ' && *p != '\0') p++; if (*p == '\0') { break; } *p = '\0'; } argv[i] = NULL;/*最后一个参数须用空指针NULL作结束*/ execvp (argv[0], argv);/*执行命令,argv[0]放着执行的命令,其余的argv放着参数*/ } int main() { char inputBuffer[MAXLINE]; char *argv[MAXLINE / 2 - 1]; while (1) { printf ("COMMAND->"); gets (inputBuffer);/*输入命令*/ setup (inputBuffer, argv); printf ("扑街!"); } return 0; }
如果我们输入 ls -l的话,会列出该目录的文件夹,但是就结束了,主程序的“扑街!”并未有输出!原因在于:execvp函数,execvp如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。由于执行成功了,这个进程就结束了,也代表这个程序也完了,所以它不会返回至主程序,这就是要创建子进程的原因,子进程用于执行命令,父进程用于返回!
下面是简单shell的代码:
#include <stdio.h> #include <unistd.h> //#define SIZE 20 #define MAXLINE 80 char *p; void setup (char inputBuffer[], char *argv[]) { int i, j; i = 0; for (p = inputBuffer; ;p++)/*一个一个地将输入字符分开*/ { argv[i++] = p; while (*p != ' ' && *p != '\0') p++; if (*p == '\0') { break; } *p = '\0'; } argv[i] = NULL; pid_t pid pid = fork();/*新建一个子进程*/ if (pid == 0)/*对于子进程,执行输入的命令*/ { execvp (argv[0], argv); printf ("command not found\n");/*如果execvp执行失败的话,会返回-1,也就是这句话会被执行*/ } else if( pid > 0 )/*对于父进程,等待*/ { wait(NULL);/*父进程等待子进程执行完*/ } else /*否则的话,就出错了*/ { printf ("fork error\n"); } } int main() { char inputBuffer[MAXLINE]; char *argv[MAXLINE / 2 - 1]; while (1) { printf ("COMMAND->"); gets (inputBuffer); /*关于scanf和gets,scanf对于输入的字符遇到空格或回车就结束了,而gets对于输入的空格也接受*/ setup (inputBuffer, argv); } return 0; }
相关文章推荐
- 一个关于多线程的简单例子(两种实现方法)
- 关于java通信的一个简单聊天系统的实现
- 关于java通信的一个简单聊天系统的实现
- 一个简单地Shell-like 的实现
- 关于java通信的一个简单聊天系统的实现
- 操作系统上机——实现一个简单的shell
- 关于一个简单的python上传到linux服务器再经过shell脚本ftp传输的问题
- 实现一个简单shell(支持重定向)
- 【微信支付】分享一个失败的案例 跨域405(Method Not Allowed)问题 关于IM的一些思考与实践 基于WebSocketSharp 的IM 简单实现 【css3】旋转倒计时 【Html5】-- 塔台管制 H5情景意识 --飞机 谈谈转行
- 一个简单的shell脚本-----实现虚拟机实验环境的简单配置
- Linux.实现一个简单的shell
- Linux编程实现一个简单的Shell
- 一个简单的wifi开关shell脚本实现
- Clojure:在REPL上实现一个简单的shell(二)
- 【Linux】实现一个简单的shell
- shell实现一个简单进度条
- Linux下实现一个简单进度条和shell脚本实现彩色进度条
- shell实现一个简单的计算器功能小脚本
- 问题:关于贴友一个用js传递value默认值的简单实现
- 用Qt实现一个简单的shell (Qt5+V8)