Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метод_ПСРВ.doc
Скачиваний:
26
Добавлен:
12.02.2016
Размер:
1.6 Mб
Скачать

1.4. Файл process.C

/* Данная программа производит обработку сформированной базы данных, выдирая из неё только записи, удовлетворяющие какому-либо критерию. В конкретном примере критерием является равенство оценки студента с заданной*/

# include <fcntl.h>

# include <sys/types.h>

# include <fcntl.h>

# include <stdio.h>

# include <malloc.h>

# include <process.h>

int stud_num; // количество студентов

int mark; // оценка, поиск которой

// производится

int i; // временная переменная

int Handle; // дескриптор файла

long FSize; // размер файла (байт)

char FName[15]; // имя файла

struct stud {char stud_surname[20]; // фамилия студента

int stud_group; // группа

int stud_mark;}; // оценка

struct stud *Buffer; // буфер для хранения записей

int main ()

{printf ("\n PID текущего процесса равен: %i", getpid());

printf ("\n Введите имя файла, в котором хранится база данных: ");

scanf ("%s", &FName);

// Открытие файла базы данных

if ((Handle = open (FName, O_RDONLY))==-1)

{printf ("Файл не может быть открыт. Программа прервана.");

exit (-1);}

// Вычисление размера файла

FSize=lseek(Handle, 0, SEEK_END);

lseek(Handle, 0, SEEK_SET);

stud_num=FSize/sizeof(struct stud);

printf ("\n База данных хранит информацию по %i студентам \n", stud_num);

printf ("\n Резервирование памяти в размере %i байт..\n.", stud_num*sizeof(struct stud));

if ((Buffer=(struct stud*) malloc (stud_num*sizeof(struct stud)))==NULL)

{printf ("\nНедостаточно памяти. Программа остановлена.");

exit (-1);}

// Чтение всего содержимого файла базы данных в память

if (FSize!=read (Handle, Buffer, FSize))

{printf ("\n Ошибка чтения файла. Программа остановлена.");

exit (-1);

close (Handle);}

close (Handle);

printf ("\n выводить студентов, чья оценка равна: ");

scanf ("%i", &mark);

for (i=0;i<stud_num;i++)

if (Buffer[i].stud_mark==mark)

{printf ("\nИмя студента: %s", Buffer[i].stud_surname);

printf ("\nГруппа студента: %i", Buffer[i].stud_group);

printf ("\nОценка студента: %i", Buffer[i].stud_mark);}

printf ("\n\n Обработка базы данных завершена!\n");

}

1.5. Используемые функции

Функция system() – выполнить системную команду

Синтаксис:

#include <stdlib.h>

int system( const char *command );

Библиотека:

libc.so

Описание:

Если значение переменной является NULL, тогда функция system() определяет отсутствие командного интерпретатора. В POSIX 1003.2 системах (например в QNX 4 и Neutrino), подразумевается, что командный интерпретатор загружен постоянно, и вызов system(NULL) всегда возвращает ненулевое значение.

В противном случае, функция system() вызывает копию командного интерпретатора и передаёт строку command на выполнение. Эта функция использует spawnlp() для загрузки копии командного интерпретатора.

В качестве командного интерпретатора всегда используется /bin/sh, независимо от значения переменной окружения SHELL, поскольку приложения обычно располагают возможностями стандартного интерпретатора и могут воспринять запуск иного интерпретатора как ошибку.

Это значит, что любая команда, которая может быть введена в системе Neutrino, может быть выполнена, включая программы, команды Neutrino и сценарии оболочки. Функции exec*() и spawn*() могут выполнять только программы.

Возвращает:

Если значение command равно NULL, тогда функция system() возвращает ноль, если интерпретатор не загружен, и значение, отличное от нуля, если интерпретатор загружен. В данной реализации всегда возвращается ненулевое значение.

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

Например, предположим, что status содержит значение, возвращённое функцией system(). Если WEXITSTATUS( status ) возвращает 255, это может говорить либо о том, что команда вернула код завершения, равный 255, либо о том, что выхода из командного интерпретатора не было (то есть, произошло прекращение работы по сигналу или не было даже запуска) и возвращён код 255. Например, в Neutrino и большинстве Unix чичтем, значение 255 появляется при значении переменной status , равному -1, которое говорит, что командный процессор не может быть запущен. WEXITSTATUS() определено в <sys/wait.h>.

При возникновении ошибки, errno содержит значение, которое указывает на тип ошибки.

Функция errno – глобальная переменная ошибки

Синтаксис:

#include <errno.h>

extern int errno;

Библиотека:

libc.so

Описание:

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

Эта функция может рассматриваться как макрос, но всегда проверяется на предмет допустимости значения. Значения для errno определены в файле <errno.h> и включают следующие значения:

Значение

Что под ним подразумевается

Системное сообщение

Перевод

E2BIG

Список аргументов слишком велик

EACCES

В доступе отказано

EADDRINUSE

Адрес уже используется

EADDRNOTAVAIL

Невозможно сопоставить запрашиваемый адрес

EADV

Информативная ошибка

EAFNOSUPPORT

Семейство адресов не поддерживается семейством протоколов

EAGAIN

Ресурс временно недоступен, попробуйте ещё раз

EALREADY

Операция на стадии выполнения

EBADE

Неверный обмен

EBADF

Неверный файловый дескриптор

EBADFD

Файловый дескриптор неверен для данной операции

EBADFSYS

Обнаружено повреждение файловой системы

EBADMSG

Неверное сообщение (1003.1b-1993)

EBADR

Неверный дескриптор запроса

EBADRPC

Неверная структура RPC

EBADRQC

Неверный код запроса

EBADSLT

Неверный слот

EBFONT

Неверный формат файла со шрифтом

EBUSY

Устройство или ресурс занято

ECANCELED

Операция прервана (1003.1b-1993)

ECHILD

Нет дочернего процесса

ECHRNG

Номер канала выходит за допустимые пределы

ECOMM

Обнаружена ошибка связи при посылке

ECONNABORTED

Программная причина обрыва связи

ECONNREFUSED

Отказ в соединении

ECONNRESET

Сброс соединения

ECTRLTERM

Перепланирование управляющего терминала

EDEADLK

Снята блокировка ресурса

EDEADLOCK

Блокировка файла

EDESTADDRREQ

Требуется адрес назначения

EDOM

Математический аргумент выходит за область владения функции

EDQUOT

Превышена дисковая часть

EEXIST

Файл существует

EFAULT

Неверный адрес

EFBIG

Файл слишком велик

EHOSTDOWN

Главная ЭВМ недоступна

EHOSTUNREACH

Невозможно произвести подключение к удалённому узлу

EIDRM

Идентификатор удалён

EILSEQ

Неверная последовательность байт

EINPROGRESS

Операция в данный момент выполняется

EINTR

Системный вызов прерван

EINVAL

Неверный аргумент

EIO

Ошибка ввода-вывода

EISCONN

Панель уже занят

EISDIR

Существующий каталог

EL2HLT

Уровень 2 остановлен

EL2NSYNC

Уровень 2 не синхронизирован

EL3HLT

Уровень 3 остановлен

EL3RST

Уровень 3 сброшен

ELIBACC

Невозможно получить доступ к разделяемой библиотеке

ELIBBAD

Доступ к повреждённой разделяемой библиотеке

ELIBEXEC

Попытка выполнения разделяемой библиотеки

ELIBMAX

Попітка связи в большом количестве библиотек

ELIBSCN

Повреждена секция .lib в a.out

ELNRNG

Связанный номер выходит за границы

ELOOP

Слишком много символических связей или префиксов

EMFILE

Слишком много открытых файлов

EMLINK

Слишком много связей

EMORE

Необходимо послать сообщение снова

EMSGSIZE

Несоответствующая длина буфера

ENAMETOOLONG

Слишком длинное имя файла

ENETDOWN

«Падение» сети

ENETRESET

Сеть вызвала сброс соединения

ENETUNREACH

Сеть недоступна

ENFILE

У системы слишком много открытых файлов

ENOANO

Нет анода

ENOBUFS

Место в буфере отсутствует

ENOCSI

Нет доступной CSI структуры

ENODATA

Нет данных (для неинерционных устройств ввода-вывода)

ENODEV

Устройство не обнаружено

ENOENT

Файл или каталог не найден

ENOEXEC

Ошибка формата EXEC

ENOLCK

Доступные блокировки отсутствуют

ENOLIC

Лицензия недоступна

ENOMEM

Недостаточно памяти

ENOMSG

Нет сообщений желаемого типа

ENONDP

Для выполнения необходим NDP (8087...)

ENONET

Машина не находится в сети

ENOPKG

Пакет не установлен

ENOPROTOOPT

Протокол недоступен

ENOREMOTE

Необходимо выполнение на локальной машине

ENOSPC

Нем свободного места на устройстве

ENOSR

Превышение строковых ресурсов

ENOSTR

Устройство не является строкой

ENOSYS

Функция не поддерживается

ENOTBLK

Необходимо блокируемое устройство

ENOTCONN

Разъём не подсоединён

ENOTDIR

Не каталог

ENOTEMPTY

Каталог не пуст

ENOTSOCK

Применена слотовая операция к устройству, не являющимся таковым

ENOTSUP

Не поддерживается (1003.1b-1993)

ENOTTY

Несоответствующая управляющая операция ввода-вывода

ENOTUNIQ

Предоставленное имя не уникально

ENXIO

Устройство или адрес не найдено

EOK

Нет ошибки

EOPNOTSUPP

Операция не поддерживается

EOVERFLOW

Значение слишком велико и не может быть сохранено

EPERM

Операция не предусмотрена

EPFNOSUPPORT

Семейство протоколов не поддерживается

EPIPE

Повреждённая очередь

EPROCUNAVAIL

Неверная процедура

EPROGMISMATCH

Неверная версия программы

EPROGUNAVAIL

Программа RPC не доступна

EPROTO

Ошибка протокола

EPROTONOSUPPORT

Протокол не поддерживается

EPROTOTYPE

Тип протокола неверен для слотовой операции

ERANGE

Результат слишком велик

EREMCHG

Удалённый адрес изменён

EREMOTE

Объект удалён

ERESTART

Вызов перезапуска системы

EROFS

Файловая система предназначена только для чтения

ERPCMISMATCH

Неверная версия RPC

ESHUTDOWN

Посылка невозможна после выключения слота

ESOCKTNOSUPPORT

Тип слота не поддерживается

ESPIPE

Неверная позиция

ESRCH

Процесс не найден

ESRMNT

Ошибка монтирования

ESRVRFAULT

Принятая часть сообщения вызвала ошибку памяти при доступе к буферу

ESTALE

Восстановимая ошибка ввода-вывода

ETIME

Истёк таймер

ETIMEDOUT

Превышено допустимое время попытки соединения

ETOOMANYREFS

Too слишком много ссылок

ETXTBSY

Текстовый файл занят

EUNATCH

Драйвер протокола не подключен

EUSERS

Слишком много пользователей (для UFS)

EWOULDBLOCK

Операция будет заблокирована

EXDEV

Перекрёстная ссылка

Пример:

/* следующая программа производит умышленно неверный вызов функции , после чего производит вывод значение, хранимое в errno.*/

#include <stdio.h>

#include <unistd.h>

#include <errno.h>

#include <string.h>

int main( void )

{

int errvalue;

errno = EOK;

write( -1, "hello, world\n",

strlen( "hello, world\n" ) );

errvalue = errno;

printf( "The error generated was %d\n", errvalue );

printf( "That means: %s\n", strerror( errvalue ) );

}

Функция exit()Выход из вызывающей программы

Синтаксис:

#include <stdlib.h>

void exit( int status );

Библиотека:

libc.so

Описание:

Функция exit() приводит к нормальному завершению вызывающей программы.

При этом:

  1. Происходит вызов всех функций, зарегистрированных при помощи функции atexit().

  2. Все открытые файловые потоки (которые были открыты при помощи fopen(), fdopen(), freopen(), или popen()) очищаются и закрываются.

  3. Все временные файлы, созданные функцией tmpfile(), удаляются.

  4. Возвращённое значение status становится доступным родительскому процессу; как правило, status принимает значение EXIT_SUCCESS, что говорит об успешном завершении, и значение EXIT_FAILURE или любое иное, что говорит об ошибке.

Возвращает:

Функция exit() ничего не возвращает.

Функция fork()порождает новый процесс

Синтаксис:

#include <sys/types.h>

#include <process.h>

pid_t fork( void );

Библиотека:

libc.so

Описание:

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

  • Дочерний процесс имеет уникальный идентификатор процесса.

  • Идентификатор дочернего процесса отличается от идентификатора родительского процесса (которым является вызывающий процесс)

  • Дочерний процесс имеет собственную копию дескрипторов родительского процесса. Каждый из файловых дескрипторов обращается к той строке, описывающей открытый файл, что и дескриптор родительского процесса

  • Дочерний процесс имеет собственную копию строк открытых каталогов родительского процесса.

  • Значения переменных tms_utime, tms_stime, tms_cutime, и tms_cstime для дочернего процесса устанавливаются в ноль.

  • Файловые блокировки, установленные родительским процессом, не наследуются дочерним процессом.

  • Для дочернего процесса таймеры очищаются

  • Установленные сигналы, ожидающие дочернего процесса, очищаются

Возвращает:

Дочерний процесс получает значение, равное нулю, в то время как родительский процесс получает идентификатор дочернего процесса. Оба процесса продолжают выполняться, начиная с функции fork(). При возникновении ошибки родительский процесс получает -1 и происходит установка кода ошибки в errno .

Пример:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <ctype.h>

#include <process.h>

#include <sys/wait.h>

if( ( pid = fork() ) == -1 ) {

perror( "fork" );

return EXIT_FAILURE;

}

if( pid == 0 ) {

/* это дочерний процесс */

. . .

} else {

/* это родительский процесс */

. . .

}

}

Функция spawn()Создаёт и запускает на выполнение новый дочерний процесс

Синтаксис:

#include <spawn.h>

pid_t spawn( const char *path,

int fd_count,

const int fd_map[ ],

const struct inheritance *inherit,

char *const argv[ ],

char *const envp[ ] );

Библиотека:

libc.so

Описание:

Функция spawn() создаёт и выполняет новый дочерний процесс, имя которого задаётся параметром path.

Функция spawn() является функцией ядра системы (в соответствии с первой редакцией стандарта POSIX 1003.1d). Библиотека функций ядра включает несколько spawn*() функций. Их имена состоят из spawn и следующими за этим именем несколькими буквами.

Суффикс:

Говорит о том, что функция получает следующие аргументы:

e

Список переменных окружения.

l

Список параметров программы, заканчивающийся NULL.

p

Относительный путь. путь не должен содержать "слэш", поиск программы осуществляется в соответствии со значением переменной PATH

v

Вектор аргументов программы.

Как показано ниже, эти производят вызов функции spawn(), которая посылает сообщение менеджеру процессов ядра.

Аргумент path является полным именем пути исполняемого файла.

Если fd_count не равен 0, fd_map должент содержать, по крайней мере, fd_count файловых дескрипторов, но не более значения OPEN_MAX. Если fd_count равно 0, значение параметра fd_map игнорируется.

Если fd_count равно 0, все файловые дескрипторы (за исключением тех, оторые созданы с флагом FD_CLOEXEC) наследуются дочерним процессом

Структура, определенная как inherit состоит, по крайней мере, из следующих составляющих:

short flags

Один или более следующих бит:

  • SPAWN_CHECK_SCRIPT - разрешить spawn() запускать интерпритатор, рассматривая path как скрипт (не поддерживается).

  • SPAWN_SEARCH_PATH - поиск исполнимого модуля производится в соответствии со значением переменной PATH.

  • SPAWN_SETGROUP - в качестве группы дочернего процесса устанавливается значение переменной pgroup. Если данный флаг не установлен, дочерний процесс является членом той же группы, что и текущий процесс.

  • SPAWN_SETSIGDEF - используется sigdefault для определения сигналов, поддерживаемых дочерним процессом по умолчанию. Если этот флаг не определен, дочерний процесс наследует родительские способы реакции на сигналы

  • SPAWN_SETSIGMASK - используйте sigmask для определения маски сигналов дочернего процесса

pid_t pgroup является группой дочернего процесса если SPAWN_SETGROUP определено во flags.

Если SPAWN_SETGROUP установлено в inherit.flags и inherit.pgroup установлено в SPAWN_NEWPGROUP, дочерний процесс стартует с идентификатором группы, совпадающим с идентификатором процесса.

sigset_t sigmask является маской сигналов дочернего процесса если SPAWN_ SETSIGMASK определено во flags.

sigset_t sigdefault является установленными по умолчанию сигналами если SPAWN_SETSIGDEF определено во flags.

Дочерний процесс наследует следующий атрибуты текущего процесса:

  • Идентификатор группы процесса (за исключением установленного SPAWN_SETGROUP в inherit.flags)

  • Идентификатор пользователя и реальный идентификатор группы.

  • Дополнительный идентификатор группы

  • Политика приоритетов и планирования

  • Текущий рабочий каталог и корневой каталог

  • Маска создаваемых файлов

  • Маска сигнала (за исключением установленного SPAWN_SETSIGMASK в inherit.flags)

  • Действия сигнала, определенные как SIG_DFL

  • Действия сигналов, определенных как SIG_IGN (за исключением определенных посредством inherit.sigdefault при установленном SPAWN_SETSIGDEF в inherit.flags)

Дочерний процесс имеет следующие отличия от текущего процесса:

  • Сигналы, улавливаемые родительским процессом, устанавливаются как действие по умолчанию (SIG_DFL)

  • Значения tms_utime, tms_stime, tms_cutime и tms_cstime дочернего процесса устанавливаются в ноль (не поддерживается в Neutrino 2.0).

  • Число секунд остаётся до тех пор, пока сигнал SIGALRM не будет сгенерирован для дочернего процесса для установки этого значения в ноль

  • Установки рассматриваемых сигналов для дочернего процесса очищаются

  • Файловые блокировки, установленные родительским процессом, не наследуются

  • Таймеры процессов, созданные родительским процессом не наследуются

  • Блокировки памяти и отображения в памяти, установленные родительским процессом, не наследуются

Аргумент argv является указателем на вектор аргументов. Значение argv[0] должно указывать на имя программы, которая загружается, но может быть равно NULL если аргументы не передаются. Последнее значение argv должно быть равно NULL.

Аргумент envp является указателем на массив символьных указателей, каждый из которых указывает на строку, определяющую значение переменной окружения. Массив заканчивается NULL. Каждый указатель указывает на строку, записанную в виде:

Переменная = значение

Если значение envp равно NULL, тогда дочерний процесс наследует переменные окружения родительского процесса.

Дочерний процесс может получить доступ к переменным окружения родительского процесса, используя глобальную переменную environ (определена в <stdlib.h>)

Если path является монтированной файловой системой с установленным флагом ST_NOSUID, эффективный идентификатор пользователя, эффективный идентификатор группы, хранимый дополнительный идентификатор пользователя и хранимый дополнительный идентификатор группы для дочернего процесса не изменяются. В противном случае, если установлен бит режима устанавливаемого пользовательского идентификатора, эффективному пользовательскому идентификатору дочернего процесса присваивается значение идентификатора владельца path. Аналогично, если установлен бит режима устанавливаемого идентификатора группы, эффективному идентификатору группы дочернего процесса присваивается значение идентификатора владельца path. Настоящий идентификатор пользователя, настоящий идентификатор группы и вспомогательные идентификаторы групп дочернего процесса остаются такими же как и у родительского процесса. Эффективный идентификатор пользователя и эффективный идентификатор группы дочернего процесса сохраняется как устанавливаемый пользовательский идентификатор и устанавливаемый идентификатор группы, используемый при помощи setuid().

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

Возвращаемые значения:

Идентификатор дочернего процесса или -1 в случае ошибки.