我试图对linux上的串行端口进行多重访问。我正在使用一个嵌入式系统,它只有一个串口,如果有多个进程和它交谈,那就太好了。
常见的用例是:
首先,我制作了一个简单的python脚本来打开n个伪终端对(加上串口),并使用一个轮询语句将输入/输出定向到正确的位置:
# Removed boiler plate and error checking for clarity
##### Serial port setup
ttyS = serial.Serial(device, baudrate, width, parity, stopbits, 1, xon, rtc)
ttyS.setTimeout(0) # Non-blocking
##### PTYs setup
pts = []
for n in range(number_of_slave_terminals):
master, slave = os.openpty()
# Print slave names so others know where to connect
print >>sys.stderr, 'MUX > fd: %d pty: %s' % (slave, os.ttyname(slave))
pts.append(master)
##### Poller setup
poller = select.poll()
poller.register(ttyS.fd, select.POLLIN | select.POLLPRI)
for pt in pts:
poller.register(pt, select.POLLIN | select.POLLPRI)
##### MAIN
while True:
events = poller.poll(500)
for fd, flag in events:
# fd has input
if flag & (select.POLLIN | select.POLLPRI):
# Data on serial
if fd == ttyS.fd:
data = ttyS.read(80)
for pt in pts:
os.write(pt, data)
# Data on other pty
else:
ttyS.write(os.read(fd, 80))如果每个pty都连接在一起,这种方法就能很好地工作。如果有一些未连接的pty,那么它的缓冲区最终会被填满,并阻塞写入。似乎我需要知道哪些奴隶是相连的,或者是某种按需打开的。
我在this question上发现了一个巧妙的技巧,这个家伙只需要完成串口部分的读取,所以我修改了我的脚本:
##### Serial port setup
ttyS = serial.Serial(device, baudrate, width, parity, stopbits, 1, xon, rtc)
ttyS.setTimeout(0) # Non-blocking
##### PTYs setup
pts = []
for n in range(number_of_slave_terminals):
master, slave = os.openpty()
# slaves
print >>sys.stderr, 'MUX > fd: %d pty: %s' % (slave, os.ttyname(slave))
os.close(slave) # POLLHUP trick
# masters
pts.append(master)
##### Poller setup
reader = select.poll()
writer = select.poll()
reader.register(ttyS, select.POLLIN | select.POLLPRI)
for pt in pts:
reader.register(pt, select.POLLIN | select.POLLPRI)
writer.register(pt, select.POLLIN | select.POLLPRI | select.POLLOUT)
def write_to_ptys(data):
events = writer.poll(500)
for fd, flag in events:
# There is someone on the other side...
if not (flag & select.POLLHUP):
os.write(fd, data)
##### MAIN
while True:
events = reader.poll(500)
for fd, flag in events:
if flag & (select.POLLIN | select.POLLPRI):
# Data on serial
if fd == ttyS.fd:
write_to_tty(ttyS.read(80))
# Data on other pty
else:
ttyS.write(os.read(fd, 80))它可以工作,但是使用100%的CPU,因为读取器轮询中充斥着POLLHUP事件。
我想,如果我使用TCP套接字而不是伪终端,我可以得到我想要的东西。缺点是,我必须修改所有其他已经与终端一起工作的脚本,以使用套接字(我知道我可以使用套接字,我只是想要一些更简单的东西)。另外,网络的开销很大.
有什么想法吗?
我不介意使用其他工具,只要设置简单。我也不介意使用其他语言,我只是最喜欢Python。
发布于 2012-10-01 16:08:58
最后我写了一个简单的TCP服务器,就像我说过我不想.不过,效果真的很好。它使用与问题上的代码相同的通用体系结构,但使用TCP套接字而不是伪终端。
我把它贴在here上,以防有人想要使用它。
称之为:
md:mux_serial> ./mux_server.py --device /dev/ttyS0 --baud 115200 --port 23200
MUX > Serial port: /dev/ttyS0 @ 115200
MUX > Server: localhost:23200我在另一个终端上用socat直接访问端口.
md:~> socat -,raw,echo=0,escape=0x0f TCP4:localhost:23200...or用于创建伪终端,以便在需要以下内容的脚本中使用:
md:~> socat -d -d pty,raw,echo=0 TCP4:localhost:23200
2012/10/01 13:08:21 socat[3798] N PTY is /dev/pts/4
2012/10/01 13:08:21 socat[3798] N opening connection to AF=2 127.0.0.1:23200
2012/10/01 13:08:21 socat[3798] N successfully connected from local address AF=2 127.0.0.1:35138
2012/10/01 13:08:21 socat[3798] N starting data transfer loop with FDs [3,3] and [5,5]https://stackoverflow.com/questions/12518559
复制相似问题