• 正文
    • 1、交叉編譯目標(biāo)板ELF 1S的boa
    • 2、boa配置
    • 通過網(wǎng)頁控制ELF 1S
  • 推薦器件
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

i.MX6ULL—ElfBoard Elf1板卡 移植boa服務(wù)器的方法

2023/11/17
2249
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大家好,我是雜燴君。

之前,我們介紹了一款面向嵌入式初學(xué)者、愛好者、單片機(jī)進(jìn)階學(xué)習(xí)的學(xué)習(xí)者的開發(fā)板——ELF 1S。本篇文章我們基于ELF 1S開發(fā)板移植Boa服務(wù)器的方法。

Boa

boa 是一個(gè)小巧的web 服務(wù)器,可執(zhí)行代碼只有70KB,占用的系統(tǒng)資源少,速度快安全性能高。

boa官網(wǎng):www.boa.org

我們本次下載的版本:boa-0.94.13.tar.gz

1、交叉編譯目標(biāo)板ELF 1S的boa

下載得到boa-0.94.13.tar.gz,解壓后進(jìn)入boa-0.94.13/src目錄,執(zhí)行如下命令生成Makefile文件:

./configure

修改 Makefile, 設(shè)置交叉編譯器 。找到 CC 和 CPP 變量 ,修改為:

CC?=?arm-linux-gnueabihf-gcc?
CPP?=?arm-linux-gnueabihf-gcc?-E

執(zhí)行make編譯。編譯報(bào)錯(cuò)如:

把boa-0.94.13/src/compat.h ?文件里的:

#define?TIMEZONE_OFFSET(foo)?foo##->tm_gmtoff?

修改為:

#define?TIMEZONE_OFFSET(foo)?foo->tm_gmtoff?

再次編譯,可以編譯通過,并且會在當(dāng)前路徑下生成boa可執(zhí)行文件:

2、boa配置

編譯完之后,還需要在我們的開發(fā)板上針對boa做一些必要的配置。

把主機(jī)/etc 目錄下的 mime.types 文件傳到開發(fā)板的/etc目錄下。注:這是MIME(多用途因特網(wǎng)郵件擴(kuò)展),這是web服務(wù)器支持的規(guī)范。

scp?/etc/mime.types?root@192.168.3.36:/etc

在開發(fā)板/etc目錄下創(chuàng)建boa文件夾(用于存放boa的配置文件及l(fā)og文件):

cd?/etc
mkdir?boa

在開發(fā)板根目錄下建立 www 文件夾 ?,www 目錄下面建立文件夾 cgi-bin 目錄 (用于存放后期頁面及交互代碼):

mkdir?-p?/www/cgi-bin

把boa-0.94.13目錄下的boa.conf 文件傳到開發(fā)板的/etc/boa目錄下。

scp?boa.conf?root@192.168.3.36:/etc/boa

把boa 可執(zhí)行程序傳到開發(fā)板的 bin 目錄下 。

scp?boa?root@192.168.3.36:/bin

在開發(fā)板/etc目錄下創(chuàng)建group文件:

cd?/etc
touch?group

在開發(fā)板上使用vi編輯器打開/etc/boa目錄下的boa.conf文件,需要做如下修改:

① 把里面的Group nogroup 改為Group 0 ?。

②把ErrorLog ?和 AccessLog 這兩行, 指定 log 文件的路徑,把log保存到/etc/boa目錄下,修改如下:

ErrorLog?/etc/boa/error_log
#?Please?NOTE:?Sending?the?logs?to?a?pipe?('|'),?as?shown?below,
#??is?somewhat?experimental?and?might?fail?under?heavy?load.
#?"Usual?libc?implementations?of?printf?will?stall?the?whole
#??process?if?the?receiving?end?of?a?pipe?stops?reading."
#ErrorLog?"|/usr/sbin/cronolog?--symlink=/var/log/boa/error_log?/var/log/boa/error-%Y%m%d.log"

#?AccessLog:?The?location?of?the?access?log?file.?If?this?does?not
#?start?with?/,?it?is?considered?relative?to?the?server?root.
#?Comment?out?or?set?to?/dev/null?(less?effective)?to?disable
#?Access?logging.

AccessLog?/etc/boa/access_log

③ 把#ServerName www.your.org.here這一行, 修改為ServerName www.your.org.here

#?ServerName:?the?name?of?this?server?that?should?be?sent?back?to
#?clients?if?different?than?that?returned?by?gethostname?+?gethostbyname

ServerName?www.your.org.here

④ 然后找到DocumentRoot /var/www這一行, 修改為DocumentRoot /www

DocumentRoot?/www

⑤ 然后找到ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/這一行, 修改為ScriptAlias /cgi-bin/ /www/cgi-bin/

ScriptAlias?/cgi-bin/?/www/cgi-bin/

上面就是boa.conf配置文件需要修改的幾點(diǎn)內(nèi)容。

最后,進(jìn)入我們前面創(chuàng)建的 www 目錄, 然后使用 vi index.html 命令建立 index.html 網(wǎng)頁文件進(jìn)行測試,關(guān)于簡單網(wǎng)頁的設(shè)計(jì)大家可以上網(wǎng)搜一些教程。這里我們設(shè)計(jì)一個(gè)簡單的網(wǎng)頁如:

<html>
?<head>
??<meta?http-equiv="Content-Type"?content="text/html;charset=utf-8"/>
??<title>
??boa服務(wù)器測試
??</title>
?</head>
?<body?style="background-color:#000000;padding-left:300px;?padding-top:100px;">
??<p?style="color:white;?text-align:left;?width:1900px;?height:45px;?font-size:30px;?font-family:微軟雅黑;?padding-left:5px;">ElfBoard,讓嵌入式學(xué)習(xí)釋放無限可能</p>
??<p?style="color:yellow;?font-size:20px;?font-family:微軟雅黑;?text-align:left;">ELF是Embedded Learning Fans嵌入式學(xué)習(xí)愛好者的首字母縮寫。ELF也是精靈的意思,ElfBoard以靈動(dòng)的精靈形象作為品牌Logo,代表著自由、智慧和科技,也寓意學(xué)習(xí)者能夠像精靈一樣自由地掌握技術(shù),發(fā)揮無限創(chuàng)造力。</p>
?</body>
</html>

保存 index.html。

到了這一步我們的web服務(wù)器就大致搭建完成了,服務(wù)器上有一個(gè)簡單的網(wǎng)頁文件index.html。

下面進(jìn)行簡單的測試:

在我們的ELF 1S開發(fā)板上輸入boa 命令啟動(dòng) web 服務(wù)器 。

輸入 如下命令查看boa程序是否啟動(dòng)成功:

ps?-e?|?grep?"boa"

boa 進(jìn)程啟動(dòng)成功后,在瀏覽器中輸入我們開發(fā)板的 IP 地址就可以訪問到 index.html 網(wǎng)頁:

通過網(wǎng)頁控制ELF 1S

上一節(jié),我們已經(jīng)搭建好了基于boa的服務(wù)器,可以通過瀏覽器來訪問我們開發(fā)板上設(shè)計(jì)好的網(wǎng)頁。這一節(jié)我們使用網(wǎng)頁來控制我們ELF 1S板上的LED。

我們要通過網(wǎng)頁來點(diǎn)燈,設(shè)備端需要一個(gè)程序來解析網(wǎng)頁下發(fā)的點(diǎn)燈操作,即這個(gè)程序叫做CGI程序。

1、什么是CGI?

CGI即通用網(wǎng)關(guān)接口(Common Gateway Interface),是一個(gè)Web服務(wù)器主機(jī)提供信息服務(wù)的標(biāo)準(zhǔn)接口。通過CGI接口,Web服務(wù)器就能夠獲取客戶端提交的信息,轉(zhuǎn)交給服務(wù)器端的CGI程序進(jìn)行處理,最后返回結(jié)果給客戶端。

根據(jù)CGI標(biāo)準(zhǔn),編寫外部擴(kuò)展應(yīng)用程序,可以對客戶端瀏覽器輸入的數(shù)據(jù)進(jìn)行處理,完成客戶端與服務(wù)器的交互操作。CGI規(guī)范定義了Web服務(wù)器如何向擴(kuò)展應(yīng)用程序發(fā)送消息,在收到擴(kuò)展應(yīng)用程序的信息后又如何進(jìn)行處理等內(nèi)容。

一般情況下,服務(wù)器和CGI程序之間是通過標(biāo)準(zhǔn)輸入輸出來進(jìn)行數(shù)據(jù)傳遞的,CGI程序中的標(biāo)準(zhǔn)輸出stdout是經(jīng)過重定義了的,它并沒有在服務(wù)器上產(chǎn)生任何的輸出內(nèi)容,而是被重定向到客戶瀏覽器。即我們的CGI程序是在我們的板子服務(wù)器里運(yùn)行,但實(shí)際調(diào)用printf輸出信息時(shí)并不會輸出到我們的板子終端,而是輸出到客戶端瀏覽器。

2、CGI程序小例子

CGI程序可以使用多種語言來實(shí)現(xiàn),這里我們選用我們比較熟悉的C語言來實(shí)現(xiàn)。先來看一個(gè)簡單的示例:

test.c:

#include?<stdio.h>

int?main()
?{
????printf("Content-type:?text/htmlnn")?;??//?這一句是必須的,設(shè)定輸出到HTML
????printf("Hello?CGIn")?;
????return?0;
}

利用交叉編譯工具,編譯上述文件:

arm-linux-gnueabihf-gcc?test.c?-o?test.cgi

把test.cgi程序傳到開發(fā)板上的/www/cgi-bin目錄:

scp?test.cgi?root@192.168.3.36:/www/cgi-bin

在ELF 1S板子上修改test.cgi權(quán)限:

chmod?777?test.cgi

瀏覽器進(jìn)行訪問:

http://192.168.3.36/cgi-bin/test.cgi

3、網(wǎng)頁控制ELF 1S板上的LED

我們已經(jīng)知道了CGI程序是什么了。下面我們來進(jìn)行網(wǎng)頁點(diǎn)燈。首先,需要說明的是,我們有兩種方式來編寫CGI程序。一種是借助環(huán)境變量來獲取相關(guān)信息;另一種是使用CGIC庫。

方法一:

對于CGI程序來說,它繼承了系統(tǒng)的環(huán)境變量。CGI環(huán)境變量在CGI程序啟動(dòng)時(shí)初始化,在結(jié)束時(shí)銷毀。當(dāng)一個(gè)CGI程序不是被服務(wù)器調(diào)用時(shí),它的環(huán)境變量幾乎是系統(tǒng)環(huán)境變量的復(fù)制。當(dāng)這個(gè)CGI程序被服務(wù)器調(diào)用時(shí),它的環(huán)境變量就會多了以下關(guān)于服務(wù)器、客戶端、CGI傳輸過程等項(xiàng)目。如:

方法二:

用C語言寫CGI程序還可以有比較簡單的方式,那就是我們可以借助使用第三方庫CGIC(CGIC是一個(gè)功能比較強(qiáng)大的支持CGI開發(fā)的標(biāo)準(zhǔn)C庫,并支持Linux, Unix 和Windows等多操作系統(tǒng))來編寫,省去了必須自己去遵循CGI規(guī)范來編碼的痛苦。

CGIC庫下載地址:

https://github.com/boutell/cgic

這里只是簡單地介紹了兩種方法。還不理解沒關(guān)系,下面我們通過具體的實(shí)例來認(rèn)識這兩種方法。

首先,我們需要點(diǎn)燈,自然需要先設(shè)計(jì)一個(gè)簡單的led.html網(wǎng)頁。我們要通過網(wǎng)頁控制開發(fā)板上的led,需要兩條信息:led的序號及l(fā)ed的狀態(tài)。在網(wǎng)上找到了現(xiàn)成的html代碼,稍微修改一下就直接拿來用了(文末給出參考的博客)。

led.html:

<html?xmlns="http://www.w3.org/1999/xhtml">
?<head>
?<meta?http-equiv="Content-Type"?content="text/html;?charset=utf-8"?/>????
?<title>led?control</title>
?</head>
?
?<body>
?<h1?align="center">基于ELF?1S?+?boa的遠(yuǎn)程控制系統(tǒng)</h1>
??<!--新建一個(gè)表單,動(dòng)作鏈接到開發(fā)板的/cgi-bin/led.cgi,采用的方法為GET-->?
??<form?action="/cgi-bin/led.cgi"?method="get">??
???<p?align="center">請輸入需要控制的led編號?<input?type="text"?name="led_num"/></p>
???<p?align="center">請輸入控制led的狀態(tài)?<input?type="text"?name="led_state"/></p>
???<p?align="center"><input?type="submit"?value="確認(rèn)"/>????????
?????????<input?type="reset"?value="返回"/>
???</p>
??</form>
?</body>
</html>

把led.html放到我們開發(fā)板上的/www/中,通過瀏覽器訪問:

http://192.168.3.36/led.html

這個(gè)led.html需要依賴板子上的led.cgi程序。

下面我們編寫我們的led.cgi程序。

方法一:借助環(huán)境變量來獲取相關(guān)信息。

#include<stdio.h>
#include?<stdlib.h>
#include?<sys/types.h>
#include?<sys/stat.h>
#include?<fcntl.h>
#include?<unistd.h>
#include?<sys/ioctl.h>
#include?<linux/limits.h>
#include?<errno.h>

int?main(int?argc,?const?char?*argv[])
{
?int?led_num,led_state;
?char?*data;

????printf("Content-type:?text/html;charset=utf-8nn");
????printf("<html>n");
????printf("<head><title>cgi?control?led?web</title></head>n");
????printf("<body>n");
????printf("<p>led?is?setted?successful!?you?can?watch?the?led's?change</p>n");
????printf("<p><a?herf=led.html><button>get?back</button></a></p>n");
????printf("</body>n");

????data?=?getenv("QUERY_STRING");???//getenv()讀取環(huán)境變量的當(dāng)前值的函數(shù)?

????if(sscanf(data,?"led_num=%d&led_state=%d",?&led_num,?&led_state)?!=?2)
????{???//利用sscnaf()函數(shù)的特點(diǎn)將環(huán)境變量分別提取出led_num和led_state這兩個(gè)值
????????printf("<p>please?input?right");?
????????printf("</p>");
????}?
????printf("<p>led_num?=?%d,led_state?=??%d</p>",??led_num,??led_state);
????if(led_num?<?2?||?led_num?>?5)?
????{?
????????printf("<p>Please?input?2<=led_num<=5!");?
????????printf("</p>");
????}?
????if(led_state>1)
????{
????????printf("<p>Please?input?0<=led_state<=1!");?
????????printf("</p>");?
????}

????printf("</html>n");

?return?0;
}

運(yùn)行測試:

image-20231112231256601

這里的getenv函數(shù)就是獲取環(huán)境變量當(dāng)前值的函數(shù),其中,各環(huán)境變量的意義可以參考上面的表。這里的QUERY_STRING環(huán)境變量就是采用GET時(shí)所傳輸?shù)男畔?。在這個(gè)例子中就是:

led_num=3&led_state=1

上面的CGI程序把收到網(wǎng)頁發(fā)送過來的led_num及l(fā)ed_state的值再使用printf返回至網(wǎng)頁中顯示。從網(wǎng)頁中也可以看到相關(guān)信息,整個(gè)流程也就打通了。

方法二:使用CGIC庫。

第二種方法我們使用CGIC庫來編寫我們的CGI程序。首先我們需要下載CGIC庫,下載地址如:

https://github.com/boutell/cgic

下載得到:

整個(gè)包的內(nèi)容不多,就幾個(gè)文件。其中:

    cgic.c ? 函數(shù)庫。capture.c ?一個(gè)很簡單的CGI例子。僅僅輸出兩行提示文字。cgictest.c 一個(gè)演示讀取form表單數(shù)據(jù)的CGI例子。

因?yàn)槲覀兊腃GI程序要運(yùn)行在我們的arm板中,當(dāng)然要交叉編譯,首先需要修改Makefile文件,需要修改如下幾處內(nèi)容:

第①個(gè)修改點(diǎn):

CFLAGS=-g?-Wall
CC=gcc
AR=ar
RANLIB=ranlib
LIBS=-L./?-lcgic

修改為:

CFLAGS=-g?-Wall
CC=arm-linux-gnueabihf-gcc
AR=arm-linux-gnueabihf-ar
RANLIB=arm-linux-gnueabihf-ranlib
LIBS=-L./?-lcgic

第②個(gè)修改點(diǎn):

gcc?cgictest.o?-o?cgictest.cgi?${LIBS}

修改為:

arm-linux-gnueabihf-gcc?cgictest.o?-o?cgictest.cgi?${LIBS}

第③個(gè)修改點(diǎn):

gcc?capture.o?-o?capture?${LIBS}

修改為:

arm-linux-gnueabihf-gcc?cgictest.o?-o?cgictest.cgi?${LIBS}?capture.o?-o?capture?${LIBS}

第④個(gè)修改點(diǎn):

gcc?-D?UNIT_TEST=1?cgic.c?-o?cgicunittest

修改為:

arm-linux-gnueabihf-gcc?-D?UNIT_TEST=1?cgic.c?-o?cgicunittest

這里我的編譯器是arm-linux-gnueabihf-gcc,大家需根據(jù)自己的實(shí)際環(huán)境進(jìn)行修改。make編譯得到cgictest.cgi及capture程序,大家可以自行傳到板子上進(jìn)行測試。下面我們在這個(gè)文件夾下新增一個(gè)led.c文件,用于編寫我們的leg cgi程序:

#include?"cgic.h"

//?cgic程序以cgiMain作為入口點(diǎn),?cgic的函數(shù)庫會自動(dòng)把cgiMain連接到相應(yīng)的main()上去
int?cgiMain()?
{?
?char?led_num[10];??
?char?led_state[10];?
?cgiFormString("led_num",??led_num,?10);????//?從表單中的led_num字段獲取值存入到led_num
?cgiFormString("led_state",??led_state,?10);//?從表單中的led_state字段獲取值存入到led_state
?cgiHeaderContentType("text/html");?????????//?設(shè)定輸出的內(nèi)容格式?這里我們要輸出HTML
?fprintf(cgiOut,"<title>LED?Test</title>");???
?fprintf(cgiOut,"<p>recv?from?arm:</p>");
?fprintf(cgiOut,"led_num:?%s",?led_num);
?fprintf(cgiOut,"<br>");????????????????????
?fprintf(cgiOut,"led_state:?%s",?led_state);
?return?0;
}

修改Makefile,把我們的led.c也加入編譯。編譯得到led.cgi,同樣也要傳入到板子中的/www/cgi-bin文件夾下。

以上就是本次分享的基于boa的遠(yuǎn)程控制系統(tǒng),環(huán)境打通了,想怎么玩就怎么玩!

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險(xiǎn)等級 參考價(jià)格 更多信息
74HC245D,653 1 Nexperia 74HC245; 74HCT245 - Octal bus transceiver; 3-state@en-us SOP 20-Pin

ECAD模型

下載ECAD模型
$0.61 查看
FTLF8524P2BNV 1 Finisar Corporation Transceiver, 830nm Min, 860nm Max, 4250Mbps(Tx), 4250Mbps(Rx), LC Connector, Panel Mount, ROHS COMPLIANT PACKAGE
$301.6 查看
AQV252GAZ 1 Panasonic Electronic Components Solid State Relay,
$6.55 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

本公眾號專注于嵌入式技術(shù),包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學(xué)習(xí)筆記,同時(shí),公眾號內(nèi)包含大量的學(xué)習(xí)資源。歡迎關(guān)注,一同交流學(xué)習(xí),共同進(jìn)步!