-->

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

На нашем литературном портале можно бесплатно читать книгу Операционная система UNIX, Робачевский Андрей Михайлович-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
Операционная система UNIX
Название: Операционная система UNIX
Дата добавления: 16 январь 2020
Количество просмотров: 431
Читать онлайн

Операционная система UNIX читать книгу онлайн

Операционная система UNIX - читать бесплатно онлайн , автор Робачевский Андрей Михайлович

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

В книге рассматриваются: архитектура ядра UNIX (подсистемы ввода/вывода, управления памятью и процессами, а также файловая подсистема), программный интерфейс UNIX (системные вызовы и основные библиотечные функции), пользовательская среда (командный интерпретатор shell, основные команды и утилиты) и сетевая поддержка в UNIX (протоколов семейства TCP/IP, архитектура сетевой подсистемы, программные интерфейсы сокетов и TLI).

Для широкого круга пользователей.

 

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

1 ... 31 32 33 34 35 36 37 38 39 ... 156 ВПЕРЕД
Перейти на страницу:

Для получения и установки значений конкретных переменных окружения используются две функции: getenv(3C) и putenv(3C):

#include <stdlib.h>

char *getenv(const char *name);

возвращает значение переменной окружения

name
, a

int putenv(const char *string);

помещает переменную и ее значение (

var_name=var_value
) в окружение программы.

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

#include <stddef.h>

#include <stdlib.h>

#include <stdio.h>

main(int argc, char *argv[]) {

 char *term;

 char buf[200], var[200];

 /* Проверим, определена ли переменная TERM */

 if ((term = getenv("TERM")) == NULL)

  /* Если переменная не определена, получим от пользователя ее значение и

     поместим переменную в окружение программы */

 {

  printf("переменная TERM не определена, введите значение: ");

  putenv(var);

 } else

  /* Если переменная TERM определена, предоставим пользователю возможность

     изменить ее значение, после чего поместим ее в окружение процесса */

 {

  printf("TERM=%s. Change? [N]", getenv("TERM"));

  gets(buf);

  if (buf[0] == 'Y' || buf[0] == 'y') {

   printf("TERM=");

   gets{buf);

   sprintf(var, "TERM=%s", buf);

   putenv(var);

   printf("new %sn", var);

  }

 }

}

Сначала программа проверяет, определена ли переменная

TERM
. Если переменная
TERM
не определена, пользователю предлагается ввести ее значение. Если же переменная
TERM
определена, пользователю предлагается изменить ее значение, после чего новое значение помещается в окружение программы.

Запуск этой программы приведет к следующим результатам:

$ <b>а.out</b>

TERM=ansi. Change? [N]<b>y</b>

TERM=<b>vt100</b>

new TERM=vt100

$

К сожалению, введенное значение переменной будет действительно только для данного процесса и порожденных им процессов: если после завершения программы a.out вывести значение

TERM
, то видно, что оно не изменилось:

$ <b>echo $TERM</b>

ansi

$

Наследование окружения программы мы обсудим в разделе "Создание и управление процессами" далее в этой главе.

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

Обычно при запуске программы на выполнение из командной строки shell автоматически устанавливает для нее три стандартных потока ввода/вывода: для ввода данных, для вывода информации и для вывода сообщений об ошибках. Начальную ассоциацию этих потоков (их файловых дескрипторов) с конкретными устройствами производит терминальный сервер (в большинстве систем это процесс getty(1M)), который открывает специальный файл устройства, связанный с терминалом пользователя, и получает соответствующие дескрипторы. Эти потоки наследует командный интерпретатор shell и передает их запускаемой программе. При этом shell может изменить стандартные направления (по умолчанию все три потока связаны с терминалом пользователя), если пользователь указал на это с помощью специальных директив перенаправления потока (>, <, >>, <<) см. главу 1, раздел "Пользовательская среда UNIX"). Раздел "Группы и сеансы" внесет окончательную ясность в этот вопрос при описании управляющего терминала.

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

Завершая разговор о запуске программ, заметим, что при компиляции программы редактор связей устанавливает точку входа в программу, указывающую на библиотечную функцию _start(). Эта функция инициализирует процесс, создавая кадр стека, устанавливая значения переменных и, в конечном итоге, вызывая функцию main().

Завершение C-программы

Существует несколько способов завершения программы. Основными являются возврат из функции main() [17] и вызов функций exit(2), оба приводят к завершению выполнения задачи. Заметим, что процесс может завершиться по не зависящим от него обстоятельствам, например, при получении сигнала, действие по умолчанию для большинства из которых приводит к завершению выполнения процесса [18] (см. раздел "Сигналы" далее в этой главе). В этом случае функция exit(2) будет вызвана ядром от имени процесса.

Системный вызов exit(2) выглядит следующим образом:

#include &lt;unistd.h&gt;

void exit(int status);

Аргумент

status
, передаваемый функции exit(2), возвращается родительскому процессу и представляет собой код возврата программы. По соглашению программа возвращает 0 в случае успеха и другую величину в случае неудачи. Значение кода неудачи может иметь дополнительную трактовку, определяемую самой программой. Например, программа grep(1), выполняющая поиск заданных подстрок в файлах, определяет следующие коды возврата:

1 ... 31 32 33 34 35 36 37 38 39 ... 156 ВПЕРЕД
Перейти на страницу:
Комментариев (0)
название