Python 我这里有线程问题吗?
我一直在试验GNU收音机,偶然发现了tunnel.py程序。此程序允许您使用Linux TUN/TAP设备通过无线无线电链路传输IP流量。在大多数情况下,它是工作的,但是代码的一部分让我困惑 有一个类实现了“基本MAC层”。此类具有一个回调函数,该函数将新数据包写入TUN设备。此函数(Python 我这里有线程问题吗?,python,multithreading,gnuradio,Python,Multithreading,Gnuradio,我一直在试验GNU收音机,偶然发现了tunnel.py程序。此程序允许您使用Linux TUN/TAP设备通过无线无线电链路传输IP流量。在大多数情况下,它是工作的,但是代码的一部分让我困惑 有一个类实现了“基本MAC层”。此类具有一个回调函数,该函数将新数据包写入TUN设备。此函数(phy\u rx\u callback)是从单独的线程调用的 功能main_loop在发送新数据包之前进行载波检测。我不明白的是,为什么它在一个单独的非重叠的传输通道上传输之前会感应到一个接收通道 RX和TX通道都
phy\u rx\u callback
)是从单独的线程调用的
功能main_loop
在发送新数据包之前进行载波检测。我不明白的是,为什么它在一个单独的非重叠的传输通道上传输之前会感应到一个接收通道
RX和TX通道都是独立的频率,我们的硬件允许全双工通信
因此,我的问题是,在执行main\u循环时,另一个线程异步调用phy\u rx\u回调
函数意味着什么?问题是我试图理解载波检测循环的目的,我发现注释该代码会严重降低性能。在使用传输通道之前监视接收通道对我来说毫无意义,实际上是将其转换为半双工。那么我看不出使用两个频率的目的,一个用于发射,一个用于接收。我开始怀疑这里是否有一个奇怪的线程问题
最初创建一个cs_mac
类的实例。指向rx_回调函数的“指针”向下传递到实际调用它的线程类。以下是cs_mac类:
class cs_mac(object):
def __init__(self, tun_fd, verbose=False):
self.tun_fd = tun_fd # file descriptor for TUN/TAP interface
self.verbose = verbose
self.tb = None # top block (access to PHY)
def set_top_block(self, tb):
self.tb = tb
def phy_rx_callback(self, ok, payload):
if self.verbose:
print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload))
if ok:
os.write(self.tun_fd, payload)
def main_loop(self):
min_delay = 0.001 # seconds
while 1:
payload = os.read(self.tun_fd, 10*1024)
if not payload:
self.tb.send_pkt(eof=True)
break
if self.verbose:
print "Tx: len(payload) = %4d" % (len(payload),)
delay = min_delay
while self.tb.carrier_sensed():
sys.stderr.write('B')
time.sleep(delay)
if delay < 0.050:
delay = delay * 2 # exponential back-off
self.tb.send_pkt(payload)
class cs\u mac(对象):
定义初始化(self,tun\u fd,verbose=False):
self.tun_fd=tun_fd#tun/TAP接口的文件描述符
self.verbose=verbose
self.tb=无#顶层块(访问物理层)
def set_top_块(自身,tb):
self.tb=tb
def phy_rx_回调(自身、正常、有效负载):
如果self.verbose:
打印“Rx:ok=%r len(有效负载)=%4d”%(ok,len(有效负载))
如果确定:
操作系统写入(self.tun\u fd,有效负载)
def主回路(自):
最小延迟=0.001秒
而1:
有效负载=操作系统读取(self.tun_fd,10*1024)
如果不是有效载荷:
self.tb.send_pkt(eof=True)
打破
如果self.verbose:
打印“Tx:len(有效负载)=%4d”%(len(有效负载),)
延迟=最小延迟
当self.tb.carrier_感应到()时:
sys.stderr.write('B')
时间。睡眠(延迟)
如果延迟小于0.050:
延迟=延迟*2#指数退避
self.tb.send_pkt(有效负载)
好的,所以使用调用gettid
的ctypes.CDLL('libc.so.6').syscall(186))
我发现调用rx\u回调函数的线程具有相同的PID,但TID不同
问题变成了,让一个单独的线程从主线程中的一个对象调用一个函数(当该线程不断循环时)意味着什么
函数main_loop在发送新数据包之前进行载波检测。我不明白的是,为什么它在一个单独的非重叠的传输通道上传输之前会感应到一个接收通道
CSMA/CA拟用于半双工系统,其中所有节点使用相同的频率发送和接收。所以你是对的,如果你在另一个信道中传输,那么感知RX信道是没有意义的
carrier_sensed()在receive_path.py文件中被调用,因此它应该在RX线程中运行。在我的代码中,我注释掉了sys.stderr.write('B')和time.sleep(delay)行,这似乎不会影响性能。在我的情况下可能会有所不同,因为我使用的是半双工的XCVR子板。不能说我对GNU收音机了解很多,但这是我的2美分。只要TX和RX在GNU无线电端使用单独的资源(软件和硬件方面),就可以将TX和RX放在单独的线程中。你说他们使用不同的频道,所以听起来他们可能是分开的。另一方面,他们使用相同的天线,所以你真的能同时发射和接收吗?