Н.В. Вдовикина, И.В. Машечкин, А.Н. Терехин, В.В. Тюляева - Программирование в ОС UNIX на языке Си (1114934), страница 12
Текст из файла (страница 12)
Таким средствомсинхронизации будут сигналы.#include#include#include#include#include#include<signal.h><sys/types.h><sys/wait.h><unistd.h><stdlib.h><stdio.h>#define MAX_CNT 100int target_pid, cnt;int fd[2];int status;void SigHndlr(int s)76{/* в обработчике сигнала происходит и чтение, изапись */signal(SIGUSR1, SigHndlr);if (cnt < MAX_CNT){read(fd[0], &cnt, sizeof(int));printf("%d \n", cnt);cnt++;write(fd[1], &cnt, sizeof(int));/* посылаем сигнал второму: пора читать из канала */kill(target_pid, SIGUSR1);}elseif (target_pid == getppid()){/* условие окончания игры проверяется потомком */printf("Child is going to be terminated\n");close(fd[1]); close(fd[0]);/* завершается потомок */exit(0);} elsekill(target_pid, SIGUSR1);}int main(int argc, char **argv){pipe(fd); /* организован канал */signal (SIGUSR1, SigHndlr);/* установлен обработчик сигнала для обоих процессов*/cnt = 0;if (target_pid = fork()){/* Предку остается только ждать завершения потомка*/while(wait(&status) == -1);printf("Parent is going to be terminated\n");close(fd[1]); close(fd[0]);return 0;}else{/* процесс-потомок узнает PID родителя */target_pid = getppid();/* потомок начинает пинг-понг */write(fd[1], &cnt, sizeof(int));kill(target_pid, SIGUSR1);for(;;); /* бесконечный цикл */77}}Упражнения1.
Написать программу, реализующую следующую команду Shell:a. pr1 arg1 arg2 | pr2; pr3>>f1.datb. pr1<f1.dat | pr2>f2.dat; pr3c. pr1 | pr2 | . . . | prnd. pr1 arg1>f1.dat; pr2 | pr3 | pr4>>f1.dat, где pr i – имена исполняемых файлов, а f i .dat – имена файловданных. Имена в указанном порядке задаются вкомандной строке.2. Написать программу, обрабатывающую каждое четноевозникновение сигнала SIGTRAP формированием двухсыновних процессов, связанных каналом.
Завершитьработу по 3-му нажатию CTRL+C.3. Написать программу подсчета поступивших сигналовSIGTRAP между 2-ым и 4-ым нажатием CTRL+C.Завершить работу по 7-му нажатию CTRL+C.4. Написать программу параллельного поиска подстроки вфайлах, имена которых заданы в командной строке. Поиск подстроки в каждом из заданных файлов организовать в процессе – потомке, создав для каждого файласвой процесс. Программа завершается, как только подстрока будет найдена в одном из файлов. Все незавершенные процессы должны быть прерваны.5. Написать программу слияния двух файлов в третий.Файл-результат формируется чередованием отрезков поN символов из первого и второго файлов (если один изфайлов длиннее другого, то его оставшаяся часть приписывается в конец файла-результата). Имена файлов и величина N задаются в командной строке. Исходные файлы читаются разными процессами; эти же процессы поочереди записывают по N байт из обрабатываемых имифайлов в файл-результат.
Синхронизацию их работы организовать с помощью сигналов.6. Написать программу копирования содержимого одногофайлавдругой.Копированиеосуществляетвспомогательный процесс. Если во время копированиявстретилась строка, длина которой больше N, этотпроцесс сообщает процессу-родителю о такой ситуации.78Головной процесс запрашивает у пользователя, чтоделать с этой строкой:D – не записывать строку в формируемый файл;С – записать только первые N символов;А – прекратить копирование;и сообщает вспомогательному процессу о принятом решении.Головной процесс ждет окончания работы, сообщает пользователю отом, что копирование завершено, и завершается сам.
Имена файлови величина N задаются в командной строке.79ТЕМА 12. Средства межпроцессного взаимодействия System VРассматриваемую в этой главе группу средств межпроцессного взаимодействия называют System V IPC (interprocess communication), так как изначально эти средства были реализованы именно вUNIX System V, однако к настоящему моменту они включены практически во все версии UNIX.System V IPC включает в себя очереди сообщений, семафоры, разделяемую память.Именование разделяемых объектовДля всех средств IPC приняты общие правила именованияобъектов, позволяющие процессу получить доступ к такому объекту.Для именования объекта IPC используется ключ, представляющийсобой целое число.
Ключи являются уникальными во всей UNIXсистеме идентификаторами объектов IPC, и, зная ключ для некоторого объекта, процесс может получить к нему доступ. При этом процессу возвращается дескриптор объекта, который в дальнейшем используется для всех операций с ним. Проведя аналогию с файловойсистемой, можно сказать, что ключ аналогичен имени файла, а получаемый по ключу дескриптор – файловому дескриптору, получаемому во время операции открытия файла.Ключ для каждого объекта IPC задается в момент его созданиятем процессом, который его порождает, а все процессы, желающиеполучить в дальнейшем доступ к этому объекту, должны указыватьтот же самый ключ.Как видно, встает проблема именования разделяемого ресурса:необходим некий механизм получения заведомо уникального ключадля именования ресурса, но вместе с тем нужно, чтобы этот механизм позволял всем процессам, желающим работать с одним ресурсом, получить одно и то же значение ключа.Для решения этой задачи служит функция key_t ftok(char*filename, int proj).
Эта функция генерирует значение ключапо путевому имени некоторого существующего файла и добавочному целому, передаваемым в качестве параметров. Она используетдля создания значения ключа номер индексного дескриптора указанного файла и информацию о файловой системе, в которой он находится. Если файл с указанным именем не существует или недоступен вызывающему процессу, функция возвращает -1.Гарантируется, что при повторном запуске ftok() с теми же параметрамибудет получено то же самое значение ключа 15.
Предполагается, чтопри условии, что указанный файл между двумя обращениями к ftok() не удалялся и непересоздавался заново, т.к. при этом он получит другой номер индексного дескриптора1580передаваемое путевое имя файла известно всем процессам вызывающей программы и имеет в рамках ее некоторый смысл (например, это может быть имя демона-сервера, имя файла данных используемого сервером и т.п.).Смысл же второго аргумента функции ftok() – добавочногоцелого – в том, что он позволяет генерировать разные значения ключа по одному и тому же значению первого параметра – имени файла.Тем самым, используя одно и то же путевое имя, можно получитьнесколько ключей, если нам требуется доступ к нескольким различным ресурсам в рамках одной и той же программы. Кроме того, этопозволяет программисту поддерживать несколько версий своей программы, которые будут использовать одно и то же имя файла, норазные добавочные параметры для генерации ключа, и тем самымполучат возможность в рамках одной системы работать с разнымиразделяемыми ресурсами.Функция ftok() не является системным вызовом, а предоставляется библиотекой.Общие принципы работы с разделяемыми ресурсамиКак уже говорилось, общим для всех ресурсов является механизм именования.
Кроме того, для каждого IPC-ресурса поддерживается идентификатор его владельца и структура, описывающая права доступа к нему. Подобно файлам, права доступа задаются отдельно для владельца, его группы и всех остальных пользователей; однако, для разделяемых ресурсов поддерживается только две категориидоступа: по чтению и записи. Априори считается, что возможностьизменять свойства ресурса и удалять его имеется только у процесса,эффективный идентификатор пользователя которого совпадает сидентификатором владельца ресурса.
Владельцем ресурса назначается пользователь, от имени которого выполнялся процесс, создавший ресурс, однако создатель может передать права владельца другому пользователю. В заголовочном файле <sys/ipc.h> определентип struct ipc_perm, который описывает права доступа к любомуIPC-ресурсу. Поля в этой структуре содержат информацию о создателе и владельце ресурса и их группах, правах доступа к ресурсу иего ключе.Для создания разделяемого ресурса с заданным ключом, либоподключения к уже существующему ресурсу с таким ключом используются ряд системных вызовов, имеющих общий суффикс get.Общими параметрами для всех этих вызовов являются ключ и флаги.В качестве значения ключа при создании любого IPC-объектаможет быть указано значение IPC_PRIVATE.
При этом создается ре81сурс, который будет доступен только породившему его процессу.Такие ресурсы обычно порождаются родительским процессом, который затем сохраняет полученный дескриптор в некоторой переменной и порождает своих потомков. Так как потомкам доступенуже готовый дескриптор созданного объекта, они могут непосредственно работать с ним, не обращаясь предварительно к «get»методу. Таким образом, созданный ресурс может совместно использоваться родительским и порожденными процессами.