Linux——简单的Shell程序

文章目录
- 一、Shell程序思路
- 二、Shell代码展示
一、Shell程序思路
用下图的时间轴来表示事件的发生次序。其中时间从左向右。shell由标识为sh的方块代表,它随着时间的流逝从左向右移动。shell从用户读入字符串"ls"。shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束。

然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。
- 获取命令行
- 解析命令行
- 建立一个子进程(fork)
- 替换子进程(execvp)
- 父进程等待子进程退出(wait)
根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。
二、Shell代码展示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 1024
#define SIZE 64
#define SEP " "
//#define Debug 1char cwd[1024];
char enval[1024]; // for test
int lastcode = 0;char *homepath()
{char *home = getenv("HOME");if(home) return home;else return (char*)".";
}const char *getUsername()
{const char *name = getenv("USER");if(name) return name;else return "none";
}
const char *getHostname()
{const char *hostname = getenv("HOSTNAME");if(hostname) return hostname;else return "none";
}
const char *getCwd()
{const char *cwd = getenv("PWD");if(cwd) return cwd;else return "none";
}
int getUserCommand(char *command, int num)
{printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd());char *r = fgets(command, num, stdin); // 最终你还是会输入\nif(r == NULL) return -1;// "abcd\n" "\n"command[strlen(command) - 1] = '\0'; // 有没有可能越界?不会return strlen(command);
}void commandSplit(char *in, char *out[])
{int argc = 0;out[argc++] = strtok(in, SEP);while( out[argc++] = strtok(NULL, SEP));#ifdef Debugfor(int i = 0; out[i]; i++){printf("%d:%s\n", i, out[i]);}
#endif
}int execute(char *argv[])
{pid_t id = fork();if(id < 0) return -1;else if(id == 0) //child{// exec commandexecvp(argv[0], argv); // cd ..exit(1);}else // father{int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){lastcode = WEXITSTATUS(status);}}return 0;
}void cd(const char *path)
{chdir(path);char tmp[1024];getcwd(tmp, sizeof(tmp));sprintf(cwd, "PWD=%s", tmp); // bugputenv(cwd);
}// 什么叫做内键命令: 内建命令就是bash自己执行的,类似于自己内部的一个函数!
// 1->yes, 0->no, -1->err
int doBuildin(char *argv[])
{if(strcmp(argv[0], "cd") == 0){char *path = NULL;if(argv[1] == NULL) path=homepath();else path = argv[1];cd(path);return 1;}else if(strcmp(argv[0], "export") == 0){if(argv[1] == NULL) return 1;strcpy(enval, argv[1]);putenv(enval); // ???return 1;}else if(strcmp(argv[0], "echo") == 0){if(argv[1] == NULL){printf("\n");return 1;}if(*(argv[1]) == '$' && strlen(argv[1]) > 1){ char *val = argv[1]+1; // $PATH $?if(strcmp(val, "?") == 0){printf("%d\n", lastcode);lastcode = 0;}else{const char *enval = getenv(val);if(enval) printf("%s\n", enval);else printf("\n");}return 1;}else {printf("%s\n", argv[1]);return 1;}}else if(0){}return 0;
}int main()
{while(1){char usercommand[NUM];char *argv[SIZE];// 1. 打印提示符&&获取用户命令字符串获取成功int n = getUserCommand(usercommand, sizeof(usercommand));if(n <= 0) continue;// 2. 分割字符串// "ls -a -l" -> "ls" "-a" "-l"commandSplit(usercommand, argv);// 3. check build-in commandn = doBuildin(argv);if(n) continue;// 4. 执行对应的命令execute(argv);}
}
相关文章:
Linux——简单的Shell程序
📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、Shell程序思路二、Shell代码展示 一、Shell程序思路 用下图的时间轴来表示事件的发生次序…...
计算机网络-网络互联与互联网(一)
1.常用网络互联设备: 1层物理层:中继器、集线器2层链路层:网桥、交换机3层网络层:路由器、三层交换机4层以上高层:网关 2.网络互联设备: 中继器Repeater、集线器Hub(又叫多端口中继器…...
Android 解决后台服务麦克风无法录音问题
Android 解决后台无法录音问题 问题分析问题来源解决方案1. 修改清单文件:`AndroidManifest.xml`2. 修改启动服务方式3. 服务启动时创建前台通知并且指定前台服务类型参考文档最后我还有一句话要说我用心为你考虑黄浦江的事情,你心里想的却只有苏州河的勾当 问题分析 安卓9.…...
【计网】TCP的三次握手四次挥手
🍎个人博客:个人主页 🏆个人专栏:JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 三次握手(Connection Establishment) 四次挥手(Connection Termination) 结语 我…...
android pdf框架-4,分析vudroid源码2
继续分析源码 阅读器的入口 MainBrowserActivity,这个是主ui,由于代码较旧,所以没有处理sdcard的权限. 一般阅读器申请整个卡的读写. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {if (!Environment.isExternalStorageManager()) {Intent intent = new Intent…...
[算法沉淀记录] 排序算法 —— 希尔排序
排序算法 —— 希尔排序 算法介绍 希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。希尔排序的基本思想是将待排序的序列划分成若干个子序列,分别进行插入排序,待整个序列中的记录基本有…...
conda 进入虚拟环境命令报错
问题描述 conda-script.py: error: argument COMMAND: invalid choice: activate 解决方案: 在终端命令先执行 conda init,重置conda环境。然后退出终端,重新进入终端即可conda activate env了。...
域名 SSL 证书信息解析 API 数据接口
域名 SSL 证书信息解析 API 数据接口 网络工具,提供域名 SSL 证书信息解析,多信息查询,毫秒级响应。 1. 产品功能 提供域名 SSL 证书信息解析;最完整 SSL 属性信息解析;支持多种元素信息抽取,包括主题的可…...
学习JAVA的第二天(基础)
目录 基本概念 关键字 class关键字 字面量 练习 变量 定义格式 变量使用 数据类型 基本数据类型 标识符 命名规则 键盘录入 1.导包 2.创建对象 3.接受数据 运算符 算术运算符 练习 隐式转换(自动类型提升) 强制转换 自增自减运算符 …...
代码随想录算法训练营第二十七天|93.复原IP地址、78.子集、90.子集II
93.复原IP地址 刷题https://leetcode.cn/problems/restore-ip-addresses/description/文章讲解https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html视频讲解https://www.bilibili.com/video/BV1XP4y1U73i/?vd_sourceaf4853e80f89e28094a5fe1e220d9…...
【蓝桥备赛】字串简写
字串简写 数据范围 字符串的长度为5*10的五次方,on方时间复杂度会很大。 才用动态规划的思想,dp[i]以i开头的的可能性,因为长度必须大于等于k,当i小于k的时候,如果等于第一个字符,s1时,dp[…...
nios ii开发随笔
错误一: d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_64-mingw32/bin/../lib/gcc/nios2-elf/5.3.0/../../../../../H-x86_64-mingw32/nios2-elf/bin/ld.exe: test.elf section .text will not fit in region ram_oc_xzs d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_6…...
SpringBoot项目嵌入RabbitMQ
在Spring Boot中嵌入RabbitMQ可以通过添加相应的依赖来完成。首先需要在pom.xml文件中引入spring-boot-starter-amqp依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</a…...
提升网络质量:UDPspeeder 实现网络优化与提速
提升网络质量:UDPspeeder 实现网络优化与提速 背景与意义原理与功能使用方法未来展望相关链接服务 在当今高度互联的网络环境下,网络质量的优化和提速对于用户体验至关重要。针对高延迟和丢包率较高的网络链路,UDPspeeder 提供了一种前向纠错…...
为什么前端开发变得越来越复杂了?这可能是我们的错
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello,大家好,我是 Sunday。 最近有很多同学来问我:“Sunday 老师,前端学起…...
VR系统的开发流程
虚拟现实(Virtual Reality,VR)系统是一种通过计算机技术模拟出的具有三维视角和交互性的虚拟环境,使用户能够沉浸在其中并与虚拟环境进行交互。这种技术通常利用头戴式显示器和手柄等设备,使用户能够感觉到仿佛身临其境…...
前端输入框校验限制不能输入中文
一般我们在做表单的时候都会有表单校验,通常都是用element提供的表单验证的功能,只需要通过 rules 属性传入约定的验证规则,如下面这样 rules: {userName: [{validator: checkUsername,trigger: "blur",},{ validator: this.checkData, trigge…...
强大的文本绘图——PlantUML
PlantUML是一款开源工具,它允许用户通过简单的文本描述来创建UML图(统一建模语言图)。这种方法可以快速地绘制类图、用例图、序列图、状态图、活动图、组件图和部署图等UML图表。PlantUML使用一种领域特定语言(DSL)&am…...
ES相关问题
在Elasticsearch(ES)集群中,节点根据其配置和角色可以分为以下几种主要类型: Master Node(主节点): 主节点负责管理整个集群的元数据,如索引的创建、删除、分片分配等。它维护着集群…...
基于Linux直接安装的Nginx版本升级方法
引言 随着版本的迭代和漏洞的发现,Nginx作为一款软件避免不了打补丁的命运。 以下基于Linux直接安装的Nginx版本升级。 以下操作均在本地虚拟机中操作验证,请验证后再线上操作。基于centos7测试。 前置资源 获取nginx的最新源码版本网址:…...
告别重复配置,用快马生成可共享的virtualbox开发环境模板提升团队效率
在团队协作开发中,最让人头疼的莫过于每个成员都要重复配置相同的开发环境。尤其是使用VirtualBox这类虚拟机时,从安装系统到配置依赖,往往要耗费数小时。最近我发现了一个能大幅提升效率的方法——通过InsCode(快马)平台生成可共享的Virtual…...
从OBS源码看WASAPI实战:Windows音频采集的‘静音循环’修复与高精度时间戳处理
从OBS源码剖析WASAPI音频采集:静音循环修复与高精度时间戳的工程实践 在直播软件OBS的音频处理模块中,WASAPI接口的高效运用直接决定了音画同步质量与系统资源占用率。本文将深入OBS源码,揭示其解决Windows音频采集两大核心难题的技术方案&am…...
基于FPGA的智能车牌识别系统Verilog代码详解:含OV5640图像采集与HDMI显示功能...
基于FPGA的车牌识别系统verilog代码,包含verilog仿真代码,matlab仿真 OV5640采集图像,HDMI显示图像,车牌字符显示在车牌左上角,并且把车牌用红框框起。 正点原子达芬奇或者达芬奇pro都可以直接使用,fpga芯片…...
HDLC(高级数据链路控制):从帧结构解析到C语言模拟实现
1. HDLC协议基础:从比特流到可靠传输 第一次接触HDLC协议时,我盯着那串01111110的标志位发了半天呆——这不就是个简单的比特序列吗?怎么就能成为整个协议的基础?后来在调试卫星通信模块时才发现,正是这个看似简单的设…...
LAV Filters:解码Windows媒体播放困境的开源解决方案
LAV Filters:解码Windows媒体播放困境的开源解决方案 【免费下载链接】LAVFilters LAV Filters - Open-Source DirectShow Media Splitter and Decoders 项目地址: https://gitcode.com/gh_mirrors/la/LAVFilters 如何突破Windows媒体播放的格式壁垒 在2010…...
NOJ编程竞赛中的五大常见错误类型及高效调试技巧
1. NOJ编程竞赛错误类型全景解析 第一次参加NOJ在线编程竞赛时,看到满屏的WA、CE、RE、TE错误提示,我整个人都是懵的。直到后来在实战中踩过无数坑,才发现这些错误其实都有规律可循。最常见的五大错误类型就像编程路上的五个拦路虎࿰…...
中兴B863AV3.2-M/B863AV3.1-M2_S905L3A_通刷_优化开机速度_指示灯绿色
中兴B863AV3.2-M/B863AV3.1-M2_S905L3A_通刷_优化开机速度_指示灯绿色线刷方法:1、准备好一根双公头USB线刷刷机线,长度30-50CM长度最佳,同时准备一台电脑;2、电脑上安装好刷机工具Amlogic USB Burning Tool 软件 →打…...
别再只用id=0了!手把手教你用Simulink实现PMSM的MTPA控制(附模型下载)
从id0到MTPA:永磁同步电机高效控制策略的Simulink实战指南 在电机控制领域,永磁同步电机(PMSM)因其高效率、高功率密度等优势,已成为工业驱动和电动汽车的主流选择。然而,许多工程师仍停留在基础的id0控制策略上,未能充…...
效率提升秘籍:用快马平台快速生成魔鬼面具试戴应用代码骨架
效率提升秘籍:用快马平台快速生成魔鬼面具试戴应用代码骨架 最近在做一个有趣的个人项目——魔鬼面具在线试戴应用。作为一个前端开发者,我深知从零开始搭建这种交互式应用需要花费不少时间在基础框架上。幸运的是,我发现了InsCode(快马)平台…...
Linux 0.11内核调试实战:手把手教你用Bochs+GDB定位第一次页故障(附完整答案)
Linux 0.11内核调试实战:从页故障到内存管理的深度探索 当你第一次在Linux 0.11内核实验中遇到页故障时,那种既兴奋又困惑的感觉可能还记忆犹新。作为操作系统学习者,理解页故障不仅是掌握内存管理的关键,更是通往内核深处的一扇门…...
