linux系统编程综合练习-实现一个小型的shell程序(四)
#include "execute.h" #include "def.h" #include "externs.h" #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <linux/limits.h> #include <fcntl.h>void forkexec(int i){pid_t pid;pid = fork();if(pid == -1) {/* 创建进程失败了 */ERR_EXIT("fork");}if(pid > 0) {/* 父进程 */if (backgnd == 1)printf("%d\n", pid);lastpid = pid;} else if(pid == 0) {/* 子进程 *//* 表示将第一条简单命令的infd重定向至/dev/null,其中cmd[i].infd == 0只有可能是第一条简单命令 *//* 当第一条命令试图从标准输入获取数据的时候立既返回EOF */if(cmd[i].infd == 0 && backgnd == 1){//屏蔽后台作业,因为没有实现作业控制cmd[i].infd = open("/dev/null", O_RDONLY);}/* 将第一个简单命令进程作为进程组组长 */if(i == 0){setpgid(0, 0);}if(cmd[i].infd != 0){//说明该命令的输入是指向管道的读端close(0);dup(cmd[i].infd);}if(cmd[i].outfd != 1){//说明该命令的输出指向的是管道的写端close(1);dup(cmd[i].outfd);}/* 关闭3以上的所有文件描述符 *//*int i;for(i=3; i<OPEN_MAX; ++i){close(i);}*//*前台作业能够接收SIGINT,SIGQUIT信号,这两个信号就要恢复成默认操作*/if(backgnd == 0){//非后台作业 signal(SIGINT, SIG_DFL);signal(SIGQUIT, SIG_DFL);}/* 开始替换进程 */execvp(cmd[i].args[0], cmd[i].args);/* 如果执行到这句,则证明替换失败了 */exit(EXIT_FAILURE);} }int execute_disk_command(void){/* ls | grep init | wc -w */if(cmd_count == 0) {return 0;}if(infile[0] != '\0'){cmd[0].infd = open(infile, O_RDONLY);}if(outfile[0] != '\0'){if(append)//说明是以追加的方式cmd[cmd_count-1].outfd = open(outfile, O_WRONLY | O_CREAT | O_APPEND, 0666);else cmd[cmd_count-1].outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);}/* 因为后台作业不会调用wait等待子进程退出,为避免僵尸进程,可以忽略SIGCHLD信号 */if(backgnd == 1){signal(SIGCHLD, SIG_IGN);}else{signal(SIGCHLD, SIG_DFL);}int i;/* 管道描述符 */int fds[2];int fd;for(i=0; i<cmd_count; ++i){/* 如果不是最后一条命令,则需要创建管道 */if(i < cmd_count-1){pipe(fds);/* 第一条命令的输出不再是标准输出,而是管道的写端 */cmd[i].outfd = fds[1];/* 第二条命令的输入不再是标准输入,而是管道的读端 */cmd[i+1].infd = fds[0];}/* 创建一个进程,并且替换成系统命令 */forkexec(i);if((fd = cmd[i].infd) != 0)close(fd);if((fd = cmd[i].outfd) != 1)close(fd);}if(backgnd == 0){//如果是非后台作业while(wait(NULL) != lastpid); } }
将其forkexec函数也抽取到execute.c文件中,下面来进行编译一下:
另外在编译成,需要修改一下Makefile:
#include "builtin.h" #include "parse.h" #include "externs.h" #include <stdlib.h> #include <stdio.h>typedef void (*CMD_HANDLER)(void);typedef struct builtin_cmd {char *name;CMD_HANDLER handler;} BUILTIN_CMD;void do_exit(void); void do_cd(void); void do_type(void);BUILTIN_CMD builtins[] = {{"exit", do_exit},{"cd", do_cd},{"type", do_type},{NULL, NULL} };/** 内部命令解析* 返回1表示为内部命令,0表示不是内部命令*/ int builtin(void) {/*if (check("exit"))do_exit();else if (check("cd"))do_cd();elsereturn 0;return 1;*/int i = 0;int found = 0;while (builtins[i].name != NULL){if (check(builtins[i].name)){builtins[i].handler();found = 1;break;}i++;}return found; }void do_exit(void) {printf("exit\n");exit(EXIT_SUCCESS); }void do_cd(void) {printf("do_cd ... \n"); }void do_type(void) {printf("do_type ... \n"); }
编译运行:
转载于:https://www.cnblogs.com/webor2006/p/3888463.html
linux系统编程综合练习-实现一个小型的shell程序(四)相关推荐
- Linux系统编程30:进程信号之产生信号的四种方式(Core Dump,kill,raise)
文章目录 (1)通过按键产生信号-Core Dump (2)调用系统函数向进程发送信号 A:kill B:raise C:abort (3)由软件条件产生信号 (4)硬件异常产生信号 总结: 为了方便 ...
- linux系统发送信号的系统调用是,linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction...
信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...
- Linux系统编程(一)
Linux系统编程(一) 一.进程和程序 二.内存布局 内核空间 用户空间 三.进程状态 四.环境变量 五.进程共享 一.进程和程序 程序:是指编译好的二进制文件,存储在磁盘中,不占用系统资源. 进程 ...
- linux原子过程,linux系统编程:IO读写过程的原子性操作实验
所谓原子性操作指的是:内核保证某系统调用中的所有步骤(操作)作为独立操作而一次性加以执行,其间不会被其他进程或线程所中断. 举个通俗点的例子:你和女朋友OOXX的时候,突然来了个电话,势必会打断你们高 ...
- 资深程序员带你攻克 Linux 系统编程
作者简介:宇文拓,近十年 Linux C/C++ 开发经验,现就职于某创业公司,负责服务器架构与系统设计.曾就职于某通信业知名美企,负责核心网和防火墙产品研发.在 GitHub 上发布了开源项目 An ...
- 【README】Linux系统编程必读:本专栏内容提要以及系统调用接口总结
文章目录 前言 第一部分:博客知识点 (1)基础篇 Linux系统编程1:Linux中使用率最高的一些命令 Linux系统编程2:详解Linux中的权限问题 Linux系统编程3:基础篇之详解Linu ...
- Linux系统编程25:基础IO之亲自实现一个动静态库
本文接:Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系 文章目录 A:说明 B:实现静态库 C:实现动态库 A:说明 前面说过,库其实就是头文件和和.a ...
- 【Linux】Linux系统编程(入门与系统编程)(一)(环境搭建、常见指令以及权限理解)
目录 linux系统编程 : 1.推动技术进步的基本模式 2.理解操作系统的发展 Linux 背景介绍 UNIX发展的历史: Linux发展历史 开源 Linux的发行版本: a.技术角度 b.商业化 ...
- linux 可定义信号数,Linux系统编程(20)——信号基本概念
信号及信号来源 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知 ...
最新文章
- 【百度地图API】——如何用label制作简易的房产标签
- 滑动门和翻转门实现的横竖双tab标签测试页面(附源码)
- 网站社区类产品管理经验
- python学习_数据处理编程实例(一)
- 语义分割和实例分割_一文读懂语义分割与实例分割
- 嵌入式无法使用QAudioDeviceInfo类
- 接口测试---mock变量自定义变量的使用
- DOM对象转化成jQuery对象 $(参数) (能不能查到jQuery对象的所有方法)
- 2021 年 338 道架构技术面试大厂高频题汇总(附答案详解)
- Java的GUI学习三(frame)
- C++ 读取txt文件方法读取速度比较
- 2021-05-22 Android 网络性能测试工具iperf详细使用方法
- go模板引擎生成html,goweb-模板引擎
- 【gp数据库】十条实用数据库SQL优化建议
- linux新硬盘格式化,linux添加新硬盘并格式化
- js在一个指定元素前添加内容_Day036-JS
- Android程序中重启系统,Android调用系统关机与重启功能
- ajax、promise、react、缓存笔记记录
- 解决IE11兼容HTML5 设置:设置兼容性视图网站正常显示网页
- 少儿Python编程6-计算机数据结构和算法