Linux自行实现的一个Shell(15)
文章目录
- 前言
- 一、头文件和全局变量
- 头文件
- 全局变量
- 二、辅助函数
- 获取用户名
- 获取主机名
- 获取当前工作目录
- 获取最后一级目录名
- 生成命令行提示符
- 打印命令行提示符
- 三、命令处理
- 获取用户输入
- 解析命令行
- 执行外部命令
- 四、内建命令
- 添加环境变量
- 检查和执行内建命令
- 五、初始化
- 初始化环境变量
- 主循环
- 总结
前言
MyShell源代码公开
本篇是对之前知识的一个综合运用,也是检验你是否对前置知识有个较为透彻的理解的好时机
一、头文件和全局变量
头文件
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
全局变量
const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;// 全局的命令行参数表
char *gargv[argvnum];
int gargc = 0;// 全局的变量
int lastcode = 0;// 我的系统的环境变量
char *genv[envnum];// 全局的当前shell工作路径
char pwd[basesize];
char pwdenv[basesize];
- basesize:缓冲区基本大小
- argvnum 和 envnum:参数和环境变量的最大数量
- gargv 和 gargc:存储解析后的命令参数
- lastcode:存储上一条命令的退出状态码
- genv:存储环境变量
- pwd 和 pwdenv:存储当前工作目录
二、辅助函数
获取用户名
string GetUserName()
{string name = getenv("USER");return name.empty() ? "None" : name;
}
- 通过 getenv(“USER”) 获取当前用户名
- 如果获取失败返回 “None”
获取主机名
string GetHostName()
{string hostname = getenv("HOSTNAME");return hostname.empty() ? "None" : hostname;
}
- 通过 getenv(“HOSTNAME”) 获取主机名
- 如果获取失败返回 “None”
获取当前工作目录
string GetPwd()
{if(nullptr == getcwd(pwd, sizeof(pwd))) return "None";snprintf(pwdenv, sizeof(pwdenv),"PWD=%s", pwd);putenv(pwdenv); // PWD=XXXreturn pwd;
}
- 使用 getcwd() 获取当前工作目录
- 如果失败返回 “None”
- 将当前目录设置到环境变量 PWD 中
- 返回当前目录路径
获取最后一级目录名
string LastDir()
{string curr = GetPwd();if(curr == "/" || curr == "None") return curr;size_t pos = curr.rfind("/");if(pos == std::string::npos) return curr;return curr.substr(pos+1);
}
- 获取当前目录
- 如果是根目录或无效目录直接返回
- 查找最后一个 ‘/’ 的位置
- 返回最后一个 ‘/’ 之后的部分
生成命令行提示符
string MakeCommandLine()
{char command_line[basesize];snprintf(command_line, basesize, "[%s@%s %s]# ",\GetUserName().c_str(), GetHostName().c_str(), LastDir().c_str());return command_line;
}
- 生成类似 [user@host dirname]# 的提示符
打印命令行提示符
void PrintCommandLine() // 1. 命令行提示符
{printf("%s", MakeCommandLine().c_str());fflush(stdout);
}
- 打印提示符
- fflush(stdout) 确保立即显示
三、命令处理
获取用户输入
bool GetCommandLine(char command_buffer[], int size)
{char *result = fgets(command_buffer, size, stdin);if(!result){return false;}// 因为 command_line 里有一个 \n,我们把它替换成 \0 即可command_buffer[strlen(command_buffer)-1] = '\0';if(strlen(command_buffer) == 0) return false;return true;
}
- 使用 fgets 读取用户输入
- 移除末尾的换行符
- 检查是否为空输入
解析命令行
获取用户输入后,我们需要将接收到的字符串拆分为命令及其参数。
将接收到的字符串拆开
通过 strtok 函数,我们可以将一个字符串按照特定的分隔符打散,依次返回子串
void ParseCommandLine(char command_buffer[], int len)
{(void)len;memset(gargv, 0, sizeof(gargv));gargc = 0;const char *sep = " ";gargv[gargc++] = strtok(command_buffer, sep);while((bool)(gargv[gargc++] = strtok(nullptr, sep)));gargc--;
}
- 重置参数数组和计数器
- 使用 strtok 以空格为分隔符分割命令
- 将分割后的参数存入 gargv 数组
- 调整 gargc 为实际参数数量
执行外部命令
bool ExecuteCommand()
{pid_t id = fork();if(id < 0) return false;if(id == 0){execvpe(gargv[0], gargv, genv);exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){if(WIFEXITED(status)){lastcode = WEXITSTATUS(status);}else{lastcode = 100;}return true;}return false;
}
- 创建子进程
- 子进程使用 execvpe 执行命令
- 父进程等待子进程结束
- 保存子进程退出状态到 lastcode
四、内建命令
内建命令是指直接内置在操作系统内核中的一些命令,与普通的外部命令(外部程序文件)不同。这些内建命令是直接由shell解释器(如Bash、Zsh等)所处理,而不需要通过外部文件的方式来执行。这些内建命令通常在操作系统的shell环境中被频繁使用,并且执行速度更快,因为它们不需要创建新的进程来执行
在Unix和类Unix操作系统中,通常会有一些内建命令,比如cd、echo、exit等。这些命令不需要单独的可执行文件,而是直接由shell内核提供支持。当用户在shell中输入这些命令时,shell会直接处理它们,而不需要通过搜索系统路径来找到可执行文件
值得一提的是,某些shell也允许用户通过自定义的方式添加新的内建命令,这样用户可以根据自己的需求来扩展shell的内建功能
添加环境变量
void AddEnv(const char *item)
{int index = 0;while(genv[index]){index++;}genv[index] = (char*)malloc(strlen(item)+1);strncpy(genv[index], item, strlen(item)+1);genv[++index] = nullptr;
}
- 找到环境变量数组的末尾
- 分配内存并复制新环境变量
- 确保数组以 NULL 结尾
检查和执行内建命令
bool CheckAndExecBuiltCommand()
{if(strcmp(gargv[0], "cd") == 0){if(gargc == 2){chdir(gargv[1]);lastcode = 0;}else{lastcode = 1;}return true;}else if(strcmp(gargv[0], "export") == 0){if(gargc == 2){AddEnv(gargv[1]);lastcode = 0;}else{lastcode = 2;}return true;}else if(strcmp(gargv[0], "env") == 0){for(int i = 0; genv[i]; i++){printf("%s\n", genv[i]);}lastcode = 0;return true;}else if(strcmp(gargv[0], "echo") == 0){if(gargc == 2){if(gargv[1][0] == '$'){if(gargv[1][1] == '?'){printf("%d\n", lastcode);lastcode = 0;}}else{printf("%s\n", gargv[1]);lastcode = 0;}}else{lastcode = 3;}return true;}return false;
}
支持的内建命令有:
- cd:改变工作目录
- export:设置环境变量
- env:显示所有环境变量
- echo:打印内容或上一条命令的退出码
五、初始化
初始化环境变量
void InitEnv()
{extern char **environ;int index = 0;while(environ[index]){genv[index] = (char*)malloc(strlen(environ[index])+1);strncpy(genv[index], environ[index], strlen(environ[index])+1);index++;}genv[index] = nullptr;
}
从父进程复制环境变量
主循环
int main()
{InitEnv();char command_buffer[basesize];while(true){PrintCommandLine();if( !GetCommandLine(command_buffer, basesize) ){continue;}ParseCommandLine(command_buffer, strlen(command_buffer));if ( CheckAndExecBuiltCommand() ){continue;}ExecuteCommand();}return 0;
}
主循环流程:
- 打印提示符
- 获取用户输入
- 解析命令
- 尝试执行内建命令
- 如果不是内建命令,则执行外部命令
总结
感觉如何呢!
相关文章:
Linux自行实现的一个Shell(15)
文章目录 前言一、头文件和全局变量头文件全局变量 二、辅助函数获取用户名获取主机名获取当前工作目录获取最后一级目录名生成命令行提示符打印命令行提示符 三、命令处理获取用户输入解析命令行执行外部命令 四、内建命令添加环境变量检查和执行内建命令 五、初始化初始化环境…...
powerDesign 逆向 mysql 生成 物理模型,并用VBS脚本整理comment
学习自:https://www.cnblogs.com/xmyjcs/p/8536233.html 文章目录 Reverse Engineer格式化模型执行 VBS 脚本 Reverse Engineer 下面 DBMS 可以通过 ODBC(Open Database Connectivity,开放数据库连接)连接, 需要自己先…...
跨境全域中台:前端独立站群+后端共享云仓的协同作战体系
在全球化浪潮与互联网技术飞速发展的当下,跨境电商已然成为国际贸易领域中最为活跃的力量。据相关数据显示,过去几年跨境电商的年增长率持续保持高位,越来越多的企业投身于这片充满机遇与挑战的蓝海市场。在竞争日益激烈的跨境电商赛道上&…...
国产芯片解析:乐得瑞LDR6500C 超小封装全能芯片,赋能智能设备未来
LDR6500C是乐得瑞科技针对USB-C标准中的Bridge设备而开发的双USB-C DRP接口PD通信芯片,具备切换Data Role功能,支持最高USB PD 100W 充电,并且针对各大品牌设备的 USB-C 兼容性进行了特别优化,非常适合于 USB Type-C 设备快充转接…...
代码随想录-06-二叉树-05.10 二叉树的最小深度
二叉树的最小深度 #模板题 题目描述 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明叶子节点是指没有子节点的节点 具体思路(暴力) 层序遍历;找到cur.left null && cur.ri…...
系统与网络安全------网络通信原理(6)
资料整理于网络资料、书本资料、AI,仅供个人学习参考。 应用层解析 DNS Domain Name System,域名系统 用来完成域名与IP地址之间的映射,便于用户对网站的记忆和访问 端口号为TCP或UDP的53 DNS工作原理 FTP File Transfer Protocol 文件…...
【Vue #2】脚手架 指令
一、脚手架 脚手架:一个保证各项工作顺利开展的平台,方便我们 拿来就用,零配置 1. Vue 代码开发方式 相比直接 script 引入 vue 源码,有没有更好的方式编写vue代码呢? ① 传统开发模式: 基于html文件开发Vue&…...
UE5 后坐力枪口上抬和恢复
文章目录 计算后坐力并让视角上抬后坐力回落 计算后坐力并让视角上抬 在玩家蓝图里,声明一个方法OnShootOnce,在武器每次射击时调用 1检测新的后坐力是否超过了最大后坐力,并选择一个小的 2 如何将角色模型设置为相机的子物体 3 最后记录一下当前的…...
Mysql B+树高度如何计算?
MySQL 的 InnoDB 存储引擎使用 B+树 作为索引结构,其高度增加会直接影响查询性能(每次高度增加意味着多一次磁盘 I/O)。以下是 B+树高度增加的 关键场景 和 优化建议: 1. B+树高度增加的触发条件 (1) 数据量持续增长 根本原因:B+树的层级由数据量(记录数)和每个节点的容…...
UE5 使用贴花创建弹孔
文章目录 使用射线检测击中点在击中点处创建贴花 使用射线检测击中点 和untiy一样,发射一条射线,在命中点处创建弹孔 在武器里定义射击检测方法 以下是对上边使用的方法的展开 GetShootStartPosition:获取射击起点 computeShootEndPosition:…...
程序持续内存泄漏问题定位参考
0 概括 本文用于记录 x86-Linux 应用程序发生持续性内存泄漏问题时的定位方法。主要介绍valgrind工具的应用。 1 原理 对于内存泄漏问题的定位,一种朴素的想法就是对内存申请点进行监控。对于一个内存申请调用点(例如c/c中的malloc函数)&a…...
Lumion 与 Enscape 怎么选?附川翔云电脑适配指南
建筑可视化领域,Lumion 和 Enscape 是两款主流实时渲染器,核心差异体现在操作逻辑、渲染特性及适用场景。结合川翔云电脑平台的硬件支持,可进一步优化使用体验。 一、核心差异:效率、操作与场景适配 1. 操作门槛与实时性 Lumio…...
WebShell详解:原理、分类、攻击与防御
目录 一、WebShell的定义与核心概念 二、WebShell的分类 三、WebShell的攻击原理与常见手法 1. 攻击原理 2. 常见攻击路径 四、WebShell的危害 五、防御与检测策略 六、总结 一、WebShell的定义与核心概念 WebShell是一种以ASP、PHP、JSP等网页脚本形式存在的恶…...
Ubuntu 24.04 中文输入法安装
搜狗输入法,在Ubuntu 24.04上使用失败,安装教程如下 https://shurufa.sogou.com/linux/guide 出现问题的情况,是这个帖子里描述的: https://forum.ubuntu.org.cn/viewtopic.php?t493893 后面通过google拼音输入法解决了&#x…...
数码视讯TR100系列/TR100-G1/TR100-G4/数码视讯F7-国科GK6323V100C芯片-刷机固件包
数码视讯TR100系列/数码视讯TR100-G1/数码视讯TR100-G4/数码视讯F7-国科GK6323V100C芯片-刷机固件包 刷机教程: 里面共有两种方法,一是TTL线刷烧录方法;二是卡刷固件包; 下面以数码视讯TR100-…...
Cloudflare教程:免费优化CDN加速配置,提升网站访问速度 | 域名访问缓存压缩视频图片媒体文件优化配置
1、启用 Tiered Cache 缓存开关:通过选择缓存拓扑,可以控制源服务器与 Cloudflare 数据中心的连接方式,以确保缓存命中率更高、源服务器连接数更少,并且 Internet 延迟更短。 2、增加浏览器缓存时间TTL:在此期间&#…...
24体育NBA足球直播M24模板自适应板源码
源码名称:体育直播赛事扁平自适应M24直播模板源码 开发环境:帝国cms7.5 空间支持:phpmysql 带软件采集,可以挂着自动采集发布,无需人工操作! 演示地址:https://www.52muban.com/shop/184022.h…...
dify+wan2.1搭建文生视频生成工具流
本文介绍在dify中使用阿里开源的Wan2.1 1.3B模型搭建文生视频工作流的方法。 使用的工具如下: 1、dify(官方:https://docs.dify.ai/zh-hans) 2、comfyui 一、comfyui安装 为了简单起见,本文介绍使用autodl完成comfyui的部署。在autodl创建实例,使用的镜像如下图: 大…...
C# js 判断table中tr否存在相同的值
html 中如: 实现:table数据表格中,点击删除按钮时,验证相同子订单号条数是否大于1,大于允许删除。保证数据表格中只有唯一的一条子订单号数据。 <table style"width: 100%; background-color: #fff;" ce…...
HTML5+CSS3小实例:纯CSS绘制七巧板
实例:纯CSS绘制七巧板 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…...
什么是虚拟线程?与普通线程的区别
引言:线程的演进与挑战 在传统的并发编程中,线程是一种非常重要的概念。我们使用线程来实现任务的并发执行,从而提高程序的执行效率。普通线程(如 Thread 类)是一种重量级的线程,每个线程都对应着操作系统…...
Docker MySQL的主从同步 数据备份 数据同步 配置文件
创建主库 docker run \--namemysql_1 \-e MYSQL_ROOT_PASSWORD123456 \-p 3306:3306 \-v mysql_main_data:/var/lib/mysql \--restart unless-stopped \-d \mysql:8.0进入容器内部 docker exec -it mysql_1 bash查找配置文件 find / -name my.cnf复制出主机 docker cp mysql…...
PowerBI中的DATEDIFF函数
一、语法 DATEDIFF(开始日期,结束日期,日期时间类型),返回两个日期之间的时间差 二、示例 开始日期结束日期度量值计算结果2025/4/1 15:33:202025/4/1 15:33:30计算 DATEDIFF([开始日期],[结束日期],SECOND)102025/4/1 15:332025/4/1 15:3…...
C/C++共有的类型转换与c++特有的四种强制类型转换
前言 C 语言和 C 共有的类型转换: 自动类型转换(隐式类型转换): 编译器在某些情况下会自动进行的类型转换。强制类型转换(显示类型转换): 使用 (type)expression 或 type(expression) 语法进行…...
体验OceanBase的 并行导入功能
在数据库的日常使用中,会经常遇到以下场景: 数据复制:将一个或多个表中的数据复制到目标表中,可能是复制全部数据,也可能仅复制部分数据。数据合并:将数据从一个表转移到另一个表,或者将多…...
CSS的字体
在 CSS 中,字体(font)是网页设计中的一个重要部分,它控制了文本的外观和排版效果。通过设置不同的字体属性,我们可以使网页上的文字更具吸引力和可读性。以下是与字体相关的 CSS 属性及其用法: 1️⃣ font…...
开源模型应用落地-LangChain与MCP协议-集成GPT-4o构建下一代AI智能体的全栈实践(三)
一、前言 在人工智能技术快速迭代的今天,大型语言模型(LLM)如何高效集成外部工具与多模态能力,成为开发者面临的核心挑战。Anthropic推出的模型上下文协议(MCP)通过标准化工具接口,为AI应用提供了“即插即用”的生态基础,而LangChain凭借其模块化设计,正成为连接LLM…...
Qt 5.14.2入门(一)写个Hello Qt!程序
目录 参考链接:一、新建项目二、直接运行三、修改代码增加窗口内容1、Qt 显示一个 QLabel 标签控件窗口2、添加按键 参考链接: Qt5教程(一):Hello World 程序 Qt 编程指南 一、新建项目 1、新建一个项目(…...
FPGA_DDR(二)
在下板的时候遇到问题 1:在写一包数据后再读,再写再读 这时候读无法读出 查看时axi_arready没有拉高 原因 : 由于读地址后没有拉高rready,导致数据没有读出卡死现象。 解决结果...
思科交换机配置
以下是交换机配置的详细步骤指南,适用于Cisco交换机,其他品牌需调整命令: 1. 初始连接与基本配置 连接方式:使用Console线连接交换机,通过终端软件(如PuTTY)登录。波特率:9600&…...
单链表——C语言实现
目录 一.相关指针知识点 二.链表 1.为什么学了顺序表还要学链表 2.优点 三.实现 1.链表的打印 —— 理解链表结构 (2) 物理结构图 2.链表的尾插 —— 入门 错误写法:tail ! NULL 总结: 正确代码物理图解: (2) 尾插整体代码 (思考…...
PostgreSQL插件生态全景解析:赋能数据库的无限可能
PostgreSQL以其开放的扩展生态闻名于世,其插件机制如同瑞士军刀般灵活,能够在不修改核心代码的前提下实现功能无限延伸。本文将基于多年内核开发经验,深度剖析PostgreSQL插件生态体系,为架构师与开发者提供全景式技术选型参考。 一…...
minio提供nfs服务
minio提供nfs服务 挂载minio为本地目录开机自动挂载使用supervisor实现开机自动挂载服务单元实现开机自动挂载minio为本地目录---失败 调试 挂载minio为本地目录 使用 Minio 作为后端存储,并通过 NFS 为客户端提供访问,那么你需要一个中间层来将 Minio …...
QML中的信号与槽机制
QML 中的信号与槽机制是 Qt 框架的核心特性之一,它提供了一种对象间通信的强大方式。与 C 中的信号槽类似,但语法更加简洁。 基本概念 1. 信号 (Signal) 当某个特定事件发生时由对象自动发出的通知 例如:按钮被点击时发出的 clicked 信号 …...
使用 Ktor 构建现代 Android 应用的后端服务
使用 Ktor 构建现代 Android 应用的后端服务 前言 在移动互联网时代,Android 应用对后端服务的实时性与性能要求越来越高,而传统的后端框架在一些场景中存在复杂度高、扩展性不足等问题。Ktor 作为 JetBrains 推出的异步 Web 框架,充分利用…...
leetcode_454. 四数相加 II_java
454. 四数相加 IIhttps://leetcode.cn/problems/4sum-ii/ 1、题目 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] …...
类名与协议名相同,开发中应该避免吗?
在 Objective-C 开发中,协议与实现类之间的命名关系非常重要。虽然语言允许协议名和类名相同,但从可读性和维护性等角度出发,这种做法并不推荐。本文通过一个典型示例展开分析,并提供更合理的命名建议。 一、示例 在某项目中&…...
环信鸿蒙版 UIKit 快速上手指南
环信鸿蒙版 UIKit 是专为 HarmonyOS 开发者设计的 IM UI 组件库,基于环信 IM SDK 开发,可帮助开发者快速集成即时通讯功能。 环信UIKit 的特点 ArkUI 声明式开发范式:采用高效简洁的声明式开发方式状态管理 V2:支持深度观测和精…...
编译freecad
git clone --recurse-submodules https://github.com/FreeCAD/FreeCAD.git freecad-source 手动安装 vscode 扩展安装cmake tool cmake ../ 缺什么装什么 Third Party Libraries - FreeCAD Documentation sudo apt install qt6-base-dev sudo apt install libyaml-cpp-dev …...
安卓Kotlin接入高德定位和地图SDK
前言:高德的定位sdk可以获取设备当前的详细信息,如经纬度,具体地址(省->街道)等, 本文主要使用的是定位sdk和地图sdk中的poi搜索功能(以当前位置半径多少米内的关键词搜索) 目录…...
JavaScript浅拷贝与深拷贝
目录 浅拷贝(Shallow Copy) 一、浅拷贝的定义 二、直接赋值 vs 浅拷贝 1. 直接赋值 2. 浅拷贝 三、数组的浅拷贝方法 1. slice() 2. concat() 3. 扩展运算符(...) 四、对象的浅拷贝方法 1. Object.assign() 2. 扩展运…...
智能生态之城-广东茂名
故事摘要 在中国广东茂名的未来社区,晨光中,垂直果园里发光的荔枝与智能无人机的早餐派送唤醒了城市的生活。在海底透明隧道的图书馆里,孩子们通过声控设备与虚拟生物互动。面对暴雨来临时,市民们积极参与到荔枝蜜饯制作和雨季造林…...
【Android】Android Activity 横屏设置详解及常见异常问题解决方法汇总
在 Android 开发中,我们经常需要控制 Activity 的屏幕方向,例如视频播放、游戏、VR/AR 应用等场景通常希望默认横屏显示。本文将讲解如何通过 Manifest 配置 和 Java/Kotlin 代码 设置横屏显示,并分析常见设置无效的原因与解决方法。 一、通过…...
Android 存储路径
一、内部存储路径(Internal Storage) stats.codeSize(内部代码大小) 路径:/data/app/com.example.test-{随机后缀}/base.apk 说明:APK 安装路径,包含应用代码…...
【12】数据结构之基于线性表的排序算法
目录标题 插入排序直接插入排序折半插入排序希尔排序 交换排序冒泡排序快速排序 归并排序时间复杂度对比最好情况平均情况最坏情况 空间复杂度对比 插入排序 基本思想:将一个元素插入到一个有序序列中,继而得到一个有序的元素个数加一的新序列. 直接插…...
解决RecyclerView在调用smoothScrollToPosition后最后一个item底部超出屏幕的问题
要解决RecyclerView在调用smoothScrollToPosition后最后一个item底部超出屏幕的问题,可以使用自定义的LinearSmoothScroller,使其底部对齐屏幕。步骤如下: 创建自定义的SmoothScroller类: 继承LinearSmoothScroller并重写getVerti…...
数字世界的免疫系统:恶意流量检测如何守护网络安全
在2023年全球网络安全威胁报告中,某跨国电商平台每秒拦截的恶意请求峰值达到217万次,这个数字背后是无数黑客精心设计的自动化攻击脚本。恶意流量如同数字世界的埃博拉病毒,正在以指数级速度进化,传统安全防线频频失守。这场没有硝烟的战争中,恶意流量检测技术已成为守护网…...
十分钟机器学习之--------------线性回归
线性回归(linear regression)是一种基于数学模型的算法,首先假设数据集与标签之间存在线性关系,然后简历线性模型求解参数。在实际生活中,线性回归算法因为其简单容易计算,在统计学经济学等领域都有广泛的应…...
常用 Excel VBA 技巧,简单好学易上手
在日常办公中,我们常常会遇到各种繁琐的数据处理任务,而 Excel VBA(Visual Basic for Applications)作为一款强大的自动化工具,能够帮助我们轻松应对这些挑战。本文将介绍一些常用且简单好学的 Excel VBA 技巧…...
第7篇:Linux程序访问控制FPGA端LEDR<五>
Q:如何设计.c程序代码实现FPGA端外设LEDR流水灯? A:在DE1-SoC开发板上实现的流水灯效果:一次只点亮一个红色LED,初始状态为向左移动直至点亮LEDR9,然后改变移动的方向为向右直至点亮LEDR0,以此…...