You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式Linux下如何实现web服务器与本地C应用的数据交互

实现方案整体思路

thttpd原生支持CGI程序,你可以通过CGI作为中间层完成web前端和本地C串口应用的通信,配合HTTP短轮询即可实现串口返回数据的页面实时刷新,整个方案资源占用极低,非常适配嵌入式Linux场景。

具体实现步骤

1. 选定进程间通信方式

本地UART C应用和CGI是两个独立进程,选以下任意一种简单方案即可:

  • 命名管道(FIFO):实现难度最低,单向读写就能满足需求,资源占用极小,嵌入式场景优先选这个
  • Unix域套接字:支持全双工通信,后续要扩展功能的话更灵活

2. 改造现有UART C应用

在原有串口处理逻辑的基础上增加通信监听逻辑即可:

  • 启动时创建两个命名管道,分别用于串口发送、接收方向的数据传输,可以直接调用mkfifo()函数实现,也可以启动脚本里先执行mkfifo /tmp/uart_tx_fifo 0666和mkfifo /tmp/uart_rx_fifo 0666
  • 开独立线程监听发送管道的读端,收到数据后直接调用现有串口发送函数写入UART
  • 开另一个独立线程监听UART读端,收到串口返回的数据后写入接收管道,或者直接写入临时文件缓存也可以

核心代码示例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

// 你现有串口操作函数的声明
extern int uart_send(char *buf, int len);
extern int uart_recv(char *buf, int len);

int main(void) {
    // 创建命名管道
    mkfifo("/tmp/uart_tx_fifo", 0666);
    mkfifo("/tmp/uart_rx_fifo", 0666);

    // 监听发送管道,转发数据到串口
    int tx_fd = open("/tmp/uart_tx_fifo", O_RDONLY);
    char tx_buf[256] = {0};
    while(1) {
        int rx_len = read(tx_fd, tx_buf, sizeof(tx_buf));
        if(rx_len > 0) {
            uart_send(tx_buf, rx_len);
            memset(tx_buf, 0, sizeof(tx_buf));
        }
    }

    // 监听串口,转发返回数据到接收管道
    int rx_fd = open("/tmp/uart_rx_fifo", O_WRONLY);
    char rx_buf[256] = {0};
    while(1) {
        int recv_len = uart_recv(rx_buf, sizeof(rx_buf));
        if(recv_len > 0) {
            write(rx_fd, rx_buf, recv_len);
            memset(rx_buf, 0, sizeof(rx_buf));
        }
    }
    return 0;
}

3. 编写CGI程序对接thttpd

thttpd默认支持CGI,把编译好的CGI程序放到配置的cgi-bin目录下即可:

处理表单提交的CGI(uart_send.cgi)

负责解析前端表单提交的数据,写入发送管道:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

int main(void) {
    char *content_len = getenv("CONTENT_LENGTH");
    int len = atoi(content_len);
    char req_buf[256] = {0};
    fread(req_buf, 1, len, stdin);

    // 解析表单字段,假设表单输入框的name属性为uart_data
    char *uart_data = strstr(req_buf, "uart_data=") + 9;
    // 处理URL编码的话可以自己加解码逻辑,纯ASCII字符可以直接传输

    int fd = open("/tmp/uart_tx_fifo", O_WRONLY);
    write(fd, uart_data, strlen(uart_data));
    close(fd);

    // 返回HTTP响应
    printf("Content-Type: text/plain\r\n\r\n");
    printf("ok");
    return 0;
}

读取串口返回数据的CGI(uart_recv.cgi)

负责读取接收管道的内容,返回给前端:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(void) {
    int fd = open("/tmp/uart_rx_fifo", O_RDONLY | O_NONBLOCK);
    char buf[256] = {0};
    int len = read(fd, buf, sizeof(buf));
    close(fd);

    printf("Content-Type: text/plain\r\n\r\n");
    if(len > 0) printf("%s", buf);
    else printf("");
    return 0;
}

4. 编写前端页面

  • 写一个POST表单,提交地址指向/cgi-bin/uart_send.cgi,输入框name设置为uart_data
  • 前端加JS定时器,每隔1-2秒请求一次/cgi-bin/uart_recv.cgi,拿到返回值后更新页面DOM,就可以实现数据实时刷新的效果

5. 配置注意事项

  • 给两个命名管道设置0666权限,避免thttpd运行用户没有读写权限
  • 如果thttpd默认没开启CGI,启动时加上参数-c /cgi-bin/*即可,指定该目录下的所有文件按CGI程序执行
  • cgi-bin目录要给thttpd运行用户开放执行权限

内容的提问来源于stack exchange,提问作者AlexB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 09:57:05