Выполняется двоичный код C из Java и чтение из выходного потока процесса

1

Итак, я пытаюсь прочитать вывод двоичного кода из java-кода, и я не могу понять, заблокирован ли канал связи или не блокируется.

Настройка такова:

  1. A.java Java-класс (A.java)

  2. A.java запускает двоичный файл (Bo) с помощью Runtime.getRuntime().exec("Bo"). На данный момент у меня есть объект Process (возвращается Runtime.exec)

  3. A.java считывает из входного потока объекта Process с помощью буферизированного считывателя

  4. A.java выводит данные, считываемые из входного потока, в файл (output.txt)

Би бинарный файл просто печатает случайные строки, используя вызов функции printf.

Теперь, если я запустил вышеуказанную настройку, я получаю все данные, отправленные Bo безупречно. Затем, чтобы проверить (блокирующая/неблокирующая вещь), я изменил A.java чтобы спать в течение 5 миллисекунд после каждого чтения из A.java объекта Process из Bo. Как оказалось, теперь я не получал полных данных в A.java отправленных Bo. Это указывает на то, что используемый канал связи не блокирует (согласно моему слабому пониманию).

Затем, чтобы убедиться, я начал изучать исходный код Java, чтобы убедиться, что я прав. И я нашел следующее:

Каждый вызов Runtime.getRuntime().exec(...) завершается forkAndExec() в ProcessImpl_md.c. В ProcessImpl_md.c выполняется команда, создается процесс, и PIPES настраиваются для связи (используя вызов функции pipe в c). Я не могу найти нигде в исходном коде, где PIPES устанавливаются в неблокирующий режим (как указано моим кодом). Я предполагаю, что PIPES блокируются по умолчанию.

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

Может ли кто-нибудь указать мне в правильном направлении или сказать мне:

  1. Являются ли ТРУБЫ процесса, созданного с помощью API-интерфейса java runtime, блокирующими или не блокирующими?

  2. Когда я делаю A.java сон после чтения из входного потока, почему все данные не получены? (Предполагая, что PIPE блокирует)

  3. Любой непрограммный способ (т.е. Мне не нужно менять исходный код java и т.д.!), Чтобы выяснить, блокируются или не блокируются PIPES процесса.

Спасибо.

EDIT: (добавленный код)

Ниже приведен не фактический (или даже компилируемый) код, но он показывает, что я пытаюсь сделать.

Источник "Бо":

#include <stdio.h>
void main(int argc, char*argv[]){
    int a = 0;
    for(; a<9000000; a++){
        printf("%s", argv[1]);
    }
}

Источник "А.Ява":

<java imports>
public class A{
    public static void main(String[] args) throws Exception{
        Process p = Runtime.getRuntime().exec("./B.o");
        BufferedReader br = new 
            BufferedReader(new InputStreamReader(p.getInputStream()));
        int a = 0;
        while(br.readLine() != null){
            a++;
            Thread.sleep(5);//data missed if this line not commented out
        }
        br.close();
        System.out.println(a);
    }
}

ПОЖАЛУЙСТА, ПРОВЕРЬТЕ МОЙ ОТВЕТ. БЕСПЛАТНЫЙ ВОПРОС МЕНЯ.

  • 0
    Я бы не использовал расширение * .o для исполняемых файлов (ваш Bo ). Это расширение обычно используется для объектных файлов.
  • 0
    Спящий режим не должен изменять входные данные, которые вы получаете от InputStream, обернутого в BufferedReader. «Неблокирующее» чтение не означает, что вы пропускаете ввод, чтобы перейти к более новым записям в канале. Тем не менее, не ясно, почему вы наблюдаете пропущенные данные. Не могли бы вы опубликовать соответствующий код?
Показать ещё 6 комментариев
Теги:

2 ответа

3
Лучший ответ

Независимо от того, работают ли каналы связи между Java и внешней программой (есть три, одна от Java до родной и две возвратные), работают в режиме блокировки или неблокирования, не имеют прямого отношения к тому, будут ли все данные успешно передаваться по каждому из них. Аналогично, задержки между запросами чтения напрямую не связаны с тем, будут ли все данные успешно передаваться, независимо от блокировки и неблокирующего ввода-вывода в вашей конкретной реализации java.lang.Process.

Действительно, ваши усилия по проверке блокировки и неблокирующих межоперационных операций ввода-вывода бесполезны, поскольку интерфейс ввода-вывода, предоставляемый вашей программе Java, основан на InputStream и OutputStream, которые обеспечивают только блокировку ввода-вывода. Даже если неблокирующий ввод-вывод был задействован на каком-то низком уровне реализации, я не могу придумать, как ваша программа сможет обнаружить это.

Однако в отношении ваших конкретных вопросов:

Являются ли ТРУБЫ процесса, созданного с помощью API-интерфейса java runtime, блокирующими или не блокирующими?

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

Когда я делаю A.java сон после чтения из входного потока, почему все данные не получены? (Предполагая, что PIPE блокирует)

Я могу только догадываться, но проблема, скорее всего, во внешней программе. Возможно, он ложится спать, когда его выходной буфер заполняется, и ничего не происходит, чтобы разбудить его. Это может помочь вызвать myProcess.getOutputStream().close() если ваша Java-программа не отправляет данные во внешнюю программу. Это в любом случае хорошая идея закрыть этот поток, как только вы написали ему все, что вы когда-либо собираетесь писать.

Любой непрограммный способ (т.е. Мне не нужно менять исходный код java и т.д.!), Чтобы выяснить, блокируются или не блокируются PIPES процесса.

Потенциально вы можете запустить VM под strace или подключить к нему собственный отладчик и проанализировать поведение VM таким образом. Если вы хотите сделать это изнутри Java, тогда ответ будет звучать "НЕТ". Ваша Java-программа увидит блокирующее поведение при любых обстоятельствах, потому что OutputStream требуют контракты InputStream и OutputStream.

  • 0
    Спасибо за очень подробный ответ. Можете ли вы сообщить мне, если конец записи канала Bo (c бинарный) является блокирующим или неблокирующим? Потому что единственная причина, по которой я могу думать о том, что все данные не проходят, состоит в том, что буфер записи канала (на стороне Бо) заполняется (так как я заставляю свой код Java спать, и таким образом вызываю отложенное опустошение буфера). Это приводит к удалению переполненных данных. Но чтобы это произошло, разве труба не должна быть неблокирующей?
  • 0
    Блокирование против неблокирования относится к тому, будут ли блокировать вызовы read() и write() , когда они не могут немедленно передать какие-либо данные. Ни при каких обстоятельствах не следует ожидать, что канал потеряет данные, независимо от режима блокировки или неблокирования. Если вы не получаете все данные, которые ожидаете от Bo , то это почти наверняка, потому что Bo глючит. Ваши данные не идут в трубу в первую очередь.
Показать ещё 2 комментария
0

Я делал большую ошибку и был полностью вне базы. Проводя этот ответ, чтобы прояснить ситуацию (хотя я бы вообще хотел удалить этот вопрос). Я хотел знать, блокируют или не блокируют каналы связи между двоичным кодом C от Java-кода. И я упомянул, что данные отсутствовали, когда я сделал свой код java-кода после чтения из потока ввода созданного процесса (кода C). Из-за этого данные не пропали без вести. Я на самом деле поставил таймер в Java-коде, после чего завершил процесс бинарного цикла C. И поскольку блокировки PIPES блокируются, он не смог получить все данные до истечения таймера. Я неправильно интерпретировал эту потерю данных, чтобы означать, что ТРУБЫ не блокируют. Подтвердил это, запустив STRACE на созданном двоичном процессе C. Не было ошибок EAGAIN для системных вызовов write. Виноват. Но большое спасибо всем за то, что вы нашли время ответить.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню