尧图网络科技 Logo 尧图网络科技
  • 首页
  • 关于我们
  • 建站服务
  • UI 设计
  • 案例展示
  • SEO 优化
  • 资讯中心
  • 联系我们

资讯详情

深度解读 · 专业分析

  • 首页
  • 资讯中心
  • /
  • lsh 的源码注释(1)

最新资讯

  • 全部资讯
  • 行业动态
  • UI 设计
  • SEO 优化
  • 网站开发

lsh 的源码注释(1)

📅 发布时间:2026/6/19 10:46:10 👁 浏览次数:
lsh 的源码注释(1)

lsh 的源码注释(1)

我正在通过 git@github.com:brenns10/lsh 这个项目学习如何实现一个 Shell。今天为源码添加了第一遍注释。

还有很多问号hhh

/***************************************************************************//**@file         main.c@author       Stephen Brennan@date         Thursday,  8 January 2015@brief        LSH (Libstephen SHell)*******************************************************************************/#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>/*Function Declarations for builtin shell commands:*/
int lsh_cd(char **args);
int lsh_help(char **args);
int lsh_exit(char **args);/*List of builtin commands, followed by their corresponding functions.*/
char *builtin_str[] = {"cd","help","exit"
};int (*builtin_func[]) (char **) = {&lsh_cd,&lsh_help,&lsh_exit
};int lsh_num_builtins() {return sizeof(builtin_str) / sizeof(char *);
}/*Builtin function implementations.
*//**@brief Builtin command: change directory.@param args List of args.  args[0] is "cd".  args[1] is the directory.@return Always returns 1, to continue executing.*/
// lsh 内置的函数中,只有 cd 是执行了有效功能的(help 用来打印帮助,exit 用于退出)
// 看起来 cd 命令使用的是 chdir 函数实现的功能
// 在 chdir 函数执行失败时(返回值不为 0 时),还会调用 perror 来打印错误信息
// 该函数总是返回 1,这是因为每个 builtin_func 都应该返回 int 值,这一点在 lsh_execute 的注释中解释过
int lsh_cd(char **args)
{if (args[1] == NULL) {fprintf(stderr, "lsh: expected argument to \"cd\"\n");} else {// 这个 chdir 是外部函数,是哪个库中的?if (chdir(args[1]) != 0) {// 这个 perror 函数也是外部的,是哪个库中的?perror("lsh");}}return 1;
}/**@brief Builtin command: print help.@param args List of args.  Not examined.@return Always returns 1, to continue executing.*/
int lsh_help(char **args)
{int i;printf("Stephen Brennan's LSH\n");printf("Type program names and arguments, and hit enter.\n");printf("The following are built in:\n");for (i = 0; i < lsh_num_builtins(); i++) {printf("  %s\n", builtin_str[i]);}printf("Use the man command for information on other programs.\n");return 1;
}/**@brief Builtin command: exit.@param args List of args.  Not examined.@return Always returns 0, to terminate execution.*/
// lsh_exit 通过返回 0 来使 REPL 终止,原因在 lsh_execute 的注释中有解释
int lsh_exit(char **args)
{return 0;
}/**@brief Launch a program and wait for it to terminate.@param args Null terminated list of arguments (including program).@return Always returns 1, to continue execution.*/
int lsh_launch(char **args)
{pid_t pid;int status;// 这里使用 fork 克隆了一个子进程pid = fork();// 克隆成功(pid == 0)后,使用 execvp 函数执行参数列表// 这个 execvp 看来也是外部函数了。它可以调用将参数列表传给 bash 执行?// 不对,并不是“传给bash”,bash 脚本的重定向和管道功能,lsh 并不能使用。// 那么 execvp 的作用究竟是什么?if (pid == 0) {// Child processif (execvp(args[0], args) == -1) {perror("lsh");}exit(EXIT_FAILURE);} else if (pid < 0) {// 子进程 fork 失败,直接报错。// 话说,这个情况该怎么复现呢?怎么手动使子进程 fork 失败?// Error forkingperror("lsh");} else {// 这里处理 pid > 0 的情况,似乎在等待父进程?等待什么呢?// 等待的过程中,执行了 waitpid 函数,也是一个外部函数。// waitpid 函数会修改状态码 status,而 WIFEXITED 宏和 WIFSIGNALED 宏会检测 status// 这两个宏并没有在本文件中定义o,不过看起来是检测状态码是否代表 exited 和 signaled 的// Parent processdo {waitpid(pid, &status, WUNTRACED);} while (!WIFEXITED(status) && !WIFSIGNALED(status));}return 1;
}/**@brief Execute shell built-in or launch program.@param args Null terminated list of arguments.@return 1 if the shell should continue running, 0 if it should terminate该函数的返回值为 0 时,REPL 终止因此,无论它返回 1、函数指针还是其他非假值,REPL 都将继续*/
int lsh_execute(char **args)
{int i;// 没有输入if (args[0] == NULL) {// An empty command was entered.return 1;}// 遍历匹配命令// 命令的执行函数存放在一个函数指针数组 builtin_func 中,// 使用时只需要传入 args 就行for (i = 0; i < lsh_num_builtins(); i++) {if (strcmp(args[0], builtin_str[i]) == 0) {// 匹配到就调用对应的函数指针,这个函数指针显然是一定返回 int 值的return (*builtin_func[i])(args);}}// 没有匹配到就返回 lsh_launch 函数的返回值,这个函数返回一个 int 值// lsh_launch 函数似乎就是用来打印命令不存在的报错值的,为什么还需要传入 args ?为什么里面还需要开子进程?// 原来,没有匹配到内置命令,lsh_launch 就会将参数作为 bash 的命令运行,所以 pwd、cp、rm 这样的命令仍然可以在 lsh 中使用。// 但这是怎么做到的呢?return lsh_launch(args);
}/**@brief Read a line of input from stdin.@return The line from stdin.*/
char *lsh_read_line(void)
{
#ifdef LSH_USE_STD_GETLINEchar *line = NULL;ssize_t bufsize = 0; // have getline allocate a buffer for usif (getline(&line, &bufsize, stdin) == -1) {if (feof(stdin)) {exit(EXIT_SUCCESS);  // We received an EOF} else  {perror("lsh: getline\n");exit(EXIT_FAILURE);}}return line;
#else
#define LSH_RL_BUFSIZE 1024int bufsize = LSH_RL_BUFSIZE;int position = 0;char *buffer = malloc(sizeof(char) * bufsize);int c;if (!buffer) {fprintf(stderr, "lsh: allocation error\n");exit(EXIT_FAILURE);}while (1) {// Read a characterc = getchar();if (c == EOF) {exit(EXIT_SUCCESS);} else if (c == '\n') {buffer[position] = '\0';return buffer;} else {buffer[position] = c;}position++;// If we have exceeded the buffer, reallocate.if (position >= bufsize) {bufsize += LSH_RL_BUFSIZE;buffer = realloc(buffer, bufsize);if (!buffer) {fprintf(stderr, "lsh: allocation error\n");exit(EXIT_FAILURE);}}}
#endif
}#define LSH_TOK_BUFSIZE 64
#define LSH_TOK_DELIM " \t\r\n\a"
/**@brief Split a line into tokens (very naively).@param line The line.@return Null-terminated array of tokens.*/
char **lsh_split_line(char *line)
{int bufsize = LSH_TOK_BUFSIZE, position = 0;char **tokens = malloc(bufsize * sizeof(char*));char *token, **tokens_backup;if (!tokens) {fprintf(stderr, "lsh: allocation error\n");exit(EXIT_FAILURE);}token = strtok(line, LSH_TOK_DELIM);while (token != NULL) {tokens[position] = token;position++;if (position >= bufsize) {bufsize += LSH_TOK_BUFSIZE;tokens_backup = tokens;tokens = realloc(tokens, bufsize * sizeof(char*));if (!tokens) {free(tokens_backup);fprintf(stderr, "lsh: allocation error\n");exit(EXIT_FAILURE);}}token = strtok(NULL, LSH_TOK_DELIM);}tokens[position] = NULL;return tokens;
}/**@brief Loop getting input and executing it.*/
void lsh_loop(void)
{char *line;char **args;int status;do {printf("> ");line = lsh_read_line();args = lsh_split_line(line);status = lsh_execute(args);free(line);free(args);} while (status);
}/**@brief Main entry point.@param argc Argument count.@param argv Argument vector.@return status code*/
int main(int argc, char **argv)
{// Load config files, if any.// Run command loop.lsh_loop();// Perform any shutdown/cleanup.return EXIT_SUCCESS;
}

相关新闻

Codeforces Round 1056 (Div. 2) A~D

Codeforces Round 1056 (Div. 2) A~D

2026/6/19 0:08:26 查看详情
某中心在旧金山设立AGI实验室专注长期AI研究

某中心在旧金山设立AGI实验室专注长期AI研究

2026/6/18 0:12:00 查看详情
微算法科技(NASDAQ:MLGO)开发延迟和隐私感知卷积神经网络分布式推理,助力可靠人工智能系统技术

微算法科技(NASDAQ:MLGO)开发延迟和隐私感知卷积神经网络分布式推理,助力可靠人工智能系统技术

2026/6/18 3:48:05 查看详情
2026宁波黄金回收门店实力测评榜单|收的顶五星断层领跑 - 奢侈品回收测评

2026宁波黄金回收门店实力测评榜单|收的顶五星断层领跑 - 奢侈品回收测评

2026/6/19 10:43:22 查看详情
如何免费获取119,376个英语单词发音MP3音频的完整指南

如何免费获取119,376个英语单词发音MP3音频的完整指南

2026/6/19 10:43:22 查看详情
SMUDebugTool终极指南:解锁AMD Ryzen处理器隐藏性能的完整教程

SMUDebugTool终极指南:解锁AMD Ryzen处理器隐藏性能的完整教程

2026/6/19 10:43:10 查看详情
容器化部署 vLLM,Docker 镜像构建与优化

容器化部署 vLLM,Docker 镜像构建与优化

2026/6/19 10:43:22 查看详情
2026黄南本地连锁黄金回收,承接铂金回收白银银条回收业务+公安备案门店 - 信誉隆金银铂奢回收

2026黄南本地连锁黄金回收,承接铂金回收白银银条回收业务+公安备案门店 - 信誉隆金银铂奢回收

2026/6/19 10:41:13 查看详情
解密Windows内核级硬件伪装技术:EASY-HWID-SPOOFER深度解析与实战指南

解密Windows内核级硬件伪装技术:EASY-HWID-SPOOFER深度解析与实战指南

2026/6/19 10:41:13 查看详情
行星盘动力学与分子谱线诊断技术解析

行星盘动力学与分子谱线诊断技术解析

2026/6/19 0:01:24 查看详情
2026年成都GEO优化机构怎么选?全维度实用指南 - 刘向阳而生

2026年成都GEO优化机构怎么选?全维度实用指南 - 刘向阳而生

2026/6/19 0:01:39 查看详情
Akagi终极指南:5分钟掌握智能麻将AI助手的完整使用教程

Akagi终极指南:5分钟掌握智能麻将AI助手的完整使用教程

2026/6/19 0:01:39 查看详情
从Landsat到高分系列:手把手教你选择适合自己项目的遥感卫星数据

从Landsat到高分系列:手把手教你选择适合自己项目的遥感卫星数据

2026/6/18 19:44:15 查看详情
福州空调维修上门加氟移机空调不制冷、推荐本地老牌鑫盛达、冷顺安 - 我叫一

福州空调维修上门加氟移机空调不制冷、推荐本地老牌鑫盛达、冷顺安 - 我叫一

2026/6/18 22:29:08 查看详情
嵌入式调试器组件化界面与拖拽交互技术详解

嵌入式调试器组件化界面与拖拽交互技术详解

2026/6/18 22:19:33 查看详情
YOLOv11涨点改进| CVPR 2026 | 独家创新首发、特征融合改进篇| 引入CMGF 引导特征融合机制,实现对不同模态特征的自适应增强与高效融合,助力多模态目标检测,小目标检测或分割有效涨点

YOLOv11涨点改进| CVPR 2026 | 独家创新首发、特征融合改进篇| 引入CMGF 引导特征融合机制,实现对不同模态特征的自适应增强与高效融合,助力多模态目标检测,小目标检测或分割有效涨点

2026/6/18 22:29:00 查看详情
E-E-A-T 成第一权重:2027 年无经验内容将被彻底淘汰

E-E-A-T 成第一权重:2027 年无经验内容将被彻底淘汰

2026/6/18 23:21:38 查看详情
深圳福田园岭老小区搬家公司推荐 经验足师傅高效搬运攻略 - 从来都是英雄出少年

深圳福田园岭老小区搬家公司推荐 经验足师傅高效搬运攻略 - 从来都是英雄出少年

2026/6/18 22:29:04 查看详情

关于尧图

立足北京本地的一站式网站建设服务与设计教学平台,深耕企业网站定制开发、全网 SEO 优化及网络推广服务。

快速链接

  • 关于我们
  • 建站服务
  • 案例展示
  • 资讯中心

服务项目

  • 企业官网定制
  • UI 界面设计
  • SEO 优化推广
  • 移动端适配

联系方式

电话:400-XXX-XXXX

邮箱:info@zskr.cn

地址:北京市朝阳区 XXX 路 XX 号

© 2026 尧图网络科技 版权所有 | 京 ICP 备 XXXXXXXX 号