Марк Митчелл - Программирование для Linux. Профессиональный подход Страница 14

Тут можно читать бесплатно Марк Митчелл - Программирование для Linux. Профессиональный подход. Жанр: Компьютеры и Интернет / Программирование, год -. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте «WorldBooks (МирКниг)» или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Марк Митчелл - Программирование для Linux. Профессиональный подход

Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание

Прочтите описание перед тем, как прочитать онлайн книгу «Марк Митчелл - Программирование для Linux. Профессиональный подход» бесплатно полную версию:
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.

Марк Митчелл - Программирование для Linux. Профессиональный подход читать онлайн бесплатно

Марк Митчелл - Программирование для Linux. Профессиональный подход - читать книгу онлайн бесплатно, автор Марк Митчелл

Как же различить между собой оба процесса? Во-первых, дочерний процесс — это новый, только что появившийся в системе процесс, поэтому его идентификатор отличается от идентификатора родительского процесса. Таким образом, программа может вызвать функцию getpid() и узнать, где именно она находится. Но сама функция fork() реализует другой способ: она возвращает разные значения в родительском и дочернем процессах. Родительский процесс получает идентификатор своего потомка, а дочернему процессу возвращается 0. В системе нет процессов с нулевым идентификатором, так что программа легко разбирается в ситуации.

В листинге 3.3 приведен пример ветвления программы с помощью функции fork(). Учтите, что первая часть инструкции if выполняется только в родительском процессе, тогда как ветвь else — только в дочернем.

Листинг 3.3. (fork.c) Ветвление программы с помощью функции fork()

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main() {

 pid_t child_pid;

 printf("The main program process ID is %d\n",

  (int)getpid());

 child_pid = fork();

 if (child_pid != 0) {

  printf("This is the parent process, with ID %d\n",

   (int)getpid());

  printf("The child's process ID is %d\n", (int)child_pid);

 } else

  printf("This is the child process, with ID %d\n",

   (int)getpid());

 return 0;

}

Семейство функций exec()

Функции семейства exec() заменяют программу, выполняющуюся в текущем процессе, другой программой. Когда программа вызывает функцию exec(), ее выполнение немедленно прекращается и начинает работу новая программа.

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

■ Функции, в названии которых присутствует суффикс 'p' (execvp() и execlp()), принимают в качестве аргумента имя программы и ищут эту программу в каталогах, определяемых переменном среды PATH. Всем остальным функциям нужно передавать полное путевое имя программы.

■ Функции, в названии которых присутствует суффикс 'v' (execv(), execvp() и execve()), принимают список аргументов программы в виде массива строковых указателей, оканчивающегося NULL-указателем. Функции с суффиксом 'l' (execl(), execlp() и execle()) принимают список аргументов переменного размера.

■ Функции, в названии которых присутствует суффикс 'e' (execve() и execle()), в качестве дополнительного аргумента принимают массив переменных среды. Этот массив содержит строковые указатели и оканчивается пустым указателем. Каждая строка должна иметь вид "ПЕРЕМЕННАЯ=значение".

Поскольку функция exec() заменяет одну программу другой, она никогда не возвращает значение — только если вызов программы оказался невозможен в случае ошибки.

Список аргументов, передаваемых программе, аналогичен аргументам командной строки, указываемым при запуске программы в интерактивном режиме. Их тоже можно получить с помощью параметров argc и argv функции main(). Не забывайте, когда программу запускает интерпретатор команд, первый элемент массива argv будет содержать имя программы, а далее будут находиться переданные программе аргументы. Аналогичным образом следует поступить, формируя список аргументов для функции exec().

Совместное использование функций fork() и exec()

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

Программа, показанная в листинге 3.4, отображает содержимое корневого каталога с помощью команды ls, как и программа в листинге 3.2. Но на этот раз команда ls вызывается не из интерпретатора, а напрямую; ей передаются аргументы -l и /.

Листинг 3.4. (fork-exec.с) Совместное использование функций fork() и exec()

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

/* Запуск дочернего процесса в виде новой программы. Параметр

   PROGRAM — это имя вызываемой программы; ее поиск будет

   осуществляться в каталогах, определяемых переменной среды PATH.

   Параметр ARG_LIST -- это список строковых аргументов,

   передаваемых программе (должен оканчиваться указателем NULL).

   Функция возвращает идентификатор порожденного процесса. */

int spawn(char* program, char** arg_list) {

 pid_t child_pid;

 /* Создание копии текущего процесса. */

 child_pid = fork();

 if (child_pid != 0)

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

  return child_pid;

 else {

  /* Выполнение указанной программы. */

  execvp(program, arg_list);

  /* Функция execvp() возвращает значение только в случае

    ошибки. */

  fprintf(stderr, "an error occurred in execvp\n");

  abort();

 }

}

int main() {

 /* Список аргументов, передаваемых команде ls. */

 char* arg_list[] = {

  "ls", /* argv[0] -- имя программы. */

  "-l",

  NULL /* Список аргументов должен оканчиваться указателем

          NULL. */

 };

 /* Порождаем дочерний процесс, который выполняет команду ls.

    Игнорируем возвращаемый идентификатор дочернего процесса. */

 spawn("ls", arg_list);

 printf("done with main program\n");

 return 0;

}

3.2.3. Планирование процессов

Операционная система Linux планирует работу родительских и дочерних процессов независимо друг от друга. Нет гарантии, что один процесс будет запущен раньше другого. и неизвестно, как долго один процесс будет выполняться, прежде чем Linux прервет его работу и передаст управление другому процессу. В частности, к моменту завершения родительского процесса может оказаться, что команда ls еще не выполнена, выполнена частично или уже закончила свою работу.[11] Linux лишь гарантирует, что любой процесс когда-нибудь получит свой "кусочек пирога": ни один процесс не окажется полностью лишенным доступа к процессору.

Можно сообщить системе о том, что процесс не очень важен и должен выполняться с пониженным приоритетом. Это делается путем повышения фактора уступчивости процесса. По умолчанию у каждого процесса нулевой фактор уступчивости. Повышение этого значения свидетельствует о снижении приоритета процесса, и наоборот: процессы с низким (т.е. отрицательным) фактором уступчивости получают больше времени на выполнение.

Для запуска программы с ненулевым фактором уступчивости необходимо воспользоваться командой nice -n. Рассмотрим следующий пример:

% nice -n 10 sort input.txt > output.txt

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

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

Только программа с привилегиями пользователя root может запускать процессы с отрицательным фактором уступчивости или понижать это значение у выполняющегося процесса. Это означает, что вызывать команды nice и renice с отрицательными аргументами можно, лишь войдя в систему как пользователь root, и только процесс, выполняемый от имени суперпользователя, может передавать функции nice() отрицательное значение. Таким образом, обычные пользователи не могут помешать работать процессам других пользователей и монополизировать системные ресурсы.

3.3. Сигналы

Сигналы — это механизм связи между процессами в Linux. Данная тема очень обширна, поэтому здесь мы рассмотрим лишь наиболее важные сигналы и методики управления процессами.

Сигнал представляет собой специальное сообщение, посылаемое процессу. Сигналы являются асинхронными: когда процесс принимает сигнал, он немедленно обрабатывает его, прерывая выполнение текущей функции и даже текущей строки программы. Есть несколько десятков различных сигналов, каждый из которых имеет свое функциональное назначение. Все они распознаются по номерам, но в программах для ссылки на сигналы пользуются символическими константами. В Linux эти константы определены в файле /usr/include/bits/signum.h (его не нужно включать в программы, для этого есть файл <signal.h>).

Перейти на страницу:
Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.
Комментарии / Отзывы
    Ничего не найдено.