Системные вызовы в C ++ и их роли в программировании - PullRequest
7 голосов
/ 23 мая 2009

Я часто слышал, что использование system("PAUSE") - плохая практика, и вместо этого следует использовать std::cin.get(). Теперь я понимаю, что системные вызовы берут строку, которую они вводят в системную командную строку, и общаются с ОС, поэтому PAUSE - это команда DOS, которая приостанавливает вывод в командном окне. Я предполагаю, что это работает аналогично с Mac и unix с разными ключевыми словами, и использование системных вызовов не рекомендуется из-за недостаточной совместимости с ОС. (Если я ошибаюсь, поправьте меня)

у меня такой вопрос: когда уместно использовать системные вызовы ()? Как они должны применяться? Когда они НЕ должны применяться?

Ответы [ 6 ]

29 голосов
/ 23 мая 2009

system("PAUSE"), конечно, не идеально. использование вызова системы создает подпроцесс, который в Windows довольно дорогой и в любом случае не очень дешевый в любой операционной системе. На встроенных системах накладные расходы памяти значительны.

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

Кроме того, он будет работать одинаково на всех операционных системах со всеми компиляторами c ++, поскольку он использует только очень базовую функцию очень стандартной части языка, а не зависит от того, что предоставляет ОС.

РЕДАКТИРОВАТЬ: предсказывая вашу обеспокоенность тем, что не имеет значения, стоит ли это дорого, потому что вся идея состоит в том, чтобы сделать паузу. Ну, во-первых, если это дорого, то это повредит производительности для всего, что может происходить. Когда-нибудь замечали (на окнах), когда запускается одно приложение, другие уже открытые приложения тоже становятся менее отзывчивыми? Кроме того, ваш пользователь может быть не живым человеком, а другой программой, работающей от имени пользователя (скажем, сценарий оболочки). Сценарий уже знает, что делать дальше, и может предварительно заполнить стандартный ввод символом, чтобы пропустить ожидание. Если вы использовали здесь подпроцесс, сценарий будет испытывать (заметную для человека) задержку. Если сценарий выполняет это сотни (или сотни миллионов!) Раз, сценарий, выполнение которого может занять несколько секунд, занимает дни или годы.

EDIT2: когда использовать system(): когда вам нужно сделать что-то, что делает другой процесс, что вы не можете сделать легко. system() не всегда лучший кандидат, потому что он делает две вещи, которые несколько ограничивают. Во-первых, единственный способ связаться с подпроцессом - использовать аргументы командной строки в качестве входных данных и возвращаемые значения в качестве выходных данных. Во-вторых, родительский процесс блокируется, пока дочерний процесс не завершится. Эти два фактора ограничивают случаи использования системы.

в unixy системах большинство подпроцессов происходит с fork, потому что он позволяет одной и той же программе продолжаться в том же месте, что и два отдельных процесса, один как потомок другого (что вряд ли заметно, если вы не попросите об этом у ОПЕРАЦИОННЫЕ СИСТЕМЫ). В Linux это особенно хорошо оптимизировано и примерно так же дешево, как создание pthread. Даже в системах, где это не так быстро, это все еще очень полезно (как продемонстрировано в методологии пула процессов Apache) (недоступно в Windows / ссылка на документацию Unix )

другие случаи (также и в Windows!) Часто обрабатываются семейством функций popen или exec. popen создает подпроцесс и совершенно новый канал, соединяющийся с stdin или stdout подпроцессов. И родительский, и дочерний процессы могут работать одновременно и взаимодействовать довольно легко. ( ссылка на документы Windows / ссылка на документы Unix )

exec* семейство функций (их несколько, execl, execv и т. Д.), С другой стороны, вызывает замену текущей программы новой программой. Исходная программа незаметно завершает работу, и новый процесс вступает во владение. Когда затем новый процесс возвращается, он вернется к тому, что называется исходным процессом, как если бы этот процесс вернулся в этот момент вместо исчезновения. Преимущество этого по сравнению с exit(system("command")) в том, что новый процесс не создается, что экономит время и память (хотя и не всегда ужасно) ( ссылка на документацию Windows / ссылка на документацию Unix )

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

3 голосов
/ 23 мая 2009

Но мой вопрос таков: когда уместно использовать системные вызовы ()? Как они должны применяться?

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

3 голосов
/ 23 мая 2009

Системные вызовы отправляются интерпретатору оболочки или командной строки ОС (dos, bash и т. Д.), А его задача - оболочке выполнять то, что она хочет, с помощью этой команды.

Вы бы избегали использования таких вызовов, поскольку это уменьшило бы переносимость ваших программ для работы с другими операционными системами. Я думаю, только если вы абсолютно уверены, что ваш код ориентирован на конкретную ОС, вам следует использовать такие вызовы.

2 голосов
/ 06 ноября 2012

Кстати, вызов system () никогда не должен использоваться с двоичными файлами с установленным битом SUID или SGID , цитата из справочной страницы

Не используйте system () из программы с set-user-ID или set-group-ID привилегии, потому что странные значения для некоторых переменных среды может быть использован для нарушения целостности системы. Используйте семейство exec (3) функции вместо, но не execlp (3) или execvp (3). система () не будет, на самом деле, работать правильно из программ с set-user-ID или set-group-ID привилегии в системах, в которых / bin / sh является версией bash 2, так как bash 2 сбрасывает привилегии при запуске.

1 голос
/ 23 мая 2009

system() используется для запроса операционной системы на запуск программы.

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

Функция system() сама по себе довольно переносима, но передаваемая ей командная строка, вероятно, будет очень специфичной для платформы - хотя командную строку можно извлечь из локальных данных конфигурации, чтобы сделать ее более независимой от платформы.

Другие функции, такие как fork(), exec*(), spawn*() и CreateProcess(), дадут вам гораздо больший контроль над тем, как вы запускаете внешнюю программу, но зависят от платформы и могут быть недоступны на вашей платформе. выбор.

system("PAUSE") - старый трюк для DOS, и в наши дни он считается довольно ненормальным.

1 голос
/ 23 мая 2009

Насколько я знаю, система ("ПАУЗА") - это единственное, что есть в Windows, и поэтому ее осуждают.

...