如何在 tcl 表达式中使用全局字符串值


how to use the global string value in tcl expression

我正在使用 Ns2 和 tcl 脚本。在下面的代码中,我想使用全局变量 rate12,它在表达式中的值为 2Mb

1
2
3
4
5
 if { $queuesize>16 } {
     set RL [expr $Rc * $fdec * $hf]
    set rate12 [expr $rate12 * $RL]
    puts $rate12
 }

从 proc 记录中找到。但它显示以下错误:

1
2
3
4
5
6
7
8
9
ns: record _o104 file5: invalid bareword"Mb"
in expression"4_@_Mb * 0.40000000000000002";
should be"$Mb" or"{Mb}" or"Mb(...)" or ...
    (parsing expression"4Mb * 0.40000000000000...")
    invoked from within
"expr $rate12 * $RL"
    (procedure"record" line 26)
    invoked from within
"record _o104 file5"

我该如何解决这个错误?

整个代码是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#Create a simulator object

set ns [new Simulator]

 global rate02
 global rate12
 global rate23
 global rate32

#Define different colors for data flows (for NAM)

$ns color 1 Blue
$ns color 2 Red
$ns color 3 Green

#Open the NAM trace file

set nf [open out.nam w]
$ns namtrace-all $nf
# constants
global Rc
global Fdec
global hf

#Define a 'finish' procedure

proc finish {} {
    global ns nf
    $ns flush-trace
   #Close the NAM trace file
    close $nf
   #Execute NAM on the trace file
    exec nam out.nam &
    exit 0
}

#Create four nodes

set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]

set rate02 2Mb
set rate12 4Mb
set rate23 2Mb
set rate32 0.1Mb

#Create links between the nodes

$ns duplex-link $n0 $n2 $rate02 10ms RED
$ns duplex-link $n1 $n2 $rate12 10ms DropTail
$ns duplex-link $n2 $n3 $rate23 20ms DropTail
$ns duplex-link $n3 $n2 $rate32 10ms DropTail

#Set Queue Size of link (n2-n3) to 10

$ns queue-limit $n2 $n3 16

#Give node position (for NAM)

$ns duplex-link-op $n0 $n2 orient right-down
$ns duplex-link-op $n1 $n2 orient right-up
$ns duplex-link-op $n2 $n3 orient right

#Monitor the queue for link (n2-n3). (for NAM)

$ns duplex-link-op $n2 $n3 queuePos 0.5

#creat file record infomation at queues


set queue03 [$ns monitor-queue $n2 $n3 [open qsize03.tr w] 0.05]
set qsize03 [open qsize03.tr w]


proc record {queue qsize} {
        global ns
       #set ns [Simulator instance]
        set time 0.1
        set now [$ns now]
       #print current qsize in $queuesize
        $queue instvar parrivals_ pdepartures_ bdros_ bdepartures_ pdrops_
       #set queuesize [expr $parrivals_ - $pdepartures_ - $pdrops_]
        set queuesize $parrivals_
        puts $queuesize
        puts $qsize"$now [expr $parrivals_ - $pdepartures_ - $pdrops_]"
       #puts"$now [expr $parrivals_ - $pdepartures_ - $pdrops_]"
        set $bdepartures_ 0

        set Rc 2
        set fdec 0.4
        set hf 0.5
        global rate12
        set n0 [$ns node]
        set n1 [$ns node]
        set n2 [$ns node]

        if { $queuesize>16 } {
        set RL [expr $Rc * $fdec * $hf]
        set rate12 [expr $rate12 * $RL]
        puts $rate12
        $ns duplex-link $n0 $n2 0.8Mb 10ms RED
        } elseif { $queuesize==20 } {
        puts"full"
        } else {
        puts"under"
        }

        $ns at [expr $now + $time]"record $queue $qsize"
}

#Setup a TCP connection

set tcp1 [new Agent/TCP]
$tcp1 set class_ 2
$ns attach-agent $n0 $tcp1
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp1 $sink
$tcp1 set fid_ 1
#########################################
#Setup a TCP connection
set tcp3 [new Agent/TCP]
$tcp3 set class_ 2
$ns attach-agent $n3 $tcp3
set sink2 [new Agent/TCPSink]
$ns attach-agent $n1 $sink2
$ns connect $tcp3 $sink2
$tcp3 set fid_ 3

#Setup a FTP over TCP connection

set ftp3 [new Application/FTP]
$ftp3 attach-agent $tcp3
$ftp3 set type_ FTP
############################################
#Setup a FTP over TCP connection
set ftp1 [new Application/FTP]
$ftp1 attach-agent $tcp1
$ftp1 set type_ FTP

#Setup a TCP connection

set tcp2 [new Agent/TCP]
$tcp2 set class_ 2
$ns attach-agent $n1 $tcp2
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp2 $sink
$tcp2 set fid_ 2

#Setup a FTP over TCP connection

set ftp2 [new Application/FTP]
$ftp2 attach-agent $tcp2
$ftp2 set type_ FTP

#Schedule events for the CBR and FTP agents

$ns at 0.1"$ftp2 start"
$ns at 0.5"record $queue03 $qsize03"
$ns at 1.0"$ftp1 start"
$ns at 1.0"$ftp3 start"
$ns at 4.0"$ftp2 stop"
$ns at 4.5"$ftp1 stop"
$ns at 4.5"$ftp3 stop"

#Detach tcp and sink agents (not really necessary)

$ns at 4.5"$ns detach-agent $n0 $tcp1 ; $ns detach-agent $n3 $sink"
$ns at 4.5"$ns detach-agent $n1 $tcp2 ; $ns detach-agent $n3 $sink"

#Call the finish procedure after 5 seconds of simulation time

$ns at 5.0"finish"
$ns run

Tcl 的 expr 命令不适用于附加了 Mb 等单位的值。

所以它试图解释值 $rate12 是 4Mb,但这不是一个有效的数字文字,所以你得到了错误。再加上你不支持你的表达这一事实,例如你写:

1
set rate12 [expr $rate12 * $RL]

而不是

1
set rate12 [expr {$rate12 * $RL}]

你会得到对 expr 的双重评估,这会产生误导性的错误消息(并且可能会慢得多)。

要解决这个问题,您需要对没有单位的值进行计算,或者编写一个包含单位的小程序来完成。


关键字global 仅在proc 范围内有意义。要访问 rate12,请在 proc record 的开头添加以下行:

1
global rate12

这应该可以解决你的问题。

更新

我的错,我没有在 proc 中间看到 global 命令。问题是一开始你有:

1
set rate12 4Mb

然后,在 proc record:

1
set rate12 [expr $rate12 * $RL]

根据 Tcl,4Mb 不是数字。我建议进行以下修复:

1
set rate12 4

或者,更具描述性:

1
set rateInMb12 4