关于 mini_httpd(web server) 调用 CGI 进程(脚本) 写终端问题

本文探讨了mini_httpd作为组长进程的特点及其调用的cgi子进程如何受到Linux主机进程组策略的影响,导致无法直接写入终端的问题。此外,还讨论了mini_httpd通过select-accept-fork模型处理HTTP请求的具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为 LINUX 主机的进程组策略,完全严格的 Daemon 进程无法写终端。

当一个进程既不是它自身的父进程,同时它也不是组长进程的时候,它就是严格的的 daemon 进程。

    mini_httpd 本身并不是严格的 daemon 进程。它是一个组长进程。

但是 mini_httpd 调用的 cgi 进程,就不是组长进程,它是 mini_httpd 进程组中的一个进程。

所以 cgi 在获取终端 fd 的时候会失败,内核会发送一个信号。如果不对信号进行处理的话,默认情况下进程将结束。

 


 

在具体的是实现细节上:

mini_httpd 使用 select->accept->fork 模型。

在子进程中 handle HTTP 请求(TCP socket),子进程进行必要的处理之后,将 STDOUT,STDIN 做了 dup2 修改(具体绑定到 socket 上还是 pipe 上我没有仔细研究)。因此继续往下运行,再调用 exec 系的函数,切换执行 cgi 程序,cgi 程序的标准输出即等同于 TCP socket 的 payload,即输出就是 HTTP 整个协议头+正文内容。

所以 cgi 程序也不能通过直接输出到终端的方式来 debug。

 

 Reference: AUPE

在 lwIP 中,`LWIP_HTTPD_CGI_SSI` 是一个用于启用 HTTP 服务器中 CGI(通用网关接口)和 SSI(服务器端包含)功能的配置选项。该功能允许动态生成网页内容并嵌入静态 HTML 文件中,从而实现更灵活的 Web 服务响应机制。 当 `LWIP_HTTPD_CGI_SSI` 被启用时,HTTP 服务器会支持通过 CGI 脚本处理客户端请求,并且可以解析 SSI 指令以动态插入内容[^1]。为了使用这一功能,需要在 `lwipopts.h` 或类似的配置头文件中定义以下宏: ```c #define LWIP_HTTPD_CGI_SSI 1 ``` 此外,还需要定义 `LWIP_HTTPD_SSI` 和 `LWIP_HTTPD_CGI` 来分别启用 SSI 和 CGI 功能[^2]: ```c #define LWIP_HTTPD_SSI 1 #define LWIP_HTTPD_CGI 1 ``` ### 新式 CGI 的使用 新式 CGI 支持通过 URL 参数触发特定函数,并将参数传递给这些函数以生成动态内容。用户需要注册 CGI 处理函数,通常是在初始化 HTTP 服务器时进行设置。例如,可以通过 `http_set_cgi_handler` 函数来注册 CGI 处理程序: ```c void httpd_init(void) { struct tcp_pcb *pcb; pcb = tcp_new(); tcp_bind(pcb, IP_ADDR_ANY, 80); pcb = tcp_listen(pcb); tcp_accept(pcb, httpd_accept); /* 注册 CGI 处理函数 */ http_set_cgi_handlers(&cgi_handlers, num_handlers); } ``` 其中 `cgi_handlers` 是一个结构体数组,每个元素都指定了一个 URL 路径以及对应的处理函数: ```c const tCGI cgi_handlers[] = { {"/cgi-bin/example", example_cgi_handler}, }; ``` 处理函数需要按照指定的原型编,以便接收请求参数并返回适当的内容类型: ```c const char *example_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) { // 处理逻辑 return "text/html"; } ``` ### SSI 的使用 SSI 允许在静态 HTML 文件中嵌入动态内容。为了启用 SSI,除了定义 `LWIP_HTTPD_SSI` 外,还需要提供一个 SSI 解析函数。这个函数会在遇到 `<!--#include virtual="/path/to/file.shtml" -->` 这样的指令时被调用: ```c char *ssi_handler(int ssi_id, uint8_t *ptr, uint16_t len) { switch (ssi_id) { case 0: strcpy(ptr, "Dynamic content"); break; default: break; } return ptr; } ``` 在 HTTP 服务器初始化时,需要将 SSI 解析函数注册到系统中: ```c void httpd_init(void) { http_set_ssi_handler(ssi_handler, (const char **)&tags, NUM_SSI_TAGS); } ``` 其中 `tags` 是一个字符串数组,包含了所有需要替换的 SSI 标签名称: ```c const char *tags[] = { "dynamic_content" }; ``` ### 配置建议 - **内存管理**:由于 CGI 和 SSI 都可能涉及动态内容生成,因此需要注意内存使用的优化,尤其是在资源受限的嵌入式系统中。 - **安全性**:确保 CGI 脚本不会暴露敏感信息或执行危险操作。可以通过限制输入长度、验证输入数据等方式提高安全性。 - **性能优化**:对于频繁访问的页面,可以考虑缓存生成结果以减少重复计算带来的开销。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值