大家好
剛從NP期末考爆炸的小弟
要來跟大家介紹一下這個作業的想法
以及如何實作
程式coding style如果有需要改進之處歡迎留言讓我知道XDD
(後續3個作業慢慢更新)
●本次作業說明:
實作一個shell,具有pipe + number pipe + file output 的功能
number pipe在用
本次的重點就是pipe的使用
●想法:
需要有一個能夠管理pipe的class
決定該指令的in, out, error要從哪裡來/往哪裡去
※pipe開關的原則
→在parent的部分
1.pipe進來的:關掉進來的write,fork後parent再把他的read關掉
(如果fork之前關掉,child就沒辦法讀pipe的東西了)
2.pipe出去的:不用關,因為可能還有其他指令要寫入這個pipe
→在child的部分
把stdin,stdout,stderr導入正確的pipe後
read, write都要關閉
●我的架構:
socket.cpp:負責處理連入連線
server.cpp:負責處理所有的ras要求
types.cpp:自定義的class都放在這
自定義的class包含了
1. SingleCmd
顧名思義就是一個指令的資料
紀錄了...
執行檔的名稱(execute)
是否需要pipe(need_pipe)
要往後pipe幾個指令(pipe_num)
並且有三個member function
push():在parse指令的時候用
get_exe()、get_argv():這兩個在exec的時候轉回所需的型態
2. LineCmd
這是存一整行所有指令的class
有一個vector<SingleCmd>存這一行所有的指令
有一個member function add_cmd()負責把一行內的單一指令打包
3. PipeAdmin
有一個pipe_set存1000格pipe陣列
有四個member function
create_pipe//初始pipe
void close_pipe//關閉pipe的read or write端
int find_pipe(int);//找到在1000個pipe中和pipe_num相同剩餘的pipe位置
void decr_num();//減少所有pipe的pipe_num
●流程:
e.g. 有一行指令為 removetag test.html | cat > a.txt
先從socket.cpp開始
將socket建立後,bind在指定的port並listen,直到有連線進來時呼叫accept
並且fork一個child process負責處理這個連線,就進入do_ras處理指令
(這裡fork的用意是為了下一個作業需要多人連線,預先寫好的)
do_ras會先切割指令(cmd_parse)→執行指令(run)
※cmd_parse
一開始先從client讀指令過來
將收到的字串轉換成string開始切指令
我根據"|"和">"做為切割的符號
藉由string的find_first_of()找到符號位置存入place變數
如果有找到上述兩個符號的話
就進入while迴圈
抓取從頭到place位置的字串內容
放到新的string sub_str之中
並藉由stringstream會自動看空白切字串的特性
把字串push到SingleCmd之內
接著去判斷place所指的符號為何
如果是|
就用isdigit判斷pipe後一格的是否為數字
若是就把它用atoi轉換成數字存入SingleCmd的pipe_num
不是的話pipe_num就設定為1
如果是>
因為在本次作業中必定是一行之中最後一個指令
因此只要存後面要輸出的檔案名稱
並且把toFile的flag設為true
上面的if做完之後
再判斷一次後面有沒有|或>的符號
沒有就跳出函式
※run
把剛剛parse完的LineCmd用迴圈去go through
先挑出不需要用到pipe的三個指令(setenv, printenv, exit)
接下來藉由呼叫check_exe這個函式
判斷這個cmd的名字有沒有在ras/bin底下
如果沒有的話直接輸出"Unknown command"
然後是針對output部分
判斷要pipe過去的地方是否已經有指令pipe過去
如果沒有的話要把那一格pipe做初始化的動作
最後就是fork出要拿來exec的process
根據上面想法所提及的方式
將stdin, stdout, stderr dup2去正確的地方
呼叫exec執行指令
並在parent這邊呼叫wait等到指令執行結束
(避免zombie process)
程式參考連結:
https://lsps4111wu@bitbucket.org/lsps4111wu/np_project1_0656509
沒有留言:
張貼留言