Неожиданный периодический, непостоянный выход для программы OCaml - PullRequest
0 голосов
/ 18 октября 2019

Кто-то сообщает, что при наличии потока строк на последовательном порту, который передается в конвейерную программу OCaml ниже, вывод программы не является непрерывным, а вместо этого он появляется в виде кусков (из нескольких десятков строк), как будтоbuffered.

Что может быть причиной прерывистого вывода?

(Выходной буфер должен сбрасываться после каждой новой строки из-за использования '%!'. Так что это не должноне причина, верно?)

let tp = ref 0

let get_next_entry ic =
  try
    let (ts, pred, v) = Scanf.fscanf ic " @%d %s@(%d)\n" (fun x y z -> (x,y,z)) in
    Printf.printf "at timepoint %d (timestamp %d): %s(%d)\n%!" !tp ts pred v;
    incr tp;
    true
  with End_of_file ->
    false

let _ =
  while get_next_entry stdin do
    ()
  done

Используемая версия OCaml - 4.05.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Это тройная проблема. От наименее вероятного к наиболее вероятному.

Сверкающий вывод

Это все в поле зрения наблюдателя, поскольку то, как будет выглядеть вывод программы, зависит от среды, в которой она находится. запустить, т. е. в программе, которая запускает вашу программу и отображает ее на визуальном устройстве. Другими словами, он включает в себя множество переменных, которые выходят за рамки этой программы.

С учетом сказанного, позвольте мне объяснить, что означает сброс для функции printf. Средство printf использует буферизованные каналы. И каждый канал - это примерно пара буферного и системного дескриптора файла. Когда кто-то (включая printf) выводит на канал, информация сначала попадает в буфер и остается там до тех пор, пока следующая порция информации не переопределит буфер (то есть, в буфере больше нет места) или пока функция очистки не будетназывается явно. Затем буфер очищается, что означает, что информация в буфере передается в операционную систему (например, с помощью системного вызова write или библиотечной функции).

То, что происходит потом, зависит от системы. Если дескриптор файла был связан с обычным файлом, то вы можете ожидать, что информация будет передана ему целиком (хотя файловая система имеет свою собственную иерархию кэшей, так что есть предостережения). Если дескриптор был связан с процессом оболочки в стиле Unix через канал, то он попадет в буфер канала, извлеченный из него оболочкой и напечатанный с использованием интерфейса терминала, обычно выполняемый с помощью некоторого эмулятора терминала. По умолчанию оболочки буферизуются строкой, поэтому строка должна быть напечатана целиком, если пользователь оболочки не изменит свои параметры каким-либо образом.

По сути, я надеюсь, что вы поняли, что это не ваша программа, которая фактически манипулирует терминалом и подсвечивает пиксели на ваших мониторах. Ваша программа просто выводит данные, а какая-то другая программа получает эти данные и рисует их на экране. И эта какая-то другая программа (терминал или эмулятор терминала, например, minicom) делает этот вывод сбойным, а не ваша программа. Ваша программа делает все возможное, чтобы печататься правильно - полная строка или ничего.

Ваша программа дает сбой

И это так. In_channel также буферизуется, поэтому он накапливает несколько байтов перед вызовом sprintf. Поэтому вы можете просто читать с буферизованного канала и ожидать ответа в реальном времени. Самый надежный способ для вас - использовать модуль Unix и обрабатывать ввод, используя собственную буферизацию.

Блестящий ввод

Наконец, программа ввода также может дать вам информациюкускамиЭто особенно верно для последовательных интерфейсов, поэтому убедитесь, что вы правильно настроили интерфейс терминала, используя функцию Unix.tcsetattr. В частности, когда ваша программа заблокирована на входе, операционная система может принять решение не включать ее для каждого поступившего символа или строки. Это поведение контролируется интерфейсом терминала (см. Канонический и Неканонический режимы. Если на вашем входе нет новых строк, вы должны использовать неканонический режим).

Наконец, само устройство может дрожать, и если у вас есть осциллограф поблизости, вы можете наблюдать сигналы, которые оно посылает. И убедитесь, что вы настроили ваш последовательный порт, как предписано в руководстве пользователя вашего устройства.

0 голосов
/ 18 октября 2019

Одна возможность состоит в том, что fscanf ждет, пока не увидит все, что ищет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...