2015-02-10 2 views
1

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

Установка такова:

  1. класс Java (A.java) запускается

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

  3. A.java считывает из входного потока объекта с использованием процесса BufferedReader

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

Бо двоичная просто печатает случайные строки с помощью вызова функции Printf.

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

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

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

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

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

  1. ли ТРУБЫ процесса, созданного с помощью Java Runtime API блокирующие или без блокировки?

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

  3. Любой не-программным способом (т.е. я не должен изменить исходный код Java и т.д.!), Чтобы выяснить, если ТРУБ процесса блокируют или не блокировать?

спасибо.

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

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

Источник "B.o":

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

Источник "A.java":

<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 для исполняемых файлов (ваш 'B.o'). Это расширение обычно используется для объектных файлов. –

+0

Сон не должен изменять вход, который вы получаете из InputStream, завернутого в BufferedReader. «Неблокирующее» чтение не означает, что вы пропускаете ввод, чтобы перейти к более поздней записи в трубе. Тем не менее, неясно, почему вы наблюдаете пропущенные данные. Не могли бы вы разместить соответствующий код? –

+1

Действительно "случайные" линии? Вы никогда не узнаете, пропадут ли некоторые из них. – laune

ответ

3

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

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

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

ли патрубки процесса, созданного с помощью Java Runtime API блокирует или без блокировки?

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

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

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

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

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

+0

Спасибо за очень подробный ответ. Не могли бы вы сообщить мне дополнительно, если конец записи канала B.o (c двоичный) блокируется или не блокируется? Потому что единственная причина, по которой я могу думать о том, что все данные не проходят, - это то, что буфер записи в трубе (на конце B.o) заполняется (поскольку я заставляю свой Java-код спать и, таким образом, вызывая задержку опорожнения буфера). Это приводит к отбрасыванию переполняющих данных. Но для этого не будет трубы, которая должна быть неблокирующей? – Undefined

+0

Блокировка против неблокирования связана с тем, будут ли блокировки 'read()' и 'write()' блокироваться, когда они не смогут сразу перенести какие-либо данные. Ни при каких обстоятельствах вы не должны ожидать, что труба потеряет данные, независимо от блокировки и неблокирующего режима. Если вы не получаете все данные, которые вы ожидаете от 'B.o', то это почти наверняка, потому что' B.o' является ошибкой. В первую очередь ваши данные не переходят в * трубу. –

+0

Обратите также внимание на то, что успешные 'read()' и 'write()' syscalls не гарантируют передачу полного количества запрошенных байтов, за исключением случаев, когда указан только один байт, и файловый дескриптор открыт в режиме блокировки. За исключением однобатного специального случая, который не зависит от режима блокировки. Предполагая, что эти вызовы будут передавать полное количество запрошенных байтов, является общей ошибкой, но в том, что вам нужно беспокоиться, только если вы вызываете эти функции напрямую. –

0

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

Смежные вопросы