当前位置: 首页 > article >正文

Linux 进程控制(自用)

非阻塞调用waitpid
这样父进程就不会阻塞,此时循环使用我们可以让父进程执行其他任务而不是阻塞等待

进程程序替换
进程=PCB+加载到内存中的代码和数据
替换就是完全替换当前进程的代码段、数据段、堆和栈,保存当前的PCB

代码指的是二进制代码不是源码!!!

  #include <unistd.h>extern char **environ;int execl(const char *pathname, const char *arg, .../* (char  *) NULL */);int execlp(const char *file, const char *arg, .../* (char  *) NULL */);int execle(const char *pathname, const char *arg, .../*, (char *) NULL, char *const envp[] */);int execv(const char *pathname, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[],char *const envp[]);

pathname是要执行的可执行文件的完整路径​ /bin/ls
file程序名,不带路径在环境变量PATH查找

l就是list,以可变参数的形式传递"ls",“-l”,“NULL”
p就是会从环境变量查找,只要程序名即可
e就是环境变量数组
v就是vector以指针数组的形式传递

自定义shell的编写

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <unordered_map>
#include <string>#define COMMAD_SIZE 1024
#define FORMAT "[%s@%s %s]# "// 下面是shell定义的全局数据// 1.命令行参数
#define MAXARGC 128
char *g_argv[MAXARGC];
int g_argc = 0;// 2.环境变量表
#define MAX_ENVS 100
char *g_env[MAX_ENVS];
int g_envs = 0;// 3.别名映射表
std::unordered_map<std::string, std::string> alias_list; // la对于ls -a// for test
char cwd[1024];
char cwdenv[1024];
char oldpwd[1024];
// last exit code
int lastcode = 0; // 最新子进程退出码const char *GetUserName()
{const char *name = getenv("USER");return name == NULL ? "None" : name;
}const char *GetHostName() // 变化不大,可以不用系统调用。其实最好也用系统调用
{const char *hostname = getenv("HOSTNAME");return hostname == NULL ? "None" : hostname;
}// 切换路径时,环境变量表也要切换。因此我们要更新环境变量。
// 注意我们自定义shell的环境变量表继承自shell
// 路径先变,环境变量才变,调用系统调用
const char *GetPwd()
{const char *pwd = getcwd(cwd, sizeof(cwd));if (pwd){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char *GetOldPwd()
{return getenv("OLDPWD");
}
const char *GetHome()
{return getenv("HOME");
}void InitEnv()
{extern char **environ; // 头文件#include <unistd.h>定义了这个,这里是声明memset(g_env, 0, sizeof(g_env));// 本来从父进程继承,现在直接从配置文件(操作系统)来// 1.获取环境变量for (int i = 0; environ[i]; i++){// 申请空间// 别用sizeof,sizeof得到的是指针大小g_env[i] = (char *)malloc(strlen(environ[i]) + 1);strcpy(g_env[i], environ[i]);g_envs++;}g_env[g_envs] = NULL;// 2.导入环境变量// 增量修改for (int i = 0; g_env[i]; i++){putenv(g_env[i]);}// environ=g_env;完全重置
}// command 内建命令
bool Cd()
{memset(oldpwd, 0, sizeof(oldpwd));snprintf(oldpwd, sizeof(oldpwd), "OLDPWD=%s", GetPwd());putenv(oldpwd);if (g_argc == 1){std::string home = GetHome();if (home.empty())return true;chdir(home.c_str());}else{std::string where = g_argv[1];if (where == "-")chdir(GetOldPwd());else if (where == "~")chdir(GetHome());elsechdir(where.c_str());}return true;// cd argc = 1if (g_argc == 1){std::string home = GetHome();if (home.empty())return true;chdir(home.c_str());}else{std::string where = g_argv[1];// cd - / cd ~if (where == "-"){// Todu}else if (where == "~"){// Todu}else{chdir(where.c_str());}}return true;
}void Echo()
{if (g_argc == 2){std::string opt = g_argv[1];if (opt == "$?"){std::cout << lastcode << std::endl;lastcode = 0; // echo执行完,退出码应该是0}else if (opt[0] == '$'){std::string env_name = opt.substr(1);const char *env_value = getenv(env_name.c_str());if (env_value)std::cout << env_value << std::endl;}else{std::cout << opt << std::endl;}}
}
// 防止自定义bash路径名太长
/*std::string DirName(const char *pwd)
{
#define SLASH "/"std::string dir = pwd;if (dir == SLASH)return SLASH; // 只有根目录直接返回auto pos = dir.rfind(SLASH);return dir.substr(pos + 1);
}*/
// 命令行提示符
void MakeCommandLine(char cmd_prompt[], int size)
{snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), GetPwd());
}
// 打印命令行提示符
void PrintCommandPrompt()
{char prompt[COMMAD_SIZE];MakeCommandLine(prompt, sizeof(prompt));std::cout << prompt;fflush(stdout);
}
bool GetCommandLine(char *out, int size)
{char *c = fgets(out, size, stdin);if (c == NULL)return false;out[strlen(out) - 1] = 0; // 清理\nif (strlen(out) == 0)return false; // 只输入了/nreturn true;
}
// 3.命令行分析 "ls -a -l" 解析为 "ls" "-a" "-l"
bool CommandParse(char *commandline)
{
#define SEP " "g_argc = 0;g_argv[g_argc++] = strtok(commandline, SEP);while(g_argv[g_argc++] = strtok(nullptr, SEP));g_argc--;return g_argc > 0 ? true : false;
}void PrintArgv()
{for (int i = 0; g_argv[i]; i++){printf("argv[%d]->%s\n", i, g_argv[i]);}printf("argc: %d\n", g_argc);
}bool CheckAndExecBuiltin()
{std::string cmd = g_argv[0];if (cmd == "cd"){Cd();return true;}else if (cmd == "echo"){Echo();return true;}else if (cmd == "export")return true;else if (cmd == "alias")return true;return false;
}int Execute()
{pid_t id = fork();if (id == 0){// childexecvp(g_argv[0], g_argv);exit(1); // 一旦替换exit不会执行}// fatherint status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0)                        // 等待成功lastcode = WEXITSTATUS(status); // 获取子进程退出码return 0;
}int main()
{InitEnv();while (true) // 死循环{// 1.输出命令行提示符PrintCommandPrompt();// 2.获取用户输入的命令char commandline[COMMAD_SIZE];if (!GetCommandLine(commandline, COMMAD_SIZE))continue;// 3.命令行分析,并将分析后的命令行导入全面变量表中if (!CommandParse(commandline))continue;// 检测是否是内建命令,若是直接调用然后continue,若不是则执行下面的if (CheckAndExecBuiltin())continue;;Execute();}return 0;
}

相关文章:

Linux 进程控制(自用)

非阻塞调用waitpid 这样父进程就不会阻塞&#xff0c;此时循环使用我们可以让父进程执行其他任务而不是阻塞等待 进程程序替换 进程PCB加载到内存中的代码和数据 替换就是完全替换当前进程的代码段、数据段、堆和栈&#xff0c;保存当前的PCB 代码指的是二进制代码不是源码&a…...

05-DevOps-Jenkins自动拉取构建代码

新建Gitlab仓库 先在Gitab上创建一个代码仓库&#xff0c;选择创建空白项目 安装说明进行填写&#xff0c;然后点击创建项目 创建好的仓库是空的&#xff0c;什么都没有 新建一个springboot项目&#xff0c;用于代码上传使用。 只是为了测试代码上传功能&#xff0c;所以代码…...

【Spring学习】

Spring学习 简介 Spring 是一个开源的 Java 企业级开发框架&#xff0c;最核心的特点是&#xff1a; IOC&#xff08;控制反转&#xff09;AOP&#xff08;面向切面编程&#xff09; 它有完整的生态&#xff1a; &#x1f680; Spring Boot&#xff1a;用于快速构建服务&a…...

网络基础与 HTTP 协议

一、网络基础 &#xff08;一&#xff09;TCP/IP 协议族 TCP/IP 协议族是互联网通信的核心协议&#xff0c;它包含了多个层次的协议&#xff0c;共同协作实现网络通信。 1. IP 协议 IP&#xff08;Internet Protocol&#xff09;协议位于网络层&#xff0c;主要负责将数据包…...

SRS transcode支持 h264_nvenc 硬件解码方案

文章目录 SRS transcode支持 h264_nvenc 硬件解码方案1、修改文件2、重新编译3、使用 SRS transcode支持 h264_nvenc 硬件解码方案 SRS 是开源的流媒体服务&#xff0c;但在使用 GPU 服务器时&#xff0c;想要通过硬件加速&#xff0c;目前官方是不支持的&#xff0c;所以简单…...

阿里云服务器搭建开源版禅道

一&#xff0c;下载地址&#xff1a;禅道11.5版本发布&#xff0c;主要完善细节&#xff0c;修复bug&#xff0c;新增动态过滤机制 - 禅道下载 - 禅道项目管理软件 下载地址二&#xff1a; 禅道21.6.stable 实现旧编辑器撰写的文档无感升级至新版编辑器 - 禅道下载 - 禅道项目…...

【刷题Day21】TCP(浅)

说说 TCP 的四次挥手&#xff1f; TCP的四次挥手事用于安全关闭一个已建立的连接的过程&#xff0c;它确保双方都能完成数据传输并安全地释放连接资源。 简述步骤&#xff1a; 第一次挥手&#xff08;FIN --> ACK&#xff09;&#xff1a;客户端主动关闭连接&#xff0c;…...

怎么用面向对象和状态机架构,设计一个通用的按键检测功能?

说起按键检测&#xff0c;在座的各位&#xff0c;哪个没被它折磨过&#xff1f; 我刚入门时&#xff0c;为了实现一个简单的按键功能&#xff0c;硬生生写了几十行代码&#xff0c;各种 if...else 嵌套&#xff0c;逻辑绕得我自己都头晕。 更可气的是&#xff0c;辛辛苦苦写完…...

Java基础系列-LinkedList源码解析

文章目录 简介LinkedList 插入和删除元素的时间复杂度&#xff1f;LinkedList 为什么不能实现 RandomAccess 接口&#xff1f; LinkedList 源码分析Node 定义初始化获取元素插入元素删除元素遍历链表 简介 LinkedList 是一个基于双向链表实现的集合类&#xff0c;经常被拿来和…...

day47—双指针-平方数之和(LeetCode-633)

题目描述 给定一个非负整数 c &#xff0c;你要判断是否存在两个整数 a 和 b&#xff0c;使得 a^2 b^2 c 。 示例 1&#xff1a; 输入&#xff1a;c 5 输出&#xff1a;true 解释&#xff1a;1 * 1 2 * 2 5示例 2&#xff1a; 输入&#xff1a;c 3 输出&#xff1a;f…...

qwen 14B模型配置文件,层名称weight_map. 28GB

qwen 14B模型配置文件,层名称weight_map. 28GB 目录 qwen 14B模型配置文件,层名称weight_map. 28GBmetadata(元数据)weight_map(权重映射)lm_head.weightmodel.layersmlp.{proj_type}.weightpost_attention_layernormself_attn.{proj_type}.{bias_or_weight}model.norm.w…...

LVDS系列8:Xilinx 7系可编程输入延迟(一)

在解析LVDS信号时&#xff0c;十分重要的一环就是LVDS输入信号线在经过PCB输入到FPGA中后&#xff0c;本来该严格对齐的信号线会出现时延&#xff0c;所以需要在FPGA内部对其进行延时对齐后再进行解析。 Xilinx 7系器件中用于输入信号延时的组件为IDELAYE2可编程原语&#xff0…...

【Oracle专栏】函数中SQL拼接参数 报错处理

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 1.背景 最近同事反馈了一个很奇怪的问题,即有一个函数,入参是当前年月,主要作用是通过SQL语句将不合规的数据插入到指定表中,插入数据时带上入参的年月参数。当前问题:单独测试SQL没有问题可以执行成功,…...

自然语言处理(NLP)领域大图

以下是一份自然语言处理&#xff08;NLP&#xff09;与大模型领域的领域大图&#xff0c;涵盖技术框架、发展脉络、交叉融合点和应用场景的完整解析&#xff1a; 1. 核心技术体系 基础分析层级 词法分析&#xff1a;分词、词性标注、命名实体识别句法分析&#xff1a;依存句法…...

【Linux我做主】GDB调试工具完全指南

Linux下GDB调试工具完全指南&#xff1a;25个核心命令详解与实战示例 github地址 有梦想的电信狗 前言 GDB&#xff08;GNU Debugger&#xff09;是Linux开发中不可或缺的调试工具&#xff0c;尤其在定位代码逻辑错误和内存问题时表现卓越。本文基于实际开发经验&#xff0…...

Pycharm 如何删除某个 Python Interpreter

在PyCharm中&#xff0c;点击右下角的“Interpreter Settings”按钮&#xff0c;或者通过菜单栏选择“File” > “Settings”&#xff08;macOS用户选择“PyCharm” > “Preferences”&#xff09;。在设置窗口中&#xff0c;导航到“Project: [Your Project Name]” >…...

在 Debian 12 中恢复被删除的 smb.conf 配置文件

https://forum.ubuntu.com.cn/viewtopic.php?t494763 本文结合ai输出&#xff0c;内容中可能有些错误&#xff0c;但确实解决了我的问题&#xff0c;我采取保留完整输出的方式摘录。 在 Debian 12 中恢复被删除的 smb.conf 配置文件&#xff0c;需结合 dpkg 和 ucf&#xff08…...

Day3:个人中心页面布局前端项目uniapp壁纸实战

接下来我们来弄一下个人中心页面布局user.vue <template><view class"userLayout"><view class"userInfo"><view class"avatar"><image src"../../static/Kx.jpg" mode"aspectFill"></im…...

访问”和“初始化本质区别以及C++静态成员变量定义位置详解

&#x1f4a1; 1.访问”和“初始化本质区别&#xff1a; ✅ 访问 protectedNum&#xff1a;Derived 作为 Base 的子类&#xff0c;是可以在自己的函数中访问 protectedNum 的。❌ 初始化 protectedNum&#xff1a;只能通过 Base 的构造函数来初始化&#xff0c;因为它是 Base …...

正则表达式反向引用的综合应用魔法:从重复文本到简洁表达的蜕变

“我....我要....学学学学....编程 java!” —— 这类“重复唠叨”的文本是否让你在清洗数据时头疼不已&#xff1f; 本文将带你一步步掌握正则表达式中的反向引用技术&#xff0c;并结合 Java 实现一个中文文本去重与清洗的实用工具。 结合经典的结巴实例。如何高效地将这样的…...

C实现md5功能

md5在线验证&#xff1a; 在线MD5计算_ip33.com 代码如下&#xff1a; #include "md5.h" #include <string.h> #include "stdio.h"/** 32-bit integer manipulation macros (little endian)*/ #ifndef GET_ULONG_LE #define GET_ULONG_LE(n,b,i) …...

FFmpeg+Nginx+VLC打造M3U8直播

一、视频直播的技术原理和架构方案 直播模型一般包括三个模块&#xff1a;主播方、服务器端和播放端 主播放创造视频&#xff0c;加美颜、水印、特效、采集后推送给直播服务器 播放端&#xff1a; 直播服务器端&#xff1a;收集主播端的视频推流&#xff0c;将其放大后推送给…...

在 Debian 10.x 安装和配置 Samba

1. 更新系统 sudo apt update sudo apt upgrade -y2. 安装 Samba sudo apt install samba -y3. 配置 Samba 备份默认配置文件 sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak编辑配置文件 sudo nano /etc/samba/smb.conf示例配置&#xff08;共享目录&#xff09; …...

基础(测试用例:介绍,测试用例格式,案例)

目录 测试用例介绍 测试用例编写格式 案例 测试用例介绍 用例&#xff1a;用户使用软件的案例场景 测试用例&#xff1a;是为测试项目而设计的测试执行文档 测试用例的作用&#xff1a; 防止漏测是实施测试的标准可以作为测试工作量的评估 测试用例编写格式 用例编号 用例…...

C++学习:六个月从基础到就业——内存管理:RAII原则

C学习&#xff1a;六个月从基础到就业——内存管理&#xff1a;RAII原则 本文是我C学习之旅系列的第十九篇技术文章&#xff0c;也是第二阶段"C进阶特性"的第四篇&#xff0c;主要介绍C中的RAII原则及其在资源管理中的应用。查看完整系列目录了解更多内容。 引言 在…...

Windows串口通信

Windows串口通信相比较Android串口通信,在开发上面相对方便一些。原理都是一样,需要仔细阅读厂商设备的串口通信协议。结合串口调试助手进行测试,测试通过后,编写代码实现。 比如近期就接触到了一款天平,其最大测量值为100g,测量精度0.001g。 拿到手之后我就先阅读串口通…...

bert项目解析

数据预处理 读取csv数据集 def read_file(file_path):data []label []with open(file_path, "r", encoding"utf-8") as file:reader csv.reader(file)next(reader) # 跳过标题行# row每一行用英文逗号分割成列表[标签,文本] 所以标签和文本用英文逗…...

Linux `init` 相关命令的完整使用指南

Linux init 相关命令的完整使用指南—目录 一、init 系统简介二、运行级别&#xff08;Runlevel&#xff09;详解三、常用 init 命令及使用方法1. 切换运行级别2. 查看当前运行级别3. 服务管理4. 紧急模式&#xff08;Rescue Mode&#xff09; 四、不同 Init 系统的兼容性1. Sy…...

【开源项目】Excel手撕AI算法深入理解(三):时序(RNN、mamba、Long Short Term Memory (LSTM)、xLSTM)

项目源码地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、RNN 1. RNN 的核心思想 RNN 的设计初衷是处理序列数据&#xff08;如时间序列、文本、语音&#xff09;&#xff0c;其核心特点是&#xff1a; 隐藏状态&#xff08;Hidden State&#xff…...

嵌入式音视频开发指南:从MPP框架到QT实战全解析

嵌入式音视频开发指南:从MPP框架到QT实战全解析 一、音视频技术全景概述 1.1 技术演进里程碑 2003-2010年:标清时代(H.264/AVC + RTMP)2011-2018年:高清时代(H.265/HEVC + WebRTC)2019-至今:智能时代(AV1 + AI编解码 + 低延迟传输)1.2 现代音视频技术栈 #mermaid-s…...