Н.В. Вдовикина, И.В. Машечкин, А.Н. Терехин, В.В. Тюляева - Программирование в ОС UNIX на языке Си, страница 10
Описание файла
PDF-файл из архива "Н.В. Вдовикина, И.В. Машечкин, А.Н. Терехин, В.В. Тюляева - Программирование в ОС UNIX на языке Си", который расположен в категории "". Всё это находится в предмете "операционные системы" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 10 страницы из PDF
. .fseek(f,0L,SEEK_END);а затем с помощью функции ftell определить номер текущей по-зиции (нумерация начинается с нуля):pos=ftell(f);и разделить его на размер объекта:n=pos/sizeof(long double);Упражнения1. Написать функцию сортировки файла, содержащего числа типаlong, записанные в файл с помощью функции fwrite, не используядополнительных файлов. Используя эту функцию отсортироватьдва файла и слить их в один упорядоченный файл.
Результат записать в первый файл.2. Инвертировать файл, содержащий числа типа int, не используядополнительных файлов.а) Написать функцию для записи в файл анкет студентов. Каждаяанкета есть структура:struct anketa { char fio[20];struct { int day, month, year; } data;short m[3];};в которой поле fio – фамилия студента, поле data – дата рождения, а поле m – оценки, полученные студентом в последнюю сессию.b) Написать функцию, которая из файла анкет студентов удаляетвсех “двоечников”.3. Оставить в файле только строки, содержащие некоторую подстроку. Имя файла и подстроку задавать в виде параметров командной строки.а)Длина строк не превышает 255 символов.б) Длина строк не ограничена.604.
Удалить из файла все строки длиной более пятидесяти символов.Длина строк не ограничена. Имя файла задается в команднойстроке.5. Преобразовать файл, усекая строки до 50-ти символов.6. Упорядочить текстовый файл (лексикографически сравнить строки, длина строки не более 80-ти символов), используя один из методов внешней сортировки.7. Написать функцию-упаковщик файлов.
Коды символов лежат вдиапазоне от 0 до 127. Последовательность из n одинаковыхсимволов заменяется на байт со значением –n и байт, содержащийкод символа. Рассмотреть два варианта: a) n<=127; b) n – любое.8. Написать функцию-распаковщик файлов, см. задачу 8.9. Заменить в файле все “begin” на ‘{‘ ,а “end” на ‘}’.61ТЕМА 9.
Программирование в среде OC UNIX. Организация работы с процессамиПонятие процесса. PID. Контекст процессаСледует отметить, что конкретной ОС с названием UNIX, кактаковой, не существует. Говоря об «операционной системе UNIX»,обычно подразумевают целое семейство различных операционныхсистем, в основу которых положены сходные общие концепции,структуры и алгоритмы. В UNIX процесс является единицей управления и потребления ресурсов, а с точки зрения реализации ОС процесс представляет собой объект, зарегистрированный в таблице процессов ядра UNIX.Каждому процессу в UNIX сопоставлено некое уникальноецелое число, называемое идентификатором процесса – PID.
Некоторые значения идентификаторов являются зарезервированными и назначаются специальным процессам ОС, например, во многих ОС семейства UNIX процесс с PID=0 ассоциируется с работой ядра ОС, апроцесс с PID=1 – это процесс init.Процесс характеризуется контекстом, который включает в себя тело процесса, содержимое регистров и аппаратных таблиц ЦП(аппаратный контекст) и атрибуты процесса (PID его родителя,идентификаторы владельца и группы, приоритет, таблицу открытыхфайлов, диспозицию сигналов и др.).Порождение процессовДля создания всех новых процессов в UNIX в операционнойсистеме UNIX, за исключением процессов с PID=0 и PID=1, используется системный вызов pid_t fork (void).Порожденный процесс получает свой уникальный PID.
Для нового процесса создается контекст, содержимое которого по большейчасти копируется из контекста родительского процесса. В частности, тело порожденного процесса содержит копии сегмента кодаи сегмента данных его родителя. Кроме того, в порожденномпроцессе наследуются таблица открытых файлов и разделяемыересурсы процесса-отца, диспозиция сигналов, переменные окружения и др. атрибуты.Не наследуются порожденным процессом сигналы, ждущиедоставки в родительский процесс (в том числе установки взведенного«будильника»,заданныесистемнымвызовомalarm()),блокировки файлов, установленные родительским процессом.По завершении системного вызова fork() каждый из процессов – родительский и порожденный, получив управление, продол62жит выполнение с точки, где возврата из системного вызова fork().Вызов fork() в случае удачного завершения возвращает сыновнемупроцессу значение 0, а родительскому PID порожденного процесса.В случае неудачного завершения, т.е.
если сыновний процесс не былпорожден, системный вызов fork() возвращает –1, код ошибки устанавливается в переменной errno.Задача 1. Породить сыновний процесс, затем в обоих процессах вывести на печать собственный PID и PID родительского процесса.#include <sys/types.h>#include <unistd.h>#include <stdio.h>int main(int argc, char **argv){printf("PID=%d; PPID=%d \n",getpid(), getppid());/*печать PID текущего процесса и PID процессапредка */fork();/*создание нового процесса, с этого момента двапроцесса функционируют параллельно и независимо*/printf("PID=%d; PPID=%d \n",getpid(), getppid());/*оба процесса печатают PID текущего процесса и PIDпроцесса-предка*/return 0;}Оба процесса узнают свой собственный идентификатор процесса с помощью вызова getpid(), а идентификатор родительскогопроцесса – с помощью вызова getppid().Механизм замены тела процессаСемейство системных вызовов exec() производит замену тела вызывающего процесса, после чего данный процесс начинает выполнять другую программу, начиная с ее точки входа.
После окончания выполнения новой программы возврата к первоначальнойпрограмме затем не происходит.Выполнение «нового» тела происходит в рамках уже существующего процесса, т.е. сохраняется идентификатор процесса, а также идентификатор родительского процесса, ранее открытые файлы,приоритет и большая часть других атрибутов процесса. Фактическипроисходит замена сегмента кода и сегмента данных, а также изменяются следующие атрибуты процесса:- диспозиция сигналов: для сигналов, которые перехватывались, после замены тела процесса будет установлена обработка по умолчанию, так как в новой программе могут от63сутствовать ранее установленные функции-обработчикисигналов;- эффективные идентификаторы владельца и группы могутизмениться, если для новой выполняемой программы установлен s-бит;- перед началом выполнения новой программы могут бытьзакрыты некоторые файлы, ранее открытые в процессе.
Этокасается тех файлов, для которых при помощи системноговызова fcntl() был установлен флаг close-on-exec. Соответствующие файловые дескрипторы будут помечены каксвободные.Часто системный вызов fork() используется совместно с системным вызовом exec().Задача 2. Породить сыновний процесс, в котором запустить навыполнение программу ls.#include <unistd.h>#include <stdio.h>int main(int argc, char **argv){int pid;if(pid=fork())==0){/* процесс-потомок */execl(“/bin/ls”, ”ls”, ”-l”,(char*)0);/* или execlp(“ls”,”ls”, ”-l”,(char*)0);*/printf(“это напечатается в случае неудачногообращения к предыдущей функции, к примеру, если небыл найден файл ls \n”);}}Завершение процесса. Ожидание завершения потомковДля завершения выполнения процесса предназначен системный вызов _exit(int code). С помощью параметра этого вызова процессможет передать породившему его процессу информацию о статусесвоего завершения.
Принято, хотя и не является обязательным правилом, чтобы процесс возвращал нулевое значение при нормальномзавершении, и ненулевое – в случае какой-либо ошибки или нештатной ситуации.В стандартной библиотеке Си имеется функция exit(), которая, помимо обращения к системному вызову _exit(), осуществля-64ет ряд дополнительных действий, таких как, например, очисткастандартных буферов ввода-вывода.Кроме обращения к вызову _exit(), другими причинами завершения процесса могут быть выполнение оператора return, входящего в состав функции main(), а также получение некоторых сигналов.Процесс-предок имеет возможность получить информацию озавершении своего потомка.
Для этого служит системный вызовpid_t wait (int *status).При обращении к этому вызову выполнение родительского процесса приостанавливается до тех пор, пока один из его потомковне завершится либо не будет остановлен. Если у процесса имеется несколько потомков, процесс будет ожидать завершения любого из них. PID завершившегося потомка передается в качествевозвращаемого значения wait(), а через параметр вызова можнополучить информацию о причине завершения потомка и кодевозврата.Часто используется сочетание функций fork()-wait(), еслипроцесс-сын предназначен для выполнения некоторой программы,вызываемой посредством функции exec().
Фактически этим предоставляется процессу-родителю возможность контролироватьокончание выполнения процессов-потомков.Задача 3. Написать программу, которая поочередно запускает на выполнение несколько программ (без параметров), имена которых переданы ей в командной строке.#include <sys/types.h>#include <unistd.h>#include <sys/wait.h>#include <stdio.h>int main(int argc, char **argv){int i;for (i=1; i<argc; i++){int status, pid;if(fork()>0){/*процесс-предок ожидает сообщенияот процесса-потомка о завершении */pid = wait(&status);printf(”process %d finished\n”, pid);continue;}65execlp(argv[i], argv[i], 0);return -1;/*попадем сюда при неуспехе exec()*/}return 0;}Упражнения1. Написать два варианта программы, которая запускает навыполнение следующую строку shell:gcc 1.c –o 1.exe –lmпосредством вызова execl/execlp и execv/execvp.2. В командной строке передаются имена исполняемыхфайлов.
Написать программу, которая запускает указанные исполняемые файлы на выполнение параллельно.66ТЕМА 10. Низкоуровневый ввод/выводОС UNIX предоставляет средства низкоуровневых (т.е лежащих науровне ОС, а не вышележащих библиотек) операций с файлами. Дляэтого в UNIX имеются системные вызовы, осуществляющие непосредственное обращение к средствам ОС и, в частности, к ядру.Для каждого процесса ОС поддерживает таблицу открытыхфайлов процесса (ТОФ).
Номер строки этой таблицы фактическиявляется файловым дескриптором, с которым оперируют все этивызовы. Следует отметить, что при порождении процесса ОС и интерпретатор команд автоматически открывают и сопоставляют первые три дескриптора:0 - стандартный поток ввода информации;1 - стандартный поток вывода информации;2 - стандартный поток вывода диагностик.Открытие, создание, закрытие файла. Права доступа к файламДля выполнения операции открытия файла используется системный вызов open(char *name, int flag[,int perms]),которому в качестве параметров передаются полное имя открываемого файла, комбинация флагов, определяющих режим открытия, атакже значения прав доступа, которые используются в случае, когдауказан флаг «создавать файл, если он ранее не существовал».В UNIX права доступа к файлу задаются для трех категорийпользователей: владельца файла, группы, к которой он принадлежит,и всех остальных пользователей.