Стив Саммит. Язык си в вопросах и ответах.Интерфейс с операционной системой.

Стив  Саммит. Язык си в вопросах и ответах.Интерфейс с операционной системой.

Ответы на вопросы разбиты по темам:

1. Нулевые указатели

2. Указатели и массивы.

3. Выделение памяти

4. Выражения

5. ANSI C

6. Препроцессор С.

7. Списки аргументов переменной длины.

8. Булевы выражения и переменные.

9. Структуры, перечисления и объединения.

10. Декларации.

11. Cтандартный ввод/вывод.

12. Библиотечные функции.

13. Lint.

14. Стиль.

15. Операции с плавающей точкой.

16. Интерфейс с операционной системой.

17. Разное (Пребразование Fortran -> C , грамматики для YACC и т.п.)

Интерфейс с операционной системой.

16.1    Как прочитать с    клавиатуры один    символ,    не дожидаясь новой строки?

О:      Вопреки популярному убеждению и желанию многих, этот вопрос (как и родственные вопросы, связанные с дублированием символов) не относится к языку С. Передача символов с «клавиатуры» программе, написанной на С, осуществляется операционной системой, эта операция не стандартизирована языком С.  Некоторые версии библиотеки curses содержат функцию cbreak(), которая делает как раз то, что нужно. Если Вы пытаетесь прочитать пароль с клавиатуры без вывода его на экран, попробуйте getpass(). В операционной системе UNIX используйте ioctl для смены режима работы драйвера терминала(CBREAK или RAW для «классических» версий; ICANON, c_cc[VMIN] и с_сс[VTIME] для System V или Posix). В системе MS-DOS используйте getch(). В системе VMS попробуйте функции управления экраном (SMG$) или curses, или используйте низкоуровневые команды $QIO с кодами IO$_READVBLK (и, может быть, IO$M_NOECHO) для приема одного символа за раз. В других операционных системах выкручивайтесь сами.  Помните, что в некоторых операционных системах сделать нечто подобное невозможно, так как работа с символами осуществляется вспомогательными процессорами и не находится под контролем центрального процессора.
Вопросы, ответы на которые зависят от операционной системы, неуместны в comp.lang.c. Ответы на многие вопросы можно найти в FAQ таких групп как comp.unix.questions и comp.os.msdos.programmer. Имейте в виду, что ответы могут отличаться даже в случае разных вариантов одной и той же операционной системы. Если вопрос касается специфики операционной системы, помните, что ответ, пригодный в Вашей системе, может быть бесполезен всем остальным.
Смотри: PCS Разд. 10 c. 128-9, Разд. 10.1 c. 130-1.

16.2    Как определить — есть ли символы для чтения (и если есть, то сколько?) И наоборот, как    сделать, чтобы выполнение программы не блокировалось, когда нет символов для чтения?

О:    Ответ на эти вопросы также целиком зависит от операционной системы. В некоторых версиях curses есть    функция    nodelay(). В зависимости от операционной    системы    Вы сможете использовать    «неблокирующий ввод/ вывод» или системный вызов «select» или    ioctl FIONREAD,    или kbhit(), или rdchk(), или опцию O_NDELAY    функций    open() или fcntl().

16.3    Как очистить экран? Как    выводить на экран негативное изображение?

О:    Это зависит от типа терминала (или дисплея). Можете использовать такую библиотеку как termcap или curses, или какие-то другие функциии, пригодные для данной операционной системы.

16.4    Как узнать состояние мыши?

О:    Посмотрите в системной документации, или поместите вопрос (предварительно    посмотрев их FAQ) в одну из групп, обсуждающих определенную операционную систему. Работа с мышью совершенно непохожа в X window, MS-DOS, Macintosh, и, возможно, в любой другой операционной системе.

16.5    Как программа может определить полный путь к месту, из которого она была вызвана?

О:    argv[0]    может содержать    весь путь, часть его или ничего    не содержать. Если имя файла в argv[0] имеется, но информация не полна, возможно повторение логики поиска исполнимого файла, используемой интерпретатором командного языка. Гарантированных или мобильных решений, однако, не существует.

16.6    Как процесс может изменить переменную окружения родительского процесса?

О:      В общем, никак. Различные операционные системы обеспечивают сходную с UNIX возможность задания пары имя/значение. Может ли программа с пользой для себя поменять окружение, и если да, то как — все это зависит от операционной системы.
В системе UNIX процесс может модифицировать свое окружение (в некоторых системах есть для этого функции setenv() и/или putenv()) и модифицированное окружение обычно передается дочерним процессам но _не_ распространяется на родительский процесс.

16.7    Как проверить, существует ли файл? Мне необходимо спрашивать пользователя перед тем как переписывать существующие файлы.

О:      В UNIX-подобных операционных системах можно попробовать функцию access(), хотя имеются кое-какие проблемы. (Применение access() может сказаться на последующих действиях, кроме того,    возможны особенности исполнения в setuid-программах).  Другое (возможно, лучшее) решение — вызвать stat(), указав имя файла.  Единственный универсальный, гарантирующий мобильность способ состоит в попытке открыть файл.

16.8    Как определить размер файла до его чтения?

О:      Если «размер файла» — это количество литер, которое можно прочитать, то, вообще говоря, это количество заранее неизвестно. В операционной системе Unix вызов функции stat дает точный ответ, и многие операционные системы поддерживают похожую функцию, которая дает приблизительный ответ.  Можно c помощью fseek переместиться в конец файла, а затем вызвать ftell, но такой прием немобилен (дает точный ответ только в системе Unix, в других же случаях ответ почти точен лишь для определенных стандартом ANSI «двоичных» файлов). В некоторых системах имеются подпрограммы filesize или filelength.
И вообще, так ли нужно заранее знать размер файла? Ведь    самый точный способ определения его размера в С программе заключается в открытии и чтении. Может быть, можно изменить программу так, что размер файла будет получен в процессе чтения?

16.9    Как укоротить файл без уничтожения или переписывания?

О:      В системах BSD есть функция ftruncate(), несколько других систем поддерживают chsize(), в некоторых имеется (возможно, недокументированный) параметр fcntl F_FREESP. В системе MS-DOS можно иногда использовать write(fd, «», 0).  Однако, полностью мобильного решения не существует.

16.10   Как реализовать задержку или определить время реакции пользователя, чтобы погрешность была меньше секунды?

О:    У этой задачи нет, к несчастью,    мобильных решений. Unix    V7 и ее производные имели весьма полезную функцию ftime() c точностью до миллисекунды, но она исчезла в System V и Posix. Поищите такие функции: nap(), setitimer(), msleep(), usleep(), clock(), и gettimeofday().  Вызовы select() и poll() (если эти функции доступны) могут быть добавлены к сервисным функциям для создания простых задержек.  В системе MS-DOS возможно перепрограммирование системного таймера и прерываний таймера.

16.11    Как прочитать объектный    файл и передать    управление на одну из его функций?

О:    Необходим динамический компоновщик и/или загрузчик. Возможно выделить память с помощью malloc    и читать объектные файлы, но нужны обширные познания в форматах объектных файлов, модификации адресов и пр. В системе BSD Unix можно использовать system() и ld -A для динамической компоновки. Mногие (большинство? ) версии SunOS и System V имеют библиотеку -ldl, позволяющую динамически загружать объектные модули.  Есть еще GNU пакет, который называется «dld». См. также вопрос 7.6.

16.12    Как выполнить из программы команду операционной    системы?

О:    Используйте system().
Смотри: K&R II Разд. B6 c. 253; ANSI Разд. 4.10.4.5; H&S Разд. 21.2; PCS Разд. 11 c. 179;

16.13    Как перехватить    то, что    выдает команда операционной системы?

О:    Unix и некоторые другие    операционные системы имеют функцию popen(), которая    переназначает поток stdio каналу, связанному с процессом, запустившим команду, что позволяет прочитать выходные данные (или передать входные). А можно просто (см. вопрос 16.12) перенаправить выход команды в файл, затем открыть его и прочесть.
Смотри: PCS Разд. 11 c. 169 .

16.14    Как получить содержимое    директория в С программе?

О:    Выясните, нельзя ли использовать функции opendir() и readdir(), доступные в большинстве    систем Unix. Реалиции этих функций известны для MS-DOS, VMS    и других систем. (MS-DOS имеет также функции findfirst и findnext, которые делают в точности то же самое).

16.15    Как работать с последовательными (COM) портами?

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

Добавить комментарий

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