WSN中LEACH協(xié)議源碼分析
《WSN中LEACH協(xié)議源碼分析》由會員分享,可在線閱讀,更多相關(guān)《WSN中LEACH協(xié)議源碼分析(10頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、WSN中LEACH協(xié)議源碼分析 分析(一) 首先對wireless.tcl進行分析,先對默認的腳本選項進行初始化: set opt(chan)Channel/WirelessChannel set opt(prop) Propagation/TwoRayGround set opt(netif)Phy/WirelessPhy set opt(mac) Mac/802_11 set opt(ifq) Queue/DropTail/PriQueue set opt(ll) LL set opt(ant) Antenna/OmniAntenna set opt(x)
2、0 ;# X dimension of the topography set opt(y) 0 ;# Y dimension of the topography set opt(cp) "" set opt(sc) "../mobility/scene/scen-670x670-50-600-20-2" ;# scenario file set opt(ifqlen) 50;# max packet in if set opt(nn) 51 ;# number of nodes set opt(seed) 0.0 set opt(stop) 10.
3、0 ;# simulation time set opt(tr) out.tr ;# trace file set opt(rp) dsdv ;# routing protocol script set opt(lm) "on" ;# log movement 在這個wireless.tcl中設(shè)置了一些全局變量: # # Initialize Global Variables # set ns_ [new Simulator] set chan [new $opt(chan)] set pr
4、op [new $opt(prop)] set topo [new Topography] set tracefd [open $opt(tr) w] $topo load_flatgrid $opt(x) $opt(y) $prop topography $topo 這些初始化將在后面的使用中用到,該文件最重要的是創(chuàng)建leach節(jié)點:創(chuàng)建方法如下: } elseif { [string compare $opt(rp) "leach"] == 0} { for {set i 0} {$i < $opt(nn) } {incr i} { lea
5、ch-create-mobile-node $i } 如果路由協(xié)議是leach協(xié)議,則在Uamps.tcl中調(diào)用leach-create-mobile-node方法創(chuàng)建leach節(jié)點。將在第二小節(jié)講如何創(chuàng)建leach節(jié)點。 for {set i 0} {$i < $opt(nn) } {incr i} { $ns_ at $opt(stop). "$node_($i) reset"; //完成后,重置節(jié)點的應(yīng)用 } $ns_ at $opt(stop).00000001 "puts \"NS EXITING...\" ; $ns_ halt" if { $opt(s
6、c) == "" } { puts "*** NOTE: no scenario file specified." set opt(sc) "none" } else { puts "Loading scenario file..." source $opt(sc) puts "Load complete..." } ns在什么時候結(jié)束simulation,并告訴ns加載sc場景文件。最后$ns_ run則ns就開始運行了。 分析(二) 上節(jié)對wireless.tcl進行了簡要的分析,接下來對Uamps.tcl腳本進行分析。 set opt(Efriss
7、_amp) [expr [expr 1.1 * $opt(RXThresh) * 16 * $PI * $PI] / \ [expr $opt(bw) * $opt(Gt) * $opt(Gr) * $l * $l]] # Etwo_ray_amp = RXThresh / (Rb Gt Gr ht^2 hr^2) set opt(Etwo_ray_amp) [expr 1.1 * $opt(RXThresh) / \ [expr $opt(bw) * $opt(Gt) * $opt
8、(Gr) * \ $opt(ht) * $opt(ht) * $opt(ht) * $opt(ht)]] set opt(EXcvr) 50e-9 ;# Energy for radio circuitry set opt(e_bf) 5e-9 ;# Beamforming energy (J/bit) set opt(Esense) 0 ;# Sensing energy (J/bit) set
9、 opt(thresh_energy) 0.00 ;# Threshold for power adaptation set opt(Pidle) 0 ;# Idle power (W) set opt(Psleep) 0 ;# Sleep power (W) set initialized 0 set rng_ [new RNG]#用于產(chǎn)生隨機數(shù) 首先往opt數(shù)組里面添加一些變量,并對這些變量進行初化。opt(Psleep)
10、 ,opt(Pidle), opt(thresh_energy)在ns-leach.tcl中使用到,這個是計算單位時間空閑所消耗的能量和休眠所消耗的能量。 這個腳本主要是創(chuàng)建leach節(jié)點: if {$initialized == 0} { #remove old trace sens_init set initialized 1 } # Remove old trace files. catch "eval exec rm [glob -nocomplain $opt(dirname)/TDMAschedul
11、e.*.txt]" catch "exec rm $opt(dirname)/$opt(filename).energy" catch "exec rm $opt(dirname)/$opt(filename).data" catch "exec rm $opt(dirname)/$opt(filename).alive" catch "exec rm $opt(dirname)/startup.energy" catch "exec rm $opt(dirname)/init.energy" 如果沒有初始化過,則將以前的跟蹤文件刪除,接
12、著回到創(chuàng)建leach的函數(shù)中,創(chuàng)建節(jié)點: if {$id != $opt(nn_)} { puts -nonewline "$id " #important set node_($id) [new MobileNode/ResourceAwareNode] } else { puts "($opt(nn_) == BS)" set node_($id) [new MobileNode/ResourceAwareNode $BS_NODE] } 如果不是簇頭節(jié)點則將$opt(nn_)-1個節(jié)點設(shè)置為一般
13、節(jié)點,將$opt(nn_)設(shè)置為BS節(jié)點。newMobileNode/ResourceAwareNode函數(shù)是在ns-ranode.tcl中。分析完這個我們接下來分析newMobileNode/ResourceAwareNode這個函數(shù)。 set node $node_($id) if {$id != $opt(nn_)} { # Set initial node energy. if {$opt(eq_energy) == 1} { $node set-energy $opt(init_energy) $opt(thr
14、esh_energy) } else { 由于eq-energy在leach-test中給定,將eq-energy=1;則每個節(jié)點都會對能量進行初始化,設(shè)置節(jié)點的初始能量和門檻能量(個人理解,死亡能量)。 set high_e_nodes [list 97 19 12 87 8 22 83 55 34 72] if {[lsearch $high_e_nodes $id] == -1} { set E 2 } else { set E 200 } $n
15、ode set-energy $E $opt(thresh_energy) set initf [open "$opt(dirname)/init.energy" a] puts $initf "$id\t$E" close $initf 將不屬于list中的能量初始化能量設(shè)置為2,將屬于list中的能量設(shè)置為200.并將初始化能量寫到init.energy中,將節(jié)點id和節(jié)點初始能量寫進去。 else { # Base station has an infinite amount of energy. $
16、node set-energy 50000 $opt(thresh_energy) } 節(jié)點為簇頭節(jié)點,則將節(jié)點的初始化能量設(shè)置為50000,能量無限。 到此為止,創(chuàng)建節(jié)點完成并將每個節(jié)點的能量初始化完成。下一節(jié)將分析ns-ranode.tcl腳本。區(qū)分普通節(jié)點和簇頭節(jié)點的不同。接下來是配置節(jié)點信道和跟蹤文件: $ns_ at 0.0 "$node_($id) start-app" ns在0的時候啟動應(yīng)用,應(yīng)用在ns-ranode.tcl中分析。 分析(三) 對前面兩個腳本進行分析后,已經(jīng)創(chuàng)建好節(jié)點和設(shè)置好節(jié)點的初始能量,將opt(nn_)-1個節(jié)點設(shè)置為普通節(jié)點,
17、而將opt(nn_)設(shè)置為bs?,F(xiàn)在對ns-ranode.tcl進行分析。好了我們現(xiàn)在就開始分析這個腳本。 Class MobileNode/ResourceAwareNode -superclass Node/MobileNode MobileNode/ResourceAwareNode instproc init args set bs_node [lindex $args 0] eval $self next [lreplace $args 0 0] args由參數(shù)傳遞進來,若節(jié)點為簇頭節(jié)點則bs_node=1,調(diào)用父類初始化函數(shù)。 set ResourceMa
18、nager_ [new ResourceManager] $ResourceManager_ Register [new Resource/NeighborResource] set energy [new Resource/Energy] $ResourceManager_ Register $energy ResourceManager在ns-resouce-manager.tcl中定義的。Resource/NeighborResource在ns-neighbor-resource中對能量進行管理。 # Create a new agent and
19、 attach it to the node if {$bs_node == 1} { set agent [new Agent/BSAgent] } else { set agent [new Agent/RCAgent] } set rca_agent_ $agent 普通節(jié)點的應(yīng)用為RCAgent,BS的應(yīng)用為BSAGgent。 并將應(yīng)用attch到node上。 下面兩段看不明白,但是這兩段不影響看程序。 set haslist [find_haslist
20、 [$self id]] if {$bs_node == 1} { set rca [new $opt(bsapp)] } else { set rca [new $opt(rcapp) $opt(mtype) $wantslist $haslist] } $ns_ attach-agent $self $agent $rca attach-agent $agent set rca_app_ $rca 將bs節(jié)點的應(yīng)用設(shè)置為bsapp,普通節(jié)點的應(yīng)用設(shè)置為rca
21、app,并將節(jié)點的服務(wù)設(shè)置為不同的服務(wù)。bsapp在ns-app.tcl中。$opt(rcapp)定義在leach.tcl中,opt(mtype)定義在leach.tcl中。 set opt(rcapp) "Application/LEACH" ;# Application type set opt(ra_adv) [TxTime [expr $opt(hdr_size) + 4]] ;# Total time (s) for CH ADVs
22、 ;# Assume max 4(nn*%) CHs set opt(ra_adv_total) [expr $opt(ra_adv)*($opt(num_clusters)*4 + 1)] ;# RA Time (s) for nodes' join reqs set opt(ra_join) [expr 0.01 * $opt(nn_)]
23、 ;# Buffer time for join req xmittal set opt(ra_delay) [TxTime [expr $opt(hdr_size) + 4]] ;# Maximum time required to transmit ;# a schedule (n nodes in 1 cluster) set opt(xmit_sch) [
24、expr 0.005 + [TxTime [expr $opt(nn_)*4+$opt(hdr_size)]]] ;# Overhead time for cluster set-up set opt(start_xmit) [expr $opt(ra_adv_total) + $opt(ra_join) + $opt(xmit_sch)] 一般節(jié)點的應(yīng)用為Application/LEACH,最終sink節(jié)點的應(yīng)用為Application/BSApp。 通過前3次的分析得出,在分析1中定義變量,在分
25、析2中創(chuàng)建leach節(jié)點,在分析3中將節(jié)點的應(yīng)用綁定在節(jié)點上。 下面將分析leach的主要協(xié)議ns-leach.tcl腳本。 分析(四) 完成前面3個腳本的分析,最后進行ns-leach.tcl腳本的分析.首先我們看下這個腳本要使用的有哪些功能. Application/LEACH instproc init args {} 對leach進行初始化,即構(gòu)造函數(shù)。 下面是leach的一些方法 Application/LEACH instproc start {} {} Application/LEACH instproc getRandomNumber {llim ulim} {
26、} 得到隨機數(shù) Application/LEACH instproc node {} {} Application/LEACH instproc nodeID {} {} Application/LEACH instproc mac {} {} Application/LEACH instproc getX {} {} Application/LEACH instproc getY {} {} Application/LEACH instproc getER {} {} Application/LEACH instproc GoToSleep {} {} 節(jié)點進行休眠 App
27、lication/LEACH instproc WakeUp {} {}節(jié)點醒來 Application/LEACH instproc setCode code {}{} Application/LEACH instproc checkAlive {} {} 節(jié)點是否存活 Application/LEACH instproc isClusterHead? {} {} 判斷是否是簇頭節(jié)點 Application/LEACH instproc hasbeenClusterHead? {} {} 判斷是否成為過簇頭節(jié)點 Application/LEACH instproc hasn
28、otbeenClusterHead {} {}hasbeench=0不是簇頭節(jié)點 Application/LEACH instproc setClusterHead {} {} 設(shè)置為簇頭節(jié)點 Application/LEACH instproc unsetClusterHead {} {} 設(shè)置為非簇頭節(jié)點 Application/LEACH instproc decideClusterHead {} {} 決定簇頭節(jié)點,非常重要 Application/LEACH instproc advertiseClusterHead {} {} 廣播簇頭節(jié)點 Application/
29、LEACH instproc findBestCluster {} {} 找到最佳簇 Application/LEACH instproc informClusterHead {} {} 通知簇頭節(jié)點 Application/LEACH instproc createSchedule {} {} 創(chuàng)建TDMA調(diào)度 接收功能: Application/LEACH instproc recv {args} {} Application/LEACH instproc recvADV_CH {msg} {} Application/LEACH instproc recvJOIN_REQ
30、{nodeID} {} Application/LEACH instproc recvADV_SCH {order} {} Application/LEACH instproc recvDATA {msg} {} 發(fā)送功能: Application/LEACH instproc sendData {} {} Application/LEACH instproc send {mac_dst link_dst type msgdata_size dist code} {} Application/LEACH instproc send_now {mac_dst link_dst typ
31、e msg data_size dist code} {} Application/LEACH instproc SendDataToBS {} {} Application/LEACH instproc SendMyDataToBS {} {} 分析(五) 由leach 分析三可知,一般節(jié)點的應(yīng)用為Application/LEACH。則現(xiàn)在就是如何選擇簇頭節(jié)點和設(shè)置門檻值。我們接下來分析leach 分析4中紅色的方法。在leach 分析3中創(chuàng)建一個Application/LEACH對象則就會自動調(diào)用start方法。 Application/LEACH instproc start
32、{} { [$self mac] set node_num_ [$self nodeID] $self decideClusterHead $self checkAlive } 在這個方法中會調(diào)用decideClusterHead和checkAlive方法。 Application/LEACH instproc GoToSleep {} { global opt ns_ $self instvar begin_idle_ begin_sleep_ [[$self node] set netif_(0)] set sleep_ 1 # I
33、f node has been awake, remove idle energy (e.g., the amount of energy # dissipated while the node is in the idle state). Otherwise, the node # has been asleep and must remove sleep energy (e.g., the amount of # energy dissipated while the node is in the sleep state). if {$begin_idle_ >
34、$begin_sleep_} { set idle_energy [expr $opt(Pidle) * [expr [$ns_ now] - $begin_idle_]] [$self getER] remove $idle_energy } else { set sleep_energy [expr $opt(Psleep) * [expr [$ns_ now] - $begin_sleep_]] [$self getER] remove $sleep_energy } set begin_sleep_ [$ns_ now]
35、set begin_idle_ 0 } 分析(六) 在start中調(diào)用下面這個方法。 Application/LEACH instproc decideClusterHead {} { global ns_ chan opt node_ $self instvar alive_ TDMAschedule_ $self instvar begin_idle_ begin_sleep_ # Check the alive status of the node. If the node has run out of # energy, it no l
36、onger functions in the network. set ISalive [[[$self node] set netif_(0)] set alive_] if {$alive_ == 1} { if {$ISalive == 0} { puts "Node [$self nodeID] is DEAD!!!!" $chan removeif [[$self node] set netif_(0)] set alive_ 0 set opt(nn_) [expr $opt(nn_) - 1]
37、set ISalive [[[$self node] set netif_(0)] set alive_] #從網(wǎng)絡(luò)接口netif中查看當前節(jié)點狀 況 如果節(jié)點存活,但是節(jié)點能量耗光,則$chan removeif [[$self node] set netif_(0)]將節(jié)點信道中移出,并將節(jié)點設(shè)置為死亡。節(jié)點的總數(shù)目減少一個。 if {$opt(eq_energy) == 1} { # # Pi(t) = k / (N - k mod(r,N/k)) # where k is the expected number of clusters per ro
38、und # N is the total number of sensor nodes in the network # and r is the number of rounds that have already passed. # set nn $opt(nn_) if {[expr $nn - $opt(num_clusters) * $round_] < 1} { set thresh 1 } else { set thresh [expr double($opt(num_clusters)) /
39、 \ [expr $nn - $opt(num_clusters) * $round_]] # Whenever round_ is 0, all nodes are eligible to be cluster-head. if {$round_ == 0} { $self hasnotbeenClusterHead } } # If node has been cluster-head in this group of rounds, it will not # act as a
40、cluster-head for this round. if {[$self hasbeenClusterHead?]} { set thresh 0 } } else { # # Pi(t) = Ei(t) / Etotal(t) * k # where k is the expected number of clusters per round, # Ei(t) is the node's current energy, and Etotal(t) is the total # energy fr
41、om all nodes in the network. # set Etotal 0 # Note! In a real network, would need a routing protocol to get this # information. Alternatively, each node could estimate Etotal(t) from # the energy of nodes in its cluster. for {set id 0} {$id < [expr $opt(nn)-1]} {incr
42、 id} { set app [$node_($id) set rca_app_] set E [[$app getER] query] set Etotal [expr $Etotal + $E] } set E [[$self getER] query] set thresh [expr double([expr $E * $opt(num_clusters)]) / $Etotal] } 上面是對thresh的計算,當(N - k mod(r,N/k))<1,則將thresh設(shè)置為1,否則節(jié)點thres
43、h=k / (N - k mod(r,N/k)),每個節(jié)點在一個1/p中都要成為簇頭節(jié)點一次。p=簇頭節(jié)點占所有節(jié)點的比例,在r=0的時候每個節(jié)點都有機會吃呢更為簇頭節(jié)點。如果節(jié)點成為過簇頭節(jié)點則thresh=0,則這個節(jié)點在1/p輪后才可以成為簇頭節(jié)點。 if {[$self getRandomNumber 0 1] < $thresh} { puts "$nodeID: *******************************************" puts "$nodeID: Is a cluster head at time [$ns_ now]"
44、 $self setClusterHead set random_access [$self getRandomNumber 0 $opt(ra_adv)] #opt(ra_adv) in leach.tcl $ns_ at [expr $now_ + $random_access] "$self advertiseClusterHead" } else { puts "$nodeID: *******************************************" $self unsetClusterHead
45、 } 如果thresh>getRandomNumber,則節(jié)點成為簇頭節(jié)點。然后調(diào)用advertiseClusterHead方法。 set next_change_time_ [expr $now_ + $opt(ch_change)] $ns_ at $next_change_time_ "$self decideClusterHead" $ns_ at [expr $now_ + $opt(ra_adv_total)] "$self findBestCluster" 當節(jié)點成為簇頭節(jié)點,則節(jié)點調(diào)用 advertiseClusterHead方法。 set c
46、hID [$self nodeID] set currentCH_ $chID pp "Cluster Head $currentCH_ broadcasting ADV at time [$ns_ now]" set mac_dst $MAC_BROADCAST set link_dst $LINK_BROADCAST set msg [list $currentCH_] set datasize [expr $BYTES_ID * [llength $msg]] # Send beacons opt(max_dist) meters so all nodes
47、can hear. $self send $mac_dst $link_dst $ADV_CH $msg $datasize $opt(max_dist) $code_ 將該節(jié)點設(shè)置為簇頭節(jié)點,設(shè)置當前節(jié)點所處的簇號。然后發(fā)送數(shù)據(jù),廣播該節(jié)點為簇頭信息到全局網(wǎng)絡(luò)。 在$ns_ at [expr $now_ + $opt(ra_adv_total)] "$self findBestCluster"調(diào)用findBestCluster方法。 分析(七) 當簇頭發(fā)出了一個ADV類型的包時,其他的節(jié)點會接收這個包,并會將發(fā)送這個包的簇頭的節(jié)點號按順序先后記錄在clusterChoices_中,
48、還會計算每個簇頭到接收節(jié)點的距離并記錄在clusterDist_中。這樣可以方便每個節(jié)點選簇的時候進行比較。具體的實現(xiàn)在ns-leach.tcl中的recvADV_CH函數(shù)中。 findBestCluster if [$self isClusterHead?] { # If node is CH, determine code and create a TDMA schedule. set dist_ $opt(max_dist) set currentCH_ $nodeID set myADVnum_ [[$self mac] set myAD
49、Vnum_] # There are opt(spreading) - 1 codes available b/c need 1 code # for communication with the base station. set numCodesAvail [expr 2 * $opt(spreading) - 1] set ClusterCode [expr int(fmod($myADVnum_, $numCodesAvail)) + 1] $ns_ at [expr $now_ + $opt(ra_adv_total) + $op
50、t(ra_join)] \ "$self createSchedule" } 如果這個節(jié)點是簇頭節(jié)點,設(shè)置為當前的簇頭, set numCodesAvail [expr 2 * $opt(spreading) - 1] set ClusterCode [expr int(fmod($myADVnum_, $numCodesAvail)) + 1]這兩句沒看懂 在一個隨機時間后調(diào)用createSchedule,節(jié)點根據(jù)自己收到的clusterChoices,選擇最近的簇頭作為簇頭節(jié)點。選擇好簇頭節(jié)點就informClusterHead。發(fā)送
51、完數(shù)據(jù)就進入休眠狀態(tài)。 Application/LEACH instproc createSchedule {} { global ns_ opt ADV_SCH MAC_BROADCAST BYTES_ID $self instvar clusterNodes_ TDMAschedule_ $self instvar dist_ code_ now_ beginningE_ set numNodes [llength $clusterNodes_] set chID [$self nodeID] if {$numNodes == 0}
52、{ set xmitOrder "" puts "Warning! There are no nodes in this cluster ($chID)!" $self SendMyDataToBS } else { # Set the TDMA schedule and send it to all nodes in the cluster. set xmitOrder $clusterNodes_ set msg [list $xmitOrder] set spreading_factor $opt(spread
53、ing) set datasize [expr $spreading_factor * $BYTES_ID * [llength $xmitOrder]] pp "$chID sending TDMA schedule: $xmitOrder at time [$ns_ now]" pp "Packet size is $datasize." set mac_dst $MAC_BROADCAST set link_dst $chID $self send $mac_dst $link_dst $ADV_SCH $msg $datasi
54、ze $dist_ $code_ } set TDMAschedule_ $xmitOrder set outf [open $opt(dirname)/TDMAschedule.$now_.txt a] puts $outf "$chID\t$TDMAschedule_" close $outf set outf [open $opt(dirname)/startup.energy a] puts $outf "[$ns_ now]\t$chID\t[expr $beginningE_ - [[$self getER] query]] "
55、 close $outf } 在recvADV_SCH給每個節(jié)點一個時間間隙發(fā)送數(shù)據(jù) set frame_time_ [expr [expr 5 + [llength [join $order]]] * $opt(ss_slot_time)] set xmitTime_ [expr $opt(ss_slot_time) * $ind] set end_frm_time_ [expr $frame_time_ - $xmitTime_] set xmitat [expr [$ns_ now] + $xmitTime_] pp "$nodeID scheduled to transmit at $xmitat. It is now [$ns_ now]." if {[expr $xmitat + $end_frm_time_] < \ [expr $next_change_time_ - 10 * $opt(ss_slot_time)]} { $ns_ at $xmitat "$self sendData" 具體實現(xiàn)方法看不太懂。
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 6.煤礦安全生產(chǎn)科普知識競賽題含答案
- 2.煤礦爆破工技能鑒定試題含答案
- 3.爆破工培訓考試試題含答案
- 2.煤礦安全監(jiān)察人員模擬考試題庫試卷含答案
- 3.金屬非金屬礦山安全管理人員(地下礦山)安全生產(chǎn)模擬考試題庫試卷含答案
- 4.煤礦特種作業(yè)人員井下電鉗工模擬考試題庫試卷含答案
- 1 煤礦安全生產(chǎn)及管理知識測試題庫及答案
- 2 各種煤礦安全考試試題含答案
- 1 煤礦安全檢查考試題
- 1 井下放炮員練習題含答案
- 2煤礦安全監(jiān)測工種技術(shù)比武題庫含解析
- 1 礦山應(yīng)急救援安全知識競賽試題
- 1 礦井泵工考試練習題含答案
- 2煤礦爆破工考試復習題含答案
- 1 各種煤礦安全考試試題含答案