|
Программирование >> Структура ядра и системные вызовы
функция foo может вызываться либо путем прямого вызова foo, либ<. посредством/млс/>/г. Следующие два оператора функционально эквивалентны: foo (12.78, Hello world ); funcptr (12.78, Hello world ); В K&R С для вызова foo необходимо разыменовать funcptr. В синтаксисе K&R С оператором, эквивалентным приведенному выше, будет (*funcptr) (12.78, Hello world ); В С++ поддерживаются оба эти варианта использования указателей на функции. В ANSI С определен также набор символов срр (препроцессора С), которые допускается применять в пользовательских программах. Фактические значения присваиваются этим символам во время компиляции (см. приведенную ниже таблицу). Символ срр Присваимое значение STDC L1NE FILE DATE TIME 1 - если компилятор соответствует ANSI С; в противном случае - О Номер физической строки исходного файла, в которой находится данный символ Имя модуля, который содержит данный символ Дата компиляции модуля, содержащего этот символ Время компиляции модуля, содержащего данный символ Использование этих символов иллюстрируется программой test ansi c.c, приведенной ниже: ♦ include <stdio.h>* int main О -О #if STDC == О && !defined( cplusplus) printf( cc is not ANSI С compliantXn ); lelse printf( %s compiled at %s:%s. Tliis statement is at line %d\n , FILE , DATE , TIME , LINE ) ; fendif return 0; Отметим, что С++ поддерживает символы LINE , FILE , DATE и TIME , HO не поддерживает STDC . Наконец, в ANSI С определяется набор стандартных библиотечных функций и соответствующих файлов заголовков. Файлы заголовков являются подмножеством библиотек С, имеющихся в большинстве систем, где реализован K&R С. Стандартные библиотеки ANSI С описаны в главе 4. 1.2. Стандарт ANSI/ISO С++ В начале 80-х годов сотрудник фирмы AT&T Bell Laboratories Бьярне Строуструп (Bjarne Stroustrup) разработал язык программирования С++. Язык С++ был построен на базе С и включал объектно-ориентированные конструкции, такие как классы, производные классы и виртуальные функции, заимствованные из языка simula67 [1]. Целью разработки С++ было ускорить написание хороших программ и сделать этот процесс более приятным для каждого отдельно взятого программиста [2]. Название С++, которое придумал Рик Маскитти (Rick Mascitti) в 1983 году, отражает факт происхождения этого языка от С. С момента своего появления С++ завоевал широкое признание среди профессиональных разработчиков программного обеспечения. В 1989 году Бьярне Строуструп опубликовал руководство The Annotated С++ Reference Manual [3], послужившее основой для проекта стандарта ANSI С++, который разработан комитетом ANSI X3J16. В начале 90-х годов к работе этого комитета подключился комитет WG21 Международной организации стандартизации (ISO), и была начата работа по созданию единого стандарта ANSI/ISO С++. Проект такого стандарта опубликован в 1994 году [4], однако стандарт все еще находится в стадии разработки, т.е. официального статуса он не получил. Большинство новейших коммерческих компиляторов С++, построенных на базе языка AT&T С++ версии 3.0 и выше, соответствуют проекту стандарта ANSI/ISO. В частности, эти компиляторы поддерживают классы С++, производные классы, виртуальные функции, перегрузку операций. Кроме того, они должны поддерживать шаблоны классов, шаблоны функций, обработку исключительных ситуаций и классы потоков ввода-вывода. Особенности языка С++ описываются в этой книге в соответствии с проектом стандарта ANSI/ISO. 1.3. Различия между ANSI С и С++ Язык С++ требует, чтобы все функции объявлялись или определялись до того, как программа к ним обратится. В ANSI С для тех функций, к которым программа обращается до их объявления и определения, используется стандартное объявление K&R С. Чтобы показать еще одно различие между ANSI С и С++, рассмотрим объявление функции int foo О; ANSI С трактует его как объявление функции С в старом стиле, интерпретируя ее следующим образом: int foo (..;.); Это означает, что foo можно вызывать с любым числом аргументов. В С++ это объявление трактуется по-другому: int foo (void); Другими словами, foo при вызове не может принимать никаких аргументов. Наконец, в С++ внешние функции компонуются с сохранением типов. Благодаря этому внешняя функция, неверно объявленная и вызванная в программе, заставит редактор связей {/bin/Id) сообщить о неопределенном имени функции. В ANSI С метод компоновки с сохранением типов не применяется, поэтому пользовательские ошибки такого рода не вылавливаются. Между ANSI С и С++ есть много других различий, но с перечисленными выше пользователи сталкиваются чаще всего. (Наиболее подробно язык ANSI С документирован в [5].) В следующем разделе описываются стандарты POSIX, которые достаточно полно соответствуют потребностям разработчиков UNIX-систем. 1.4. Стандарты POSIX Поскольку сегодня существует множество версий ОС UNIX и в каждой из них имеется свой набор функций интерфейсов прикладного программирования (API), то системным разработчикам трудно создавать приложения, которые можно было бы легко переносить в другие версии UNIX. Чтобы решить эту проблему, IEEE в 80-х годах сформировал специальную рабочую группу под названием POSIX, перед которой была поставлена задача создания комплекта стандартов, предназначенных для согласования между собой различных реализаций операционных систем. В POSIX имеется несколько подгрупп, в частности, POSIX.l, POSIX.lb и POSIX.lc, которые занимаются разработкой этого комплекта стандартов для системных программистов. В частности, комитет POSIX. 1 предлагает стандарт на базовый интерфейс прикладного программирования операционных систем, в котором определяются API для манипулирования файлами и процессами. Официально он известен как стандарт IEEE 1003.1-1990 [6] и принят также ISO как международный стандарт ISO/IEC 9945:1:1990. Комитет POSIX. lb предлагает набор стандартных API для интерфейса операционных систем реального времени, включающий API межпроцессного взаимодействия (официально известен как стандарт IEEE 1003.4-1993 [7]). Наконец, стандарт POSIX l.c [8] определяет интерфейс многопоточного программирования. Этот самый новый стандарт POSIX рассматривается в последней главе нашей книги. Хотя в основе своей работа комитетов POSIX строится на использовании ОС UNIX, предлагаемые ими стандарты предназначены для некой обобщенной операционной системы, которая вовсе не обязательно должна быть системой UNIX. Например, операционные системы VMS (разработчик - Digital Equipment Софога11оп), OS/2 (International Business Machines) и Windows NT (Microsoft Софога11оп) совместимы с POSIX, но UNIX-систе-мами не являются. Большинство существующих в настоящее время систем UNIX, такие как UNIX System V release 4, BSD UNIX 4.4 и операционные системы фирм-производителей UNIX (например, Solaris 2.x от Sun Microsystems, HP-UX 9.05 и 10.x фирмы Hewlett Packard, AIX 4.1 .х фирмы IBM и др.), совместимы с POSIX. 1, но все равно имеют собственные API. В этой книге рассматриваются интерфейсы прикладного программирования POSIX.l, POSIX.lb и POSIX.lc, а также API, характерные для систем UNIX. Заметим при этом, что если слово POSIX в тексте упоминается без расширения , оно относится к обоим стандартам - POSIX.l и POSIX.lb. Чтобы обеспечить соответствие своей программы стандарту POSIX.l, пользователь должен либо определить в начале каждого исходного модуля программы (до включения заголовков) макрос POSIX SOURCE: #define POSIX SOURCE либо указать при компиляции для компилятора С++ (СС) опцию -D POSIX SOURCE: % СС -D POSIX S0URCE *.С С помощью этой константы препроцессор срр отфильтровывает из применяемых пользовательской программой заголовков все коды, не соответствующие стандартам POSIX. 1 и ANSI С (например, функции, типы данных и макроопределения). Таким образом, пользовательская программа, которая компилируется с этим ключом и успешно выполняется, соответствует стандарту POSIX. 1. В POSIX.lb для проверки пользовательских программ на соответствие данному стандарту определяется другой макрос. Этот макрос называется POSIX C SOURCE, и его значением является код, обозначающий ту версию POSIX, которой соответствует данная пользовательская программа. Возможные значения макроса POSIX C SOURCE указаны ниже.
Каждое значение POSIX C SOURCE содержит значение года и месяца, в котором данный стандарт POSIX был утвержден IEEE. Суффикс L в значении показывает, что тип этого значения - длинное целое. Макрос POSIX C SOURCE можно использовать вместо POSIX SOURCE. Однако в некоторых системах, поддерживающих только POSIX.l, макрос POSIX C SOURCE не определен. Поэтому читателям следует просмотреть файл заголовков <unistd.h> у себя в системе, с тем чтобы установить, какой макрос используются в этом файле (возможно, оба). Есть также макрос POSIX VERSION, определяемый, как правило, в заголовке <unistd.h>. Этот макрос содержит версию POSIX, которой соответствует данная система. В приведенном ниже примере программы проверяется и выводится значение, присвоенное макросу POSIX VERSION; системы, где эта программа выполняется: /* show posix ver.с*/ ♦define POSIX SOURCE ♦define POSIX C SO0RCE 199309L finclude <iostream.h> ♦include <unistd.h> int mainO : ♦ifdef POSIX VERSldN cout System conforms to POSIX: POSIX VERSION endl; ♦else cout POSIX VERSION is undefinedXn ; ♦endif return 0; Вообще говоря, пользовательская программа, которая должна строго соответствовать стандартам POSIX. 1 й POSIX.lb, может включать в себя следующие строки: ♦define POSIX SOURCE ♦define POSIX C SO0RCE 199309L ♦include <unistd.h> /* здесь включить другие заголовки*/ int main О 1.4.1. Среда POSIX Хотя стандарт POSIX разработан на основе UNIX, система, соответствующая этому стандарту, не обязательно является UNIX-системой. В стандартах POSIX несколько соглашений, принятых в UNIX, имеют другой смысл. В частности, большинство стандартных файлов заголовков С и С++ в любой UNIX-системе хранятся в каталоге /usr/include, и каждый из них указывается в программе следующим образом: ♦include <имя файла заголовков> Такой метод обращения к файлам заголовков принят и в POSIX. Однако в POSIX-совместимой системе не обязательно должен существовать физический файл с именем, заданным оператором ШпсЫе. Данные, которые должны содержаться в этом именованном объекте, могут быть встроены в компилятор или храниться в данной системе каким-нибудь другим способом. В среде POSIX файлы, указываемые с помощью директивы #include, называются не файлами заголовков, а просто заголовками. В остальной части КНИГИ будет использоваться именно такое правило именования. Кроме того, в POSIX-совместимой системе существование каталога /usr/include не является обязательным. Если пользователи работают в POSIX-совместимой системе, которая не относится к системам UNIX, то стандартное местонахождение заголовков можно определить по руководству программиста С и С++. Еще одно различие между POSIX и UNIX состоит в концепции привилегированного пользователя. В UNIX привилегированный пользователь имеет право доступа ко всем системным ресурсам и функциям. Его пользовательский идентификатор всегда равен 0. Стандарты POSIX не требуют, чтобы POSIX-совместимые системы соблюдали это правило, и пользовательский идентификатор О не означает никаких особых привилегий. Более того, хотя для некоторых API POSIX. 1 и POSIX. lb необходимо выполнение функций с особыми привилегиями , решение о том, как особые привилегии будут присваиваться процессу, принимает конкретная система. 1.4.2. Макрокоманды тестирования характеристик по стандарту POSIX Некоторые возможности ОС UNIX реализуются в POSIX-совместимых системах по усмотрению разработчика. Так, в POSIX. 1 определен набор макрокоманд тестирования характеристик, который (если он определен) позволяет установить, реализованы ли в конкретной системе соответствующие возможности. Эти макрокоманды, если они определены, находятся в заголовке <unistd.h>. Ниже перечислены их имена и выполняемые действия. Макрокоманда тестирования Действие характеристик POSlX JOB CONTROL POSIX SAVED lDS POSIX CHOWN RESTRICTED Система поддерживает BSD-подобное управление заданиями Каждый процесс, работающий в системе, хранит установленные идентификаторы пользователя и группы и имеет возможность изменять их значения посредством API seteuid и setegid Если определено значение -1, пользователи имеют право изменять принадлежность файлов, которыми владеют. В противном случае только пользователи с особыми привилегиями могут изменять принадлежность всех файлов в системе. Если этот макрос в заголовке <unistd.h> не определен, пользователи должны с помощью функции pathconf или функции fpathconf (см. следующий раздел) проверить наличие разрешения на изменение принадлежности для каждого файла
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |