linux系统编程综合练习-实现一个小型的shell程序(一)
之前已经花了不少篇幅学习了linux系统编程的很多知识点:文件与io、进程、信号、管道,而零散的知识点,怎么能够综合的串接起来是学习的一个很重要的目的,当然最好的方式就是用所学的知识点做一个项目了,所以接下来会实现一个小型的迷你shell程序,跟缩减版的系统shell程序,不要看着项目很小,但是五脏俱全,先来看一下我们要实现的功能:








如exit会退出程序等。

另外还能捕捉一些信号,如:ctrl+c,也能忽略一些信号,如:ctrl+\,禁止退出自己的程序,这里就不演示了。
下面就来从零开始一步步实现我们自己的shell程序,首先进行模块的划分:
-------main.c //这个是一个主控程序
-------parse.c、parse.h //这个主要是用来进行shell命令的解析的

再编写一个Makefile,由于项目中会由多个.c文件构成,所以很有必要进行整体编译,关于Makefile的写法,可以参考博文:http://www.cnblogs.com/webor2006/p/3789589.html

这个Makefile的编写是比较简单的,这里就不详述了,里面内容如下:


这样,总体的项目编译环境就已经搭建好了,另外说明一下实现的思路:先搭建好一个整体的框架,然后于对其每个模块进行一一细化,最终完善整个功能,所有功能的实现都会按这个思路来,而且很重要的一条就是:步步为营,也就是当写完一段代码后,就立马进行编译运行,来确保每小段代码都成功,这样的话,一点点功能进行拆分,最终实现一个项目,所以接下来,先要实现一个简单的框架功能:





















































#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "parse.h"
#include "externs.h"
#include "init.h" /*
* shell主循环
*/
void shell_loop(void){
while(){
printf("[myshell]$ ");
fflush(stdout);
/* 初始化环境 */
init();
if(read_command() == -)
break;
parse_command();
execute_command();
}
printf("\nexit\n");
} /*
* 读取命令
* 成功返回0,失败或者读取到文件结束符(EOF)返回-1
*/
int read_command(void){
if(fgets(cmdline,MAXLINE,stdin) == NULL){
return -;
}
return ;
} /*
* 解析命令
* 成功返回解析到的命令个数,失败返回-1
*/
int parse_command(void){
char *cp = cmdline;
char *avp = avline; int i = ;
while(*cp != '\0'){
/** 去除左空格 **/
while(*cp == ' ' || *cp == '\t')
cp++;
/* 如果到了行尾,跳出循环 */
if(*cp == '\0' || *cp == '\n')
break;
cmd.args[i] = avp; while (*cp != '\0'
&& *cp != ' '
&& *cp != '\t'
&& *cp != '\n')
*avp++ = *cp++;
//printf("[%s]\n",cmd.args[i]);
*avp++ = '\0';
i++;
} return ;
} /*
* 执行命令
* 成功返回0,失败返回-1
*/
int execute_command(void){
pid_t pid = fork();
if(pid == -){
//进程创建失败
ERR_EXIT("fork");
}
if(pid == ) {
//子进程去执行替换函数
execvp(cmd.args[],cmd.args);
}
//父进程等待子进程的退出,这样并不会改变父进程本身的行为,所以进程就不会退出了
wait(NULL);
return ;
}
这节的最终运行效果如下:

linux系统编程综合练习-实现一个小型的shell程序(一)的更多相关文章
- linux系统编程综合练习-实现一个小型的shell程序(四)
上节中已经对后台作业进行了简单处理,基本上要实现的功能已经完了,下面回过头来,对代码进行一个调整,把写得不好的地方梳理一下,给代码加入适当的注释,这种习惯其实是比较好了,由于在开发的时候时间都比较紧, ...
- linux系统编程综合练习-实现一个小型的shell程序(三)
上节中已经实现了对普通命令的解析,包括输入重定向,输出重定向,管道,后台作业,这次就来执行已经解析好的命令,对应的函数为:execute_command(),首先对带有管道的命令进行执行: 比如:&q ...
- linux系统编程综合练习-实现一个小型的shell程序(二)
上节minishell当中,已经初步实现了一个简单命令的解析,这节来继续对更加复杂命令进行解析,包含:输入重定向的解析.管道行的解析.输出重定向的解析以及是否有后台作业的解析,如下: 下面对其进行实现 ...
- Linux系统学习笔记之 1 一个简单的shell程序
不看笔记,长时间不用自己都忘了,还是得经常看看笔记啊. 一个简单的shell程序 shell结构 1.#!指定执行脚本的shell 2.#注释行 3.命令和控制结构 创建shell程序的步骤 第一步: ...
- Linux系统编程(33)—— socket编程之TCP程序的错误处理
上一篇的例子不仅功能简单,而且简单到几乎没有什么错误处理,我们知道,系统调用不能保证每次都成功,必须进行出错处理,这样一方面可以保证程序逻辑正常,另一方面可以迅速得到故障信息. 为使错误处理的代码不影 ...
- linux系统编程之进程(一)
今天起,开始学习linux系统编程中的另一个新的知识点----进程,在学习进程之前,有很多关于进程的概念需要了解,但是,概念是很枯燥的,也是让人很容易迷糊的,所以,先抛开这些抽象的概念,以实际编码来熟 ...
- linux系统编程之管道(三)
今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题: 所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现 ...
- linux系统编程之信号(七)
今天继续学习信号,主要是学习关于时间和定时器相关的函数的使用,关于这个实际上有很多内容,这里先简要进行说明,等之后再慢慢进行相关深入,也主要是为接下来要做的一个综合linux系统编程的例子做准备,好了 ...
- Linux系统编程【2】——编写who命令
学到的知识点 通过实现who命令,学到了: 1.使用man命令寻找相关信息 2.基于文件编程 3.体会到c库函数与系统调用的不同 4.加深对缓冲技术的理解 who命令的作用 who命令的使用 在控制终 ...
随机推荐
- 说一说ORACLE的监听
1.讲在前面 本文档仅适用于如下范围:Oracle以dedicate (专有)连接模式通过TCP/IP协议连接的场景. 2.监听的作用 在谈监听的作用之前,有必要先看看监听的工作原理图: 客户端进程发 ...
- Mysql 学习整理
1 创建数据库 1.1数据库基本结构 数据库:数据库是表的集合,带有相关的数据. 表:一个表是多个字段的集合. 字段:一个字段是一列数据,由字段名和记录组成 1.2创建数据库 create datab ...
- pdflatex 插入eps图片
1. 将eps图片转成pdf或者将pdf图片转成eps,也就是说一张图片有pdf.eps两种格式.方法一: \includegraphics{pic} %不要扩展名.这样pdflatex自动调相应的p ...
- Spring MVC原理图及其重要组件
一.Spring MVC原理图: ps: springmvc的运行流程为图中数字序号 二.springmvc的重要组件: 1)前端控制器:DispatchServlet(不需要程序员开发) 接收请求, ...
- 大型web项目构建之负载均衡
日常开发和学习中经常会听到或者会看到“负载均衡”这个词汇,但是对于很多初级每天只面对增删改代码的开发人员来说,这个词汇好像离我们很遥远又很接近,很多人多多少少都有点一知半解 我结合以前在开发中遇到的场 ...
- [转帖]B树索引、位图索引和散列索引
B树索引.位图索引和散列索引 https://blog.csdn.net/huashanlunjian/article/details/84460436 索引在数据结构上可以分为三种B树索引.位图 ...
- ScheduledExecutorService调度线程池运行几次后停止某一个线程
开发中偶尔会碰到一些轮询需求,比如我碰到的和银行对接,在做完某一个业务后银行没有同步给到结果,这时候就需要查询返回结果,我们的需求是5分钟一次,查询3次,3次过后如果没有结果则T+1等银行的文件,对于 ...
- es6新特性-解构表达式、Lambda表达式、局部变量及map/reduce方法
循环内的变量在循环外可见,不合理: let定义的变量是局部变量: const修饰的是常量,不允许再次修改,类似于java中的static: 解构表达式:
- promethus监控nginx
一.摘要 promethues监控nginx可选两个exporter,通过nginx_exporter主要是获取nginx-status中的内建的指标,nginx自身提供status信息,较为简单,p ...
- Ubuntu 18.04下安装Steam顶级在线游戏平台
Ubuntu 18.04下安装Steam顶级在线游戏平台 原创: 聆听世界的鱼 Linux公社 今天 Steam是由Valve公司开发的顶级在线游戏平台,是目前全球最大的综合性数字发行平台之一.它让你 ...