Определить ОС во время выполнения

Ни ISO C, ни POSIX не предлагают функций для определения базовой ОС во время выполнения. С теоретической точки зрения это не имеет значения, так как C предлагает оболочки для наиболее распространенных системных вызовов, а с точки зрения придирки даже не обязательно существовать лежащий в основе ОПЕРАЦИОННЫЕ СИСТЕМЫ.

Однако во многих реальных сценариях полезно знать больше о хост-среде, чем C готов поделиться, например. для того, чтобы узнать, где хранить конфиги или как вызывать select(), итак:

Есть ли идиоматический способ для приложения, написанного на C, определить базовую ОС во время выполнения?

По крайней мере, могу ли я легко выбирать между Linux, Windows, BSD и MacOS?

Мое текущее предположение состоит в том, чтобы проверить наличие определенных файлов/каталогов, таких как C:\ или /, но этот подход кажется ненадежным. Возможно, запрос ряда таких источников может помочь установить понятие «отпечатки пальцев ОС», что повысит надежность. В любом случае, я с нетерпением жду ваших предложений.


person Philip    schedule 03.01.2012    source источник
comment
Э-э, вы знаете эту информацию во время компиляции   -  person David Heffernan    schedule 03.01.2012
comment
Как определение ОС во время выполнения помогает вам правильно написать вызов select()?   -  person Kerrek SB    schedule 03.01.2012
comment
+1, @ Дэвид. По крайней мере, для различий, таких как Linux, Windows, Mac OS X и т. Д. Я предполагаю, что способ выполнения, позволяющий различать разные версии каждого из них, может быть тем, что ищет OP, но ответ на это будет специфичным для каждого операционная система, предположительно.   -  person Carl Norum    schedule 03.01.2012
comment
@ Дэвид: мне не нравится #ifdef.   -  person Philip    schedule 03.01.2012
comment
Попытайтесь запустить программу в течение некоторого времени. Если он погибает в результате сбоя, вы находитесь в Windows. Если ОС обновится до 5G или Cat, вы на Mac. Если вас взломают через 180 дней, это Linux. Иначе это БСД.   -  person Kerrek SB    schedule 03.01.2012
comment
Вы «на самом деле» не знаете эту информацию во время компиляции. Вы можете запускать двоичные файлы Windows на Wine + Linux, вы можете запускать бинарные файлы Linux на Solaris, вы можете запускать бинарные файлы Linux на некоторых BSD.   -  person rsaxvc    schedule 03.01.2012
comment
@Philip Ну, #ifdef здесь важно, вы должны научиться ладить с этим, даже если вы не можете заставить себя полюбить это   -  person David Heffernan    schedule 03.01.2012
comment
@rsaxvc, но что касается вашего приложения, то wine+linux является окнами, запуск бинарных файлов Linux в Solaris является linux, а запуск их в BSD по-прежнему линукс.   -  person Carl Norum    schedule 03.01.2012
comment
@rsaxvc Тогда эмулятор должен хорошо выполнять роль эмулируемой системы. Когда вы работаете на Wine, ОС — это Windows с точки зрения программы.   -  person David Heffernan    schedule 03.01.2012
comment
@ Дэвид Хеффернан: Что ты имеешь в виду? Ни один из них не является эмулятором.   -  person rsaxvc    schedule 03.01.2012
comment
@Carl, но вам может потребоваться изменить поведение ОС во время выполнения, чтобы справиться с этим. Посмотрите на файловую систему proc — во многих юнитах она разная, поэтому вам придется иметь дело с ней во время выполнения, если вы выполняете бинарную совместимость.   -  person rsaxvc    schedule 03.01.2012
comment
wine даже говорит вам по названию: Wine — это не эмулятор   -  person Philip    schedule 03.01.2012
comment
@rsaxvc - конечно, но если вы пишете приложение, которое собираетесь запускать в этих эмулируемых средах, вам нужно это учитывать. Если вы пишете приложение для Windows, которое не работает в Wine, это просто означает, что Wine недостаточно хорошо справляется со своей задачей.   -  person Carl Norum    schedule 03.01.2012
comment
@CarlNorum - я знаю, это то, что я сказал, поэтому вам может понадобиться знать ОС во время выполнения, а не во время компиляции. (Лично я бы предпочел просто скомпилировать его дважды и завершить специфику ОС)   -  person rsaxvc    schedule 03.01.2012
comment
@rsaxvc Конечно, это эмулятор. Он эмулирует Windows в системах, отличных от Windows. Людям WINE не нравятся негативные коннотации этого слова и, в частности, ожидание плохой работы эмулятора. Но это эмулятор точно так же, как WOW64 является эмулятором.   -  person David Heffernan    schedule 03.01.2012
comment
@DavidHeffernan - Плохой пример - в WOW64 ЦП напрямую выполняет инструкции x86-32, как и в WINE. Что такое WINE, так это набор библиотек, реализующих WINAPI на другом сервере. Нет эмуляции ни в том, ни в другом (если вы не имеете в виду WOW64 на Itanium...)   -  person rsaxvc    schedule 03.01.2012
comment
@DavidHeffernan - я думаю, это просто семантика, не имеющая прямого отношения к рассматриваемому вопросу.   -  person rsaxvc    schedule 03.01.2012
comment
@rsaxvc Ах, вы определяете эмуляцию как эмуляцию оборудования. Более общее определение, которое я использую, включает эмуляцию программного обеспечения. описание Microsoft WOW64 начинается так : WOW64 — это эмулятор x86, который позволяет 32-разрядным приложениям Windows без проблем работать в 64-разрядной версии Windows. Да, это не связано с Q. Не стесняйтесь прибираться.   -  person David Heffernan    schedule 03.01.2012
comment
Я все еще пытаюсь понять, почему вам не нравится #ifdef, но вы вполне можете использовать if. Любое понимание этого?   -  person Cody Gray    schedule 03.01.2012


Ответы (5)


На самом деле, в большинстве систем есть команда uname, которая показывает текущее используемое ядро. В Mac OS это обычно «Darwin», в Linux — просто «Linux», в Windows — «ERROR», а FreeBSD вернет «FreeBSD».

Более полный список uname результатов

Я почти уверен, что для uname существует эквивалент C, так что system() вам не понадобится.

person Tom van der Woerdt    schedule 03.01.2012
comment
Кажется, я вас всех обыграл :-) - person Tom van der Woerdt; 03.01.2012
comment
@Tom Ты уверен в том, что происходит в Windows? Для всех компиляторов C? - person David Heffernan; 03.01.2012
comment
@DavidHeffernan Ха-ха, я уверен, что он не вернет строку ERROR. Однако результаты в Windows сильно различаются. Насколько я знаю, только cygwin возвращает правильный uname, но некоторые компиляторы могут его скомпилировать. Из-за этого uname ненадежен при запуске под Wine или Crossover. - person Tom van der Woerdt; 03.01.2012
comment
@TomvanderWoerdt - я опубликовал одно сообщение, в котором говорилось, что «вы правы, это невозможно сделать для всех ОС», но потом понял, что ОП спрашивал только о BSD/OSX/Windows/Linux. - person rsaxvc; 03.01.2012

ЕСЛИ вы работаете в системе POSIX, вы можете вызвать uname() из <sys/utsname.h>.

Это, очевидно, не на 100% переносимо, но я не думаю, что будет какой-либо метод, который может предоставить это во время выполнения.

подробности см. на справочной странице.

person rejj    schedule 03.01.2012

Время выполнения — не время определять это, так как без эпических заморочек двоичные файлы для одной платформы не будут работать на другой, вам следует просто использовать #ifdefs вокруг кода, чувствительного к платформе.

person richo    schedule 03.01.2012
comment
-1 потому что вопрос был о том, как определить операционную систему во время выполнения, а не о том, стоит ли это делать. - person rurouniwallace; 19.07.2014
comment
Да, но это не помогает ОП. В VAST большинстве случаев объект, сгенерированный для FreeBSD, в любом случае не будет работать в Linux (что справедливо для большинства его случаев), поэтому делать это во время выполнения - наименьшая из его проблем. - person richo; 03.08.2014

В принятом ответе указано uname, но не приводится минимальный рабочий пример, так что вот он для всех, кто заинтересован - надеюсь, это сэкономит вам время, которое потребовалось мне:

#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>

int main(void) {
   struct utsname buffer;
   if (uname(&buffer) != 0) {
      perror("uname");
      exit(0);
   }
   printf("OS: %s\n", buffer.sysname);

   return 0;
}

(Возможно) Выход:

ОС: линукс

PS: К сожалению, здесь используется заголовок POSIX: Сбой компиляции из-за отсутствует файл sys/utsname.h, который, скорее всего, не будет работать в Windows.

person gsamaras    schedule 20.11.2018
comment
ошибка C1083: не удается открыть включаемый файл: «sys/utsname.h»: нет такого файла или каталога. В Linux это работает, но не в Windows. - person txs; 06.12.2018

if (strchr(getenv("PATH"),'\\'))
    puts("You may be on windows...");

Я даже согласен с тем, что «Время выполнения - не время определять это ...»

person Roberto Cabellon    schedule 19.04.2017