Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 30
Китайская грамота, да? Проясним этот момент еще одним фрагментом программы:
>printf("PID родителя равен %d\n", getpid());
>fflush(stdout);
>if (child_pid = fork()) {
> printf("Это родитель, PID сына %d\n", child_pid);
>} else {
> printf("Это сын, PID %d\n", getpid());
>}
Эта программа выведет на экран примерно следующее:
>PID родителя равен 4496
>Это родитель, PID сына 8197
>Это сын, PID 8197
Таким образом, после применения функции fork() вы можете определить, в каком процессе находитесь («отец» это или «сын»), анализируя значение, возвращаемое функцией fork().
Применение функции vfork() по сравнению с обычной fork() позволяет существенно сэкономить на ресурсах, поскольку она делает разделяемым адресное пространство родителя.
Функция vfork() создает «сына», но затем приостанавливает родительский поток до тех пор, пока «сын» не вызовет функцию exec() или не завершится (с помощью exit() или его друзей). В дополнение к этому, функция vfork() будет работать в системах с физической моделью памяти, в то время как функция fork() не сможет, потому что нуждается в создании такого же адресного пространства, а это в физической модели памяти просто невозможно.
Предположим, что у вас есть процесс, и вы еще не создали никаких потоков (т.е., вы работаете с одним потоком — тем, который вызвал функцию main()). Если вызвать функцию fork(), то будет создан другой процесс, и тоже с одним потоком.
Это был простейший пример.
Теперь предположим, что в вашем процессе вы вызвали pthread_create() для создания другого потока. Если вы теперь вызовете функцию fork(), она возвратит ENOSYS (что означает, что функция не поддерживается)! Почему так?
Вы можете верить этому или нет, но это POSIX-совместимая ситуация. POSIX утверждает, что функция fork() может возвращать ENOSYS. На самом же деле происходит вот что: Си-библиотека QNX/Neutrino не рассчитана на ветвление процесса с потоками. Когда вы вызываете pthread_create(), эта функция устанавливает флаг, сигнализирующий что-то типа «не позволяйте этому процессу применять fork(), потому что механизм ветвления в данном случае не определен». Затем, при вызове fork(), этот флаг проверяется и, если он установлен, это принуждает fork() возвратить значение ENOSYS.