Пример многозадачного кода: файл fork_demo.c.

Программа делает разветвление и оба процесса: родительский и дочерний, выводят кое-что на экран. Результатом является чередование этих выводов.

 

(01) #include <unistd.h>

(02) #include <sys/types.h>

(03) #include <stdio.h>

 

(04) int main()

(05) {

(05) pid_t pid;

(06) int i;

 

(07) pid = fork();

 

(08) if (pid == 0){

(09) for (i = 0; i < 8; i++){

(10) printf("-ДОЧЕРНИЙ-\n");

(11) }

(12) return(0);

(13) }

 

(14) for (i = 0; i < 8; i++){

(15) printf("+РОДИТЕЛЬСКИЙ+\n");

(16) }

 

(17) return(0);

(18) }

 

Строки (01)-(03) содержат включения заголовочных файлов необходимых библиотек (стандартный ввод/вывод, многозадачность).

Функция main (как обычно в GNU) возвращает целое, которое равно нулю, если все прошло без ошибок и код ошибки, если что-то случилось не то.

Пусть все выполняется без ошибок. Далее, определяется переменная для pid (05) и целое для счетчика в циклах. Типы этих переменных одинаковы, однако они указаны различными для ясности.

В строке (07) вызывается функция fork, которая возвратит нуль в программу, выполняющуюся в дочернем процессе, и pid дочернего процесса в родительском; проверка производится в строке (08). Теперь код строк (09)-(13) будет исполнен в дочернем процессе, а оставшийся код (14)-(16) в родительском.

Эти части кода просто выводят 8 раз в стандартный вывод слово "-ДОЧЕРНИЙ-" или "+РОДИТЕЛЬСКИЙ+" в зависимости от того, какой процесс выполняется, а затем завершают выполнение, возвращая 0. Последнее по-настоящему важно, так как без этого "return" дочерний процесс после завершения цикла будет выполнять далее код родительского.

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

Задержка случайной длины перед каждым вызовом prinf, позволит нагляднее увидеть эффект многозадачности:

 

sleep(rand()%4)

 

это заставит программу "заснуть" на случайное число секунд: от 0 до 3 (% возвращает остаток от целочисленного деления). Теперь код выглядит так

 

(09) for (i = 0; i < 8; i++){

(->) sleep (rand()%4);

(10) printf("-ДОЧЕРНИЙ-\n");

(11) }

 

то же можно сделать и с кодом родительского процесса.

Порядок вывода строк может выглядеть следующим образом:

 

[leo@mobile ipc2]$ ./fork_demo2

-ДОЧЕРНИЙ-

+РОДИТЕЛЬСКИЙ+

+РОДИТЕЛЬСКИЙ+

-ДОЧЕРНИЙ-

-ДОЧЕРНИЙ-

+РОДИТЕЛЬСКИЙ+

+РОДИТЕЛЬСКИЙ+

-ДОЧЕРНИЙ-

-ДОЧЕРНИЙ-

+РОДИТЕЛЬСКИЙ+

+РОДИТЕЛЬСКИЙ+

-ДОЧЕРНИЙ-

-ДОЧЕРНИЙ-

-ДОЧЕРНИЙ-

+РОДИТЕЛЬСКИЙ+

+РОДИТЕЛЬСКИЙ+

[leo@mobile ipc2]$

 

Часто родительскому процессу необходимо обмениваться информацией с дочерними или хотя бы синхронизироваться с ними, чтобы выполнять операции в нужное время. Первый способ синхронизации процессов – функция wait

 

pid_t waitpid (pid_t PID, int *STATUS_PTR, int OPTIONS)

 

где PID – это PID ожидаемого процесса, STATUS_PTR – указатель на целое, которое будет содержать статус дочернего процесса (NULL, если эта информация не нужна), а OPTIONS – это набор опций. Пример программы, где родительский процесс создает дочерний и ждет его завершения

 

--------------------------------------------------------------

#include <unistd.h>

#include <sys/types.h>

#include <stdio.h>

 

int main()

{

pid_t pid;

int i;

 

pid = fork();

 

if (pid == 0){

for (i = 0; i < 14; i++){

sleep (rand()%4);

printf("-ДОЧЕРНИЙ-\n");

}

return 0;

}

 

sleep (rand()%4);

printf("+РОДИТЕЛЬСКИЙ+ Ожидаю завершения выполнения дочернего процесса...\n");

waitpid (pid, NULL, 0);

printf("+РОДИТЕЛЬСКИЙ+ ...завершен\n");

 

return 0;

}

--------------------------------------------------------------

 

Функция sleep введена в код родительского процесса, чтобы сделать различными результаты выполнения программы.

Синхронизация процессов

Библиотека SysV – стандартная библиотека, содержащая примитивы структуры IPC ключами. IPC ключ – это число, однозначно идентифицирующее IPC структуру управления (описывается ниже). Также ключ можно использовать для образования универсальных идентификаторов, т.е. для организации не IPC структур.

Ключ создаётся функцией ftok(3).

 

key_t ftok(const char *pathname, int proj_id);

 

Для генерирования ключа ftok берёт имя существующего файла (pathname) и идентификатор процесса (proj_id). Алгоритм построения ключа не исключает возможности появления дубликатов, поэтому следует иметь маленькую библиотеку, просматривающую уже созданные ключи и не допускающую повторений.








Дата добавления: 2015-03-26; просмотров: 550;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.007 сек.