2017-01-31 3 views
0

У меня есть устройство, у которого есть драйвер sysfs. Прежде чем делать что-либо еще, мне нужно настроить устройство, записав содержимое файла «configs.txt» в файл в каталоге sysfs для подсистемы. Это может быть успешно сделано сЗаписывает ли файл dev/sys дочерний процесс?

cat /home/configuration/configs.txt > /sys/bus/iio/devices/device3/config 

Если ввести эту команду в терминале, она занимает около 5 секунд для следующей строки для печати. Я полагаю, это означает, что независимо от того, что делает драйвер sysfs, требуется около 5 секунд.

Однако, если я пытаюсь использовать popen() следующим образом:

int main(void){ 
    FILE *file; 
    char terminal[512]; 

    if(!(file=popen("cat /home/configuration/configs.txt > /sys/bus/iio/devices/device3/config", "r"))){return -1;} 

    while(fgets(terminal,sizeof(terminal),file)!=NULL){ 
     printf("%s\n",terminal); 
    } 

    pclose(file); 
    printf("Done\n"); 
} 

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

Я думаю, что popen() считает завершение команды cat как конец процесса и, таким образом, заканчивает popen() и перемещается дальше. Он не считает, что драйвер sysfs делает как часть этого, и не ждет его.

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

Как я могу контролировать это и ждать завершения этой программы?

+0

Я не понимаю. На этой странице https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm, похоже, указывается, что fgets возвращает NULL после достижения конца выполнения, и больше не нужно читать с терминала. –

+0

Процесс 'cat', который вы охватываете, не собирается ничего писать в' stdout'. Приглашение, которое вы получаете после этой командной строки, находится из оболочки, а не из 'cat'. Поэтому не ожидайте выхода из него. –

+0

Что было бы другим способом определить, когда обработка, выполняемая драйвером sysfs, завершена? –

ответ

1

Применение pclose()

труба открыта с popen() должны быть закрыты с pclose(). Кроме того, выполнение блоков, пока дочерний процесс не будет завершен:

Функции pclose() ожидает связанный процесс прекратить и возвращает статус завершения команды, возвращаемый wait4 (2).

Но это совершенно бесполезно, поскольку ничто никогда не вернется через эту трубу. Так было бы лучше, чтобы

использования system()

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

Лучше всего было бы

все это делать сами

Вы можете открыть config.txt и файл в sysfs самостоятельно, и скопировать содержимое. Обязательно закройте их и потом, и проверьте возвращаемое значение на каждом шаге, таким образом вы точно поймете, что пошло не так, когда оно не работает.

+0

Спасибо, что ответили. Хотя мой пример не имеет выхода, есть сообщение об ошибках. Например, если конфигурации, перечисленные в файле config.txt, неприемлемы. Поэтому в лучшем случае я мог бы использовать систему, но в худшем случае я хочу поймать сообщение об ошибке, поэтому я хочу попена. Тем не менее, я уже использую pclose, поэтому я запутался, что программа закрывается преждевременно. –

+0

Упс, не должен был отвечать на вопрос, прежде чем читать его. Во всяком случае, существует около ста способов команды, и это вызов через оболочку может пойти не так, мы даже не знаем, запущен ли процесс cat или не. В соответствии с «man popen» проверка возвращаемого значения даже не говорит вам, можно ли вообще запустить _shell_. – berendi

+0

Я просто попытался изменить мою программу, добавив '&& echo done' в команду в popen, и это заканчивается тем, что распечатывается, поэтому кажется, что он вызывает команду правильно. Но все равно идет очень быстро. –

0

Я полагаю, что popen() считает завершение команды cat как будучи в конце процесса, и таким образом заканчивает popen() и идет дальше. Он не учитывает, что делает драйвер sysfs как часть , и не ждет его.

Оболочка считает завершение команды cat как конец процесса. Вероятно, ваш водитель забирает несколько секунд.

Ваша программа, с другой стороны, контролирует трубку из процесса, выполняющего вашу команду. Когда конец записи этой трубки закрыт, это, естественно, указывает на то, что конец файла popen() был достигнут. fgets() вернет NULL в ответ, сломав петлю. Поскольку ваша команда перенаправляет свой стандартный вывод в файл, это происходит сразу.

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

popen()делает запуск дочернего процесса. Было бы глупо вставлять дополнительный, и в любом случае это не решит фундаментальную проблему вашего подхода.

Ваш самый простой подход может заключаться в использовании system() вместо popen(). Как и оболочка, system() будет ждать завершения команды, которую вы передаете ей, а не отслеживания ее вывода. В любом случае выхода не ожидается (см. Выше), поэтому popen() довольно бессмысленно.

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

Как я могу контролировать это и ждать завершения этой программы?

Команда system() сделает это за вас. Если вы выполните fork() дочерний процесс для выполнения работы, вы можете дождаться его завершения через wait() или waitpid(). Если вы пишете непосредственно в целевой файл sysfs, то после успешного закрытия этого файла ваша программа будет иметь такую ​​же уверенность, как cat может предоставить конфигурацию, которая была завершена.

+0

Хотя в том случае, если я предложил, нет выхода, может быть. Драйвер sysfs может печатать сообщение об ошибке, если что-то сжимается, поэтому я хочу всплывать, поэтому я могу поймать это сообщение об ошибке, если оно появится. Вот почему я избегал вызова system(). В идеальном случае мне это не нужно, но в худшем случае я хочу поймать сообщение об ошибке. –

+0

Нет, вы не можете. Драйвер устройства не имеет возможности напечатать что-либо на стандартном выходе пользовательского процесса, который вы можете поймать с помощью 'popen()'. Но даже если это как-то удалось сделать, стандартный вывод 'cat' перенаправляется обратно в его интерфейс конфигурации, а стандартная ошибка не захватывается' popen() '. Драйвер может выводить что-то в системный журнал, который можно настроить для его печати на консоль, которая может оказаться вашим терминалом. – berendi

+0

@Craig любые сообщения, выданные драйвером * не могут * быть на стандартном выходе 'cat', и поэтому в любом случае ваш файл' popen() '' d не будет читаться. В любом случае вы должны обнаружить, что оболочка, порожденная 'system()', наследует стандартные потоки своего родителя. Если драйвер записывает либо стандартный вывод, либо (более вероятно) стандартную ошибку, тогда 'system()' вполне может делать то, что вы хотите естественным образом. Тем более, если драйвер записывает непосредственно на терминал пользователя. –

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