简单shell
目录
预备知识
fork
进程等待
wait
waitpid
环境变量
概念
分类
常见的环境变量及其用途
环境变量的查看与设置
exec系列
函数解释
命名理解
简单shell
预备知识
fork
fork 是 Linux 和许多其他类 Unix 系统中的一个重要系统调用,它用于创建一个新的进程,这个新进程是当前进程的复制品,称为子进程。子进程会获得父进程当前状态的副本,包括父进程的内存布局、环境变量、打开的文件描述符等。但是,子进程和父进程是两个独立的执行线程,它们可以独立地运行程序的不同部分。
以下是关于 fork 的一些关键点:
- 复制:子进程是父进程的一个副本。但是,这种复制是“写时复制”(Copy-On-Write, COW)的。这意味着,如果子进程和父进程都不修改它们共享的内存区域,那么这些区域实际上不会被复制,从而节省内存和 CPU 时间。
- 返回值:
fork系统调用在父进程中返回新创建的子进程的进程 ID(PID),而在子进程中返回 0。这是区分父进程和子进程的一个常用方法。 - 资源分配:子进程会获得其父进程所拥有资源的副本,如文件描述符、环境变量等。但是,这些资源并不一定是物理上独立的;它们通常是通过引用计数或其他机制来共享的。
- 并发:由于子进程和父进程是两个独立的执行线程,因此它们可以并发地执行不同的任务。这使得
fork成为实现多进程并发和并行处理的重要工具。 - 进程间通信:由于子进程和父进程是独立的,因此它们之间需要进行通信以共享数据或协调行为。这可以通过各种进程间通信(IPC)机制来实现,如管道、消息队列、信号量、共享内存等。
- 终止和等待:当子进程终止时,它会留下一个僵尸进程(Zombie Process),直到其父进程调用
wait或waitpid系统调用来获取其终止状态并释放其占用的资源。
需要注意的是,虽然 fork 是一个强大的工具,但它也有一些限制和开销。例如,由于需要复制父进程的状态,因此 fork 的开销通常比创建线程要大。此外,由于子进程和父进程是独立的,因此它们之间的通信和同步也需要额外的开销和复杂性。因此,在选择使用 fork 还是其他并发机制(如线程或协程)时,需要根据具体的应用场景和需求进行权衡。
进程等待
wait
- 功能:
wait函数用于使父进程等待其任意一个子进程结束,并回收该子进程的资源。当子进程结束时,内核会向父进程发送SIGCHLD信号,父进程可以通过wait函数来响应这个信号并获取子进程的状态。 - 函数原型:
pid_t wait(int *wstatus);- 参数
wstatus是一个指向整数的指针,用于存储子进程的退出状态。如果父进程不关心子进程的退出状态,可以将此参数设为NULL。 - 返回值是已结束子进程的进程ID(PID),如果出现错误则返回-1。
- 参数
- 特点:
wait函数会阻塞父进程的执行,直到有一个子进程结束。如果调用wait时子进程已经结束,则wait会立即返回子进程的结束状态值。
waitpid
- 函数原型:#include #include pid_t wait(int*status); 返回值: 成功返回被等待进程pid,失败返回-1
- 返回值:
- 当正常返回的时候waitpid返回收集到的子进程的进程ID;
- 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
- 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
- 参数:
- pid:
- Pid=-1,等待任一个子进程。与wait等效。
- Pid>0.等待其进程ID与pid相等的子进程。
- status:
- WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
- WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
- options:
- WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。
- pid:
环境变量
概念
- 定义:环境变量是系统预定义的参数,相当于全局变量,存在于所有的shell中,具有继承性。它们可存储有关shell会话和工作环境的信息。
- 作用:环境变量允许在内存中存储数据,以便运行在shell上的程序和脚本访问。这些数据可以用来识别用户、系统、Shell的特性以及任何其它需要存储的数据。
分类
- 按作用范围分:
- 系统环境变量:公共的,对全部的用户都生效。
- 用户环境变量:用户私有的、自定义的个性化设置,只对该用户生效。
- 按生存周期分:
- 永久环境变量:在环境变量脚本文件中配置,用户每次登录时会自动执行这些脚本,相当于永久生效。
- 临时环境变量:使用时在Shell中临时定义,退出Shell后失效。
常见的环境变量及其用途
- PATH:指定命令的搜索路径,由冒号分隔的目录列表,用于告诉系统在哪里可以找到可执行文件。
- HOME:指定用户的主工作目录,即用户登录到Linux系统时,默认的目录。
- SHELL:当前Shell的路径,通常指向用户当前使用的shell解析器,如
/bin/bash。 - LD_LIBRARY_PATH:C/C++语言动态链接库文件搜索的目录,对C/C++程序员来说非常重要。
- CLASSPATH:JAVA语言库文件搜索的目录,对JAVA程序员来说非常重要。
环境变量的查看与设置
- 查看:
- 使用
env命令可以查看当前用户全部的环境变量。 - 使用
echo $环境变量名可以查看特定环境变量的值。
- 使用
- 设置:
- 使用
export命令可以设置新的环境变量或修改现有环境变量的值。例如,export PATH=$PATH:/new/directory。 - 如果希望环境变量永久生效,需要在登录脚本文件中(如
/etc/profile、/etc/profile.d/、~/.bash_profile、~/.bashrc等)进行配置
- 使用
exec系列
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
nt execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]); i
nt execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
这些函数的主要目的是在当前进程的上下文中执行一个新程序,从而替换当前进程的映像。它们允许程序在运行时加载新的可执行文件,实现动态性和灵活性。
函数解释
- 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
- 如果调用出错则返回-1
- 所以exec函数只有出错的返回值而没有成功的返回值
命名理解
- l(list) : 表示参数采用列表
- v(vector) : 参数用数组
- p(path) : 有p自动搜索环境变量PATH
- e(env) : 表示自己维护环境变量
简单shell
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#define SIZE 512
#define ZERO '\0'
#define SEP " "
#define NUM 32
#define SkipPath(p) do{p+=strlen(p)-1;while(*p!='/')p--;}while(0)
#define SkipSpace(cmd,pos) do{ \while(1){\if(isspace(cmd[pos]))\pos++;\else break;\}}while(0)
#define none_type 0
#define in_type 1
#define out_type 2
#define app_type 3
int redir_type=none_type;
char* filename=NULL;char* gArgv[NUM];
int lastcode=0;
void Die()
{exit(1);
}
const char* GetHostname()
{const char* hostname=getenv("HOSTNAME");if(hostname==NULL)return "/";return hostname;
}
const char* GetUsername()
{const char* user=getenv("USER");if(user==NULL)return "none";return user;
}
const char* Getcwd()
{const char* cwd=getenv("PWD");if(cwd==NULL) return "none";return cwd;
}
void MakeCommmandLine()
{char line[SIZE];const char* hostname=GetHostname();const char* username=GetUsername();const char* cwd=Getcwd();SkipPath(cwd);snprintf(line,sizeof(line),"[%s@%s %s]> ",username,hostname,strlen(cwd)==1?"/":cwd+1);printf("%s",line);fflush(stdout);
}
int GetUserCommad(char commad[],size_t n)
{char* s=fgets(commad,n,stdin);if(s==NULL)return -1;commad[strlen(commad)-1]=ZERO;return strlen(commad);}
void CheckRedir(char cmd[])
{int pos=0;int end=strlen(cmd);while(pos<end){if(cmd[pos]=='>'){if(cmd[pos+1]=='>'){cmd[pos++]=0;pos++;redir_type=app_type;SkipSpace(cmd,pos);filename=cmd+pos;}else {cmd[pos++]=0;redir_type=out_type;SkipSpace(cmd,pos);filename=cmd+pos; }}else if(cmd[pos]=='<'){cmd[pos++]=0;redir_type=in_type;SkipSpace(cmd,pos);filename=cmd+pos;}else{pos++;}}
}
void SplitCommad(char command[])
{gArgv[0]=strtok(command,SEP);int index=1;while((gArgv[index++]=strtok(NULL,SEP)));
}
void ExecuteCommand()
{pid_t id=fork();if(id<0)Die();else if (id==0){//子进程if(filename!=NULL){if(redir_type==in_type){int fd=open(filename,O_RDONLY);dup2(fd,0);}else if (redir_type==out_type){int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);dup2(fd, 1); }else if (redir_type==app_type){int fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);dup2(fd, 1);}}execvp(gArgv[0],gArgv);exit(errno);}else{//父进程int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){lastcode = WEXITSTATUS(status);if(lastcode != 0) printf("%s:%s:%d\n", gArgv[0], strerror(lastcode), lastcode);} }
}
int main()
{int quit=0;while(!quit){redir_type=none_type;filename=NULL;//创建一个自己的命令行MakeCommmandLine();//获取用户命令char usercommad[SIZE];int n=GetUserCommad(usercommad,sizeof(usercommad));if(n<=0)return 1;CheckRedir(usercommad);//测试一下// printf("cmd: %s\n", usercommad);// printf("redir: %d\n", redir_type);// printf("filename: %s\n", filename);//分割字符串SplitCommad(usercommad);//执行命令ExecuteCommand();}return 0;
}
相关文章:
简单shell
目录 预备知识 fork 进程等待 wait waitpid 环境变量 概念 分类 常见的环境变量及其用途 环境变量的查看与设置 exec系列 函数解释 命名理解 简单shell 预备知识 fork fork 是 Linux 和许多其他类 Unix 系统中的一个重要系统调用,它用于创建一个新的…...
Spring Boot + FreeMarker 实现动态Word文档导出
Spring Boot FreeMarker 实现动态Word文档导出 在现代企业应用中,文档自动化生成是一项提升工作效率的重要功能。Spring Boot与FreeMarker的组合,为开发者提供了一个强大的平台,可以轻松实现动态Word文档的导出。本文将指导你如何使用Sprin…...
3D生物打印的未来:多材料技术的突破
多材料生物打印技术是近年来发展迅速的一项技术,为组织工程和再生医学带来了新的机遇,可以帮助我们更好地理解人体组织的结构和功能,并开发新的治疗方法。 1. 组织构建 复杂性模拟:多材料生物打印技术能够构建具有层次结构和异质…...
充电宝口碑哪个好?好用充电宝品牌有哪些?好用充电宝推荐
充电宝作为我们日常生活和出行的重要伙伴,其品质和性能直接影响着我们的使用体验。今天,就来和大家探讨一下充电宝口碑哪个好,为大家盘点那些备受赞誉的好用充电宝品牌,并向您推荐几款值得入手的充电宝,外出时不再担心…...
Pytorch-----(6)
一 、问题 如何计算基于不同变量的操作如矩阵乘法。 二、具体实现 0.4版本以前,张量是包裹在变量之中的,后者有三个属性grad、volatile和 requires_grad属性。(grad 就是梯度属性,requires_grad属性就是 是否需要存储梯度&#x…...
leetcode hot100 第三题:最长连续序列(Java)
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入:nums [100,4,200,1,3,2] 输出:4 解…...
利用Jaspar进行转录因子结合位点预测
前期我们介绍了如何进行ChIP-qPCR验证,里面提到了一个比较重要的因素——扩增范围的选择及引物的设计。相比双荧光素酶、酵母单杂-点对点验证等允许完整启动子验证的实验,ChIP-qPCR要求单次验证的范围尽量控制在150-200bp内。但一个基因的启动子一般有2-…...
Ubuntu添加系统字体
(2024.6.30) 系统字体保存路径在/usr/share/fonts下,如果此目录下缺少字体,则使用其他可视化api(如Python的pygame库)的默认配置时可能会出现乱码问题。 往Ubuntu中添加字体的方法 方法一:手…...
深度学习相关概念及术语总结2
目录 76.AUC77.DBSCAN聚类78.贝叶斯个性化排序79.BPRBandit算法 76.AUC AUC(Area Under the Curve)是一种常用的评价指标,用于衡量分类模型的性能。AUC值代表了模型在不同阈值下的真阳性率(True Positive Rate)和假阳…...
基于改进滑模、经典滑模、最优滑模控制的永磁同步电机调速系统MATLAB仿真
微❤关注“电气仔推送”获得资料(专享优惠) 模型简介 针对永磁同步电机调速系统的响应性能和抗干扰能力问题,本文做了四个仿真,分别为:永磁同步电机的PID控制调速系统、基于传统滑模控制的永磁同步电机的调速系统、最…...
windows环境下创建python虚拟环境
windows环境下创建python虚拟环境 使用virtualenv库创建虚拟环境,可使不同的项目处于不同的环境中 安装方法: pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple pip install virtualenvwrapper-win -i https://pypi.tuna.tsinghua…...
Fragment切换没变化?解决办法在这里
大家好,今天跟大家分享下如何避免fragment切换失败。方法其实很简单,只要在onCreate方法中初始化一个默认的fragment即可。 //开始事务FragmentTransaction transaction getActivity().getSupportFragmentManager().beginTransaction();transaction.rep…...
Linux系统防火墙iptables(下)
备份与还原iptables规则设置 1、yum -y install iptables iptables-services 安装iptables软件包 2、systemctl start iptables.service 开启服务 3、systemctl enable iptables.service 开机自启 我们对iptables命令行中的设置,都是临时设置,只要遇到服…...
你需要精益管理咨询公司的N+1个理由
近年来,精益管理作为一种被全球众多知名企业验证过的成功管理模式,越来越受到企业的青睐。但是,为何在实施精益管理的过程中,众多企业纷纷选择请咨询公司来协助呢?今天,我们就来一起揭秘这背后的原因。 1. …...
[机器学习]-3 万字话清从传统神经网络到深度学习
神经网络(Neural Networks, NNs)是机器学习的一种重要方法,灵感来源于生物神经系统,由大量互联的节点(称为神经元或单元)组成,通过调整这些节点间的连接权重来学习和表示复杂的非线性关系。传统…...
网络安全等级保护2.0(等保2.0)全面解析
一、等保2.0的定义和背景 网络安全等级保护2.0(简称“等保2.0”)是我国网络安全领域的基本制度、基本策略、基本方法。它是在《中华人民共和国网络安全法》指导下,对我国网络安全等级保护制度进行的重大升级。等保2.0的发布与实施,…...
用Lobe Chat部署本地化, 搭建AI聊天机器人
Lobe Chat可以关联多个模型,可以调用外部OpenAI, gemini,通义千问等, 也可以关联内部本地大模型Ollama, 可以当作聊天对话框消息框来集成使用 安装方法参考: https://github.com/lobehub/lobe-chat https://lobehub.com/zh/docs/self-hosting/platform/…...
基于ARM的通用的Qt移植思路
文章目录 实验环境介绍一、确认Qt版本二、确认交叉编译工具链三、配置Qt3.1、修改qmake.conf3.2、创建autoConfig.sh配置文件 四、编译安装Qt五、移植Qt安装目录六、配置Qt creator6.1、配置qmake6.2、配置GCC编译器6.3、配置G编译器6.4、配置编译器套件6.5、创建应用 七、总结…...
IT专业入门,高考假期预习指南
七月来临,各省高考分数已揭榜完成。而高考的完结并不意味着学习的结束,而是新旅程的开始。对于有志于踏入IT领域的高考少年们,这个假期是开启探索IT世界的绝佳时机。 一、基础课程预习指南 IT专业是一个广泛的领域,涵盖了从软件开…...
芯片详解——AD7606C
芯片详解——AD7606C AD7607C 是一款由 Analog Devices(模拟器件公司)生产的 6 通道同步采样模数转换器(ADC),适用于高速数据采集系统。 工作原理 AD7607C 的工作原理主要包括以下几个步骤: 模拟信号输入:AD7607C 有六个模拟输入通道,可以同时进行采样。这些模拟信号…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
