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

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.
Описание книги "Программирование для Linux. Профессиональный подход"
Описание и краткое содержание "Программирование для Linux. Профессиональный подход" читать бесплатно онлайн.
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/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>).
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!
Похожие книги на "Программирование для Linux. Профессиональный подход"
Книги похожие на "Программирование для Linux. Профессиональный подход" читать онлайн или скачать бесплатно полные версии.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Отзывы о "Марк Митчелл - Программирование для Linux. Профессиональный подход"
Отзывы читателей о книге "Программирование для Linux. Профессиональный подход", комментарии и мнения людей о произведении.