socat을 사용하여 직렬 장치를 시뮬레이션할 때 버퍼를 삭제하는 방법

socat을 사용하여 직렬 장치를 시뮬레이션할 때 버퍼를 삭제하는 방법

다음과 같은 가짜 직렬 장치를 만들고 있습니다.

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

이 방법을 사용할 때의 문제점은 socatpty에 큰 버퍼가 있다는 것입니다. 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 >inputcatcat output

프로그램은 영원히 반복됩니다. 입력 pty에서 한 줄을 읽고, 출력 pty에서 현재 대기 중인 문자 수를 테스트하고, 문자가 200개 미만이면 해당 줄을 출력에 씁니다. 200자를 초과하면 입력이 삭제됩니다.

이를 통해 두 pty 사이에 버퍼링되는 데이터의 양을 어느 정도 제어할 수 있습니다. 물론 200개 제한을 15개로 대체할 수 있습니다 readline(). read(1)이렇게 하면 제한된 fifo를 사용하여 많은 직렬 장치를 에뮬레이션할 수 있습니다.

관련 정보