#python #pty
#python #pty
Вопрос:
Я работаю над проектом, который взаимодействует с «виртуальными устройствами» (процессами python), которые используют соединения с последовательным портом, с реальными устройствами, которые также используют последовательные порты, и я использую псевдотерминальные модули для соединения нескольких (более 2) из этих процессов обмена данными с последовательным портом (моделирующих последовательные устройства) вместе, и я столкнулся с небольшой проблемой.
У меня есть процесс python, который генерирует псевдотерминальные файлы, символически связывает подчиненный конец pty с файлом (чтобы процессы могли создавать объект pyserial с именем файла), в то время как основные концы хранятся моим процессом генерации pty и считываются; когда данные поступают на один ведущий сервер, данные регистрируются, а затем записываются на другие ведущие устройства. Этот подход работает, если процесс прослушивания всегда присутствует.
Проблема заключается в том, что виртуальное устройство умирает или никогда не запускается (что является допустимым вариантом использования для этого проекта). В моей системе кажется, что если данные записываются на главный конец pty, если на подчиненном конце ничего не прослушивается, вызов read на этом главном сервере вернет данные, которые были только что записаны! Это означает, что устройства получают одни и те же данные более одного раза — нехорошо!
Пример:
>>master, slave = pty.openpty()
>>os.write(master,"Hello!")
6
>>os.read(master,6)
'Hello!'
Я бы предпочел, чтобы вызов read() блокировался до тех пор, пока подчиненное устройство не отправит данные. Фактически, это поведение ведомого устройства — оно может записывать, а затем os.read (ведомое устройство, 1) будет блокироваться до тех пор, пока ведущее устройство не запишет данные.
Мои «виртуальные устройства» должны иметь возможность передавать имя файла, чтобы открыть объект последовательного порта; Я попытался создать символическую ссылку на главный конец, но это приводит к тому, что мои виртуальные устройства открывают / dev / ptmx, что создает новую псевдотерминальную пару вместо обратной связи с уже существующими подчиненными устройствами!
Есть ли какой-либо способ изменить поведение мастера? Или даже просто передать ведущему файл, соответствующий подчиненному устройству (не только /dev/ptmx)?
Заранее спасибо!
Ответ №1:
Я почти уверен, что это потому, что эхо включено по умолчанию. Чтобы позаимствовать из Python termios docs, вы могли бы сделать:
master, slave = os.openpty() # It's preferred to use os.openpty()
old_settings = termios.tcgetattr(master)
new_settings = termios.tcgetattr(master) # Does this to avoid modifying a reference that also modifies old_settings
new_settings[3] = new_settings[3] amp; ~termios.ECHO
termios.tcsetattr(master, termios.TCSADRAIN, new_settings)
Вы можете использовать следующее, чтобы восстановить старые настройки:
termios.tcsetattr(master, termios.TCSADRAIN, old_settings)
Комментарии:
1. Я почти уверен, что это тоже так, но вы хотите отключить echo на стороне ведомого устройства. Помните, что ptys — это псевдотерминалы, а master — это как ваша клавиатура / дисплей, а slave — как устройство / dev / ttyxx, к которому оно подключено. ptys эмулируют всю обработку терминала, что здесь может быть бесполезно; OP может посмотреть, как работают FIFOs в качестве альтернативы.
Ответ №2:
На случай, если кто-то найдет этот вопрос, и ответ jszakmeister не сработает, вот что сработало для меня.
openpty
кажется, создает pty в каноническом режиме с включенным echo. Это не то, чего можно было бы ожидать. Вы можете изменить режим с помощью tty.setraw
функции, как в этом примере простого эхо-сервера openpty:
master, slave = os.openpty()
tty.setraw(master, termios.TCSANOW)
print("Connect to:", os.ttyname(slave))
while True:
try:
data = os.read(master, 10000)
except OSError:
break
if not data:
break
os.write(master, data)
Комментарии:
1. Это очень странно. openpty создает pty master / slave — подчиненный является терминалом, мастер — нет. Основная сторона не читает canonical и не обращает никакого внимания на настройки IGNCR или INLCR и т.д. Но. Он выполняет эхо без ведомого устройства, если вы это не отключите! Это не то, чего я ожидал.