다음과 같은 가짜 직렬 장치를 만들고 있습니다.
socat -d -d pty,raw,echo=0 pty,raw,echo=0
매번 새로운 번호를 가진 장치가 생성됩니다. /dev/pty/6
그들에게 전화하자/dev/pty/7
내 테스트 컴퓨터에서 사용할 수 없는 하드웨어 장치를 시뮬레이션하기 위해 /dev/pty/6
초당 20줄의 속도로 썼습니다.
이와 유사합니다(실제 프로젝트에서는 Python으로 작성하고 있지만 이는 동일한 문제를 보여줍니다).
while true
do
date > /dev/pts/6
sleep 0.05
done
몇 초 동안 실행시키면 cat
/dev/pty/7
내가 쓴 다음 줄에서 시작하는 대신 중단한 부분부터 시작한다는 것을 알았습니다.
그래서 timeout 5 cat -n /dev/pty/7
중간에 쉬는 시간 없이 계속해서 보면 항상 100줄 정도 나옵니다. 그러나 "생산자" 스크립트를 5분 동안 실행한 다음 실행하면 timeout 5 cat -n /dev/pty/7
수천 줄이 표시됩니다. 마지막으로 읽은 이후에 작성된 모든 줄인 것 같습니다.
제가 시뮬레이션하려는 실제 하드웨어는 이와 같이 동작하지 않습니다.
timeout 5 cat -n /dev/ttyUSB0
그것은 항상 나에게 약 100줄을 제공합니다. 아무도 읽지 않는 줄을 버립니다.
하드웨어 장치의 이러한 측면을 어떻게 더 잘 에뮬레이트할 수 있습니까? 생산자 스크립트는 누군가가 읽고 쓰기만 하는지 확인해야 합니까? 아니면 socat 명령에 옵션을 제공해야 합니까?
Python으로 이 작업을 수행하면 작성 중인 버퍼가 가득 차서 생산자 프로그램이 공간이 작성될 때까지 기다리다가 멈춘 것 같지만 이 경우에는 이를 증명할 수 없습니다.
답변1
이 방법을 사용할 때의 문제점은 socat
pty에 큰 버퍼가 있다는 것입니다. Python을 사용하고 있으므로 직접 모의 작업을 시도할 수 있습니다. 예를 들어,
#!/usr/bin/python3
# https://unix.stackexchange.com/a/735081/119298
# some termios code from:
# https://github.com/pyserial/pyserial/blob/master/serial/serialposix.py
import os, time, struct, fcntl, termios
class pseudotty:
TIOCM_zero_str = struct.pack('I', 0)
def __init__(self, name, mode):
master, slave = os.openpty()
sname = os.readlink(f"/proc/self/fd/{slave}") # "/dev/pts/6"
os.unlink(name)
os.symlink(sname, name)
self.mfd = master
self.sfd = slave
self.file = os.fdopen(master, mode)
def waiting(self):
result = fcntl.ioctl(self.sfd, termios.FIONREAD, self.TIOCM_zero_str)
return struct.unpack('I', result)[0]
datain = pseudotty("input", "r")
dataout = pseudotty("output", "w")
while True:
d = datain.file.readline()
wait = dataout.waiting()
if wait<200:
dataout.file.write(d)
input
그러면 현재 작업 디렉토리 및 의 각 슬레이브에 대한 심볼릭 링크가 있는 두 개의 pty가 생성되고 열립니다 . 따라서 , 및 를 output
사용하여 루프를 부트스트랩할 수 있습니다 .date >input
cat
cat output
프로그램은 영원히 반복됩니다. 입력 pty에서 한 줄을 읽고, 출력 pty에서 현재 대기 중인 문자 수를 테스트하고, 문자가 200개 미만이면 해당 줄을 출력에 씁니다. 200자를 초과하면 입력이 삭제됩니다.
이를 통해 두 pty 사이에 버퍼링되는 데이터의 양을 어느 정도 제어할 수 있습니다. 물론 200개 제한을 15개로 대체할 수 있습니다 readline()
. read(1)
이렇게 하면 제한된 fifo를 사용하여 많은 직렬 장치를 에뮬레이션할 수 있습니다.