嵌入式web伺服器BOA原始碼解析

2021-10-02 16:40:27 字數 4408 閱讀 4412

boa是乙個單程序的web伺服器,支援cgi互動,瀏覽器每次傳送乙個poat請求,boa會對應fork乙個cgi程序,資料傳送完成後,cgi程序退出,儘管存在這樣的程序建立和銷毀的開銷,但boa仍然是一款輕量級的web伺服器,適用於需要較為簡單的web頁面訪問。下面對boa的主要部分進行**分析,包含get和post兩種方法。

get和post對客戶端請求資料的解析過程都差不多,get主要的函式為init_get,而post主要為init_cgi

1 get

1.1 get呼叫過程原始碼分析

if

(request_block)

fdset_update()

;process_requests

(server_s)

;read_header

(current)

;read()

//讀取客戶端發來的資料到req->client_stream

//解析請求行,獲取http版本和請求方法,url

process_logline()

process_option_line()

//解析每一行請求頭並儲存屬性值

process_header_end()

unescape_uri()

//如果請求行中有query_string,則解析

clean_pathname()

//確保url中路徑分隔符是'/'

translate_uri()

//解析出req->pathname,絕對路徑

req->status = write;

init_get

(req)

;//獲取請求的檔案並傳送

//如果在init_get中已經傳送完,則req->status = done;

//process_get就不會執行了

process_get()

//write 狀態機

呼叫系統write

()傳送get的檔案

free_request //釋放這次請求

release_mmap

(req->mmap_entry_var)

;munmap()

close()

//關閉fd

init_get

(req)

//pathname是路徑,一般會返回index.html

//如果是檔案,直接開啟檔案

open

(req->pathname, o_rdonly)

;fstat

(data_fd,

&statbuf)

;//獲取檔案資訊if(

s_isdir

(statbuf.st_mode)

)//路徑

data_fd =

get_dir

(req,

&statbuf)

;//獲取index.html

req->filesize = statbuf.st_size;

//mmap對映檔案

req->mmap_entry_var =

find_mmap

(data_fd,

&statbuf)

; req->data_mem = req->mmap_entry_var->mmap;

send_r_request_ok

(req)

;//copy響應行和頭到req->buffer

//copy響應體,也就是get的檔案內容

memcpy

(req->buffer + req->buffer_end, req->data_mem, bytes)

;req_flush

(req)

;//傳送響應行,響應頭,響應體

1.2 get呼叫過程記憶體資料傳輸圖

boa針對post方法會fork乙個子程序進行cgi的輸出,父子程序通過pipe進行通訊,程式主要呼叫過程如下所示

2.1 post**執行過程

process_requests

read_header

(current)

;//read_header狀態機

process_header_end()

unescape_uri()

//如果請求行中有query_string,則解析

clean_pathname()

//確保url中路徑分隔符是'/'

translate_uri()

//解析出req->pathname,絕對路徑

//建立臨時檔案

req->post_data_fd =

create_temporary_file(1

,null,0

);req->status = body_write;

req->header_line //執行請求體內容的開始

req->header_end //執行請求體內容的結束

write_body

(current)

;//body_write狀態機

write

(req->post_data_fd)

//向臨時檔案中傳送client的請求體

req->header_line = req->header_end = req->buffer;

init_cgi

(req)

; req->status = pipe_read;

req->header_line = req->header_end =

(req->buffer + buffer_size /2)

;read_from_pipe

(current)

;//pipe_read狀態機,從pipe中讀取cgi寫入的資料

bytes_read =

read

(req->data_fd,req->header_end)

header_end +

= bytes_read

req->status = pipe_write;

process_cgi_header

(req)

;send_r_request_ok

(req)

;//響應行和頭寫入req->buffer

dest = req->buffer + req->buffer_end;

howmuch = req->header_end - req->header_line;

memmove

(dest, req->header_line, howmuch)

; req->buffer_end +

= howmuch;

req->header_line = req->buffer + req->buffer_end;

req->header_end = req->header_line;

req_flush

(req)

;//傳送響應行、頭、體

write_from_pipe //pipe_write狀態機

write()

return0;

init_cgi

(req)

;pipe

(pipes)

child_pid =

fork()

; child

close

(pipes[0]

);dup2

(pipes[1]

, stdout_fileno)

close

(pipes[1]

);//從標準輸入中讀取臨時檔案的內容,即client的請求體

dup2

(req->post_data_fd, stdin_fileno)

;close

(req->post_data_fd)

;execve

(req->pathname, aar**, req->cgi_env)

;//執行cgi

parent

close

(req->post_data_fd)

; eq->post_data_fd =0;

close

(pipes[1]

);req->data_fd = pipes[0]

;//可以從pipe中讀取cgi寫入的響應體

req->status = pipe_read;

2.2 post程式執行過程中記憶體中資料流圖

交叉編譯嵌入式web伺服器boa

步驟大部分都一樣吧,只是交叉編譯器會有不同.第一步boa 程式的移植 目標板為xscale pxa270 交叉編譯器arm linux gcc 去網上下了乙份源 http www.boa.org cgipath the value of the path environment variable g...

嵌入式linux部署boa伺服器

在web伺服器中,較為常用的是tomcat,nigix。但是這種伺服器比較大,占用資源比較多,並不適合於嵌入式裝置中。而boa是乙個很輕便的web伺服器,部署簡單,占用資源少,支援多種語言。2.配置boa的編譯環境 安裝bison sudo apt get install bison安裝flex s...

嵌入式Web伺服器Boa的移植及其應用

隨著嵌入式技術的發展和高速寬頻網路的普及,利用網路實現遠端監控已為人們廣泛接受,嵌入式網路監控技術正是在此條件下逐步發展成熟起來的.1 嵌入式web 伺服器boa 的特點 boa 是一款單任務的http 伺服器,與其他傳統的web 伺服器不同的是當有連線請求到來時,它並不為每個連線單獨建立程序,也不...