Читаем Linux API. Исчерпывающее руководство полностью

Когда выполняется вызов fork(), потомок получает копии всех файловых дескрипторов родителя. Эти копии создаются в той же манере, как работает функция dup(); это означает, что соответствующие дескрипторы в родительском и дочернем процессах указывают на один и тот же открытый файл. Как мы уже видели в разделе 5.4, дескриптор открытого файла содержит его текущее смещение (образовавшееся во время редактирования с помощью функций read(), write() и lseek()) и флаги состояния (установленные вызовом open() и измененные операцией fcntl() F_SETFL). Как следствие, эти атрибуты открытого файла являются общими для родителя и потомка. Например, если дочерний процесс обновляет смещение, это изменение доступно его родителю посредством соответствующего дескриптора.

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

$ ./fork_file_sharing

File offset before fork(): 0

O_APPEND flag before fork() is: off

Child has exited

File offset in parent: 1000

O_APPEND flag in parent is: on

Объяснение того, зачем мы приводим значение, возвращаемое функцией lseek(), к типу long long, ищите в разделе 5.10.


Листинг 24.2. Совместный доступ к смещению файла и флагам его состояния из родителя и потомка

procexec/fork_file_sharing.c

#include

#include

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

int fd, flags;

char template[] = "/tmp/testXXXXXX";


setbuf(stdout, NULL); /* Отключаем буферизацию стандартного вывода */


fd = mkstemp(template);

if (fd == –1)

errExit("mkstemp");


printf("File offset before fork(): %lld\n", (long long) lseek(fd, 0, SEEK_CUR));

flags = fcntl(fd, F_GETFL);

if (flags == –1)

errExit("fcntl — F_GETFL");

printf("O_APPEND flag before fork() is: %s\n", (flags & O_APPEND)? "on": "off");


switch (fork()) {

case –1:

errExit("fork");


case 0: /* Потомок изменяет сдвиг файла и флаги его состояния */

if (lseek(fd, 1000, SEEK_SET) == –1)

errExit("lseek");


flags = fcntl(fd, F_GETFL); /* Извлекаем текущие флаги */

if (flags == –1)

errExit("fcntl — F_GETFL");

flags |= O_APPEND; /* Устанавливаем флаг O_APPEND */

if (fcntl(fd, F_SETFL, flags) == –1)

errExit("fcntl — F_SETFL");

_exit(EXIT_SUCCESS);


default: /* Родитель может видеть изменения, внесенные потомком */

if (wait(NULL) == –1)

errExit("wait"); /* Ждем завершения работы потомка */

printf("Child has exited\n");


printf("File offset in parent: %lld\n", (long long) lseek(fd, 0, SEEK_CUR));


flags = fcntl(fd, F_GETFL);

if (flags == –1)

errExit("fcntl — F_GETFL");

printf("O_APPEND flag in parent is: %s\n", (flags & O_APPEND)? "on": "off");

exit(EXIT_SUCCESS);

}

}

procexec/fork_file_sharing.c

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

Если не требуется такое совместное использование атрибутов файлов, приложение должно быть спроектировано так, чтобы родитель и потомок после вызова fork() использовали разные дескрипторы, сразу же закрывая те из них, которые были получены из другого процесса (если один из процессов выполняет вызов exec(), вам также может пригодиться флаг FD_CLOEXEC, описанный в разделе 27.4). Эти шаги показаны на рис. 24.2.



Рис. 24.2. Дублирование файловых дескрипторов во время вызова fork() и закрытие тех из них, которые не используются


24.2.2. Семантика памяти вызова fork()

Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных