МЕТОДИЧЕСКАЯ РАЗРАБОТКА по учебной дисциплине Операционные системы ПРОГРАММИРОВАНИЕ В ОПЕРАЦИОННЫХ СИСТЕМАХ
методическая разработка на тему
Скачать:
Вложение | Размер |
---|---|
![]() | 114.63 КБ |
Предварительный просмотр:
ДЕПАРТАМЕНТ ОБРАЗОВАНИЯ ГОРОДА МОСКВЫ
ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
СРЕДНЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ ГОРОДА МОСКВЫ «МОСКОВСКИЙ РАДИОТЕХНИЧЕСКИЙ КОЛЛЕДЖ
ИМЕНИ А.А. РАСПЛЕТИНА»
«УТВЕРЖДАЮ»
Зам. директора по УМР
_________И.В.Микитенко
«___ » _______________ 2013 года
МЕТОДИЧЕСКАЯ РАЗРАБОТКА
по учебной дисциплине
Операционные системы
ПРОГРАММИРОВАНИЕ В ОПЕРАЦИОННЫХ СИСТЕМАХ
для учащихся
по направлению подготовки (специальности)
230115 – «Программирование в компьютерных системах»
230113«Компьютерные системы и комплексы»
230113«Компьютерные системы и комплексы»
МОСКВА
2013
Методическое пособие разработано для студентов специальности 230115 «Программирование в компьютерных системах», 230113«Компьютерные системы и комплексы» и 230111 «Компьютерные сети» с целью оказания методической помощи при выполнении лабораторных работ по дисциплине «Операционные системы».
Система
Составитель: преподаватель МРТК им.А.А.Расплетина Федорова Н.В.
Рецензент: преподаватель МРТК им.А.А.Расплетина Бурацкая Л.В.
Рассмотрено и утверждено на заседании ПЦК Программирования
Протокол №___ от «___» ___________ 2013г.
Председатель комиссии______________________ Н.В.Федорова Н.В.
СОДЕРЖАНИЕ
1 Программирование в ОС MSDOS
1.1 Использование пакетных файлов
2 Программирование в ОС семейства UNIX
2.1 Программирование на SHELL. Использование командных файлов
2.2 Программирование в ОС использованием AWK»
2.3 Программирование в ОС с использованием СИ»
2.3.1 СИ-функции работы с файлами
2.3.2 СИ-функции управления процессами
2.4 Управление оперативной памятью
Список литературы
Методическое пособие может быть использовано студентами специальностей 230115 «Программирование в компьютерных системах», 230113«Компьютерные системы и комплексы» и 230111 «Компьютерные сети» для изучения основных правил программирования на СИ++, SHELL, AWK при работе с операционными системами семейства UNIX, основных правил разработки командных файлов в ОС UNIX, MSDOS.
Методическое пособие содержит теоретический материал, примеры программ, задания к выполнению лабораторных работ, контрольные вопросы для самопроверки.
Изучение средств и методов разработки пользовательских приложений для управления ресурсами вычислительной системы, разработки конфигурационных файлов поможет студенту получить знания, практические навыки в системном администрировании.
Методическое пособие не претендует на полноту изложения материала, основной целью его является оказать помощь студентам в освоении учебной программы по дисциплине «Операционные системы».
1 ПРОГРАММИРОВАНИЕ В ОС MSDOS
1.1 Использование пакетных файлов
Цель лабораторной работы: изучение команд, используемых в написании пакетных файлов.
Основные понятия. Удобная рабочая обстановка для пользователя ПЭВМ может быть создана в результате продуманного конфигурирования и начальной настройки системы. DOS дает возможность при запуске машины автоматически задавать определенные начальные условия, которые влияют на дальнейшую работу пользователя. Кроме того, создание и последующее использование пакетных файлов позволяет системному администратору автоматизировать процесс конфигурирования и администрирования системы.
Пакетные файлы можно считать особой категорией исполняемых программ. Если часто необходимо выполнять определенную последовательность действий на компьютере, то команды в порядке выполнения рекомендуется поместить в специальный пакетный файл. Исполнение файла приведет к выполнению команд. Такие файлы должны иметь тип bat (от английского слова batch – «пакетный»). Запуск пакетного файла осуществляется точно так же, как и запуск обычной исполнимой программы типа .com или .exe. Пакетный файл, в отличие от обычных исполнимых программ, содержит не машинные коды программ, а текст, который интерпретируется командным процессором DOS. Строки этого текста могут представлять собой:
- встроенные команды DOS;
- обращения к исполнимым программам;
- вызовы других пакетных файлов;
- специальные команды для управления выдачей на экран;
- специальные команды для организации ветвлений и циклов;
- метки.
В пакетных файлах могут использоваться формальные параметры от %1 до %9. Формальный параметр принимает фактическое значение тех данных, которые указываются в командной строке после имени пакетного файла. Пример:
@echo off
cls
type %1
pause
При запуске данного пакетного файла следует указать в командной строке имя файла для просмотра. Вместо %1 будет подставлено имя этого файла с последующим выводом на экран содержимого файла в результате выполнения команды type.
В пакетных файлах DOS могут фигурировать специальные команды, предназначенные для создания нетривиальных управляющих последовательностей. К ним относятся:
- GOTO – безусловный переход (на метку);
- IF – проверка условия и ветвление;
- FOR – управление повторным выполнением команд;
- SHIFT – сдвиг списка формальных параметров.
Рассмотрим действие специальных команд, позволяющих управлять интерпретацией командных файлов.
Команда GOTO. Команда GOTO позволяет передавать управление на метку и тем самым осуществлять повторное исполнение участков командного файла или, наоборот, обходить некоторые участки (это имеет смысл в сочетании с командой ветвления IF). Пример:
echo off
:m1
echo вывод на принтер файла
echo Для остановки нажмите ctrl+break
copy %1 prn
pause
goto m1
В данном примере вторая строка содержит метку m1 (признаком метки является двоеточие в начале строки), а последняя строка – команду перехода на эту метку. Четыре команды внутри повторяемого участка командного файла служат для выдачи на экран поясняющих сообщений (команды ECHO) и копирования на принтер файла, имя которого подставляется вместо формального параметра %1. Команда PAUSE приостанавливает исполнение, чтобы пользователь имел возможность осмотреться и прервать работу или продолжить ее дальше. Допустим, пользователь дает с терминала команду: A:\>pr docum.doc. Начинается циклическое исполнение файла pr.bat с фактическим параметром docum.doc. На принтер начнут выдаваться одна за другой копии этого текстового файла, прерываемые паузами после каждой очередной копии.
Команда IF. Команда IF позволяет проверять условие и выполнять ветвление в зависимости от результата его проверки. Команда IF имеет три формата.
Формат 1. Проверка кода завершения какой-либо программы, сработавшей перед оператором IF.
Используется конструкция следующего вида:
IF ERRORLEVEL
Любая программа может с помощью специального прерывания DOS выработать в момент своего окончания собственный код завершения. Этот код сравнивается с числом N. Условие считается выполненным (истинным), если выработанный код завершения равен или больше указанного числа N.
Формат 2. Проверка наличия файла в каталоге. В этом случае начало оператора IF имеет вид:
IF EXIST <расширенное имя файла>
В данном случае команда IF проверяет, действительно ли существует файл с заданным именем в указанном или в текущем каталоге. При обнаружении файла условие считается выполненным.
Формат 3. Сравнение двух строк, которые, в частности, могут задаваться через формальные параметры. Соответствующая конструкция может иметь вид:
IF %
Здесь значение формального параметра %
Пример: Создание пакетного файла, проверяющего наличие в командной строке требуемого файла.
@echo off
if %1 == a goto end
exit
pause
:end
echo okey
Введите в командной строке proba.bat a или proba.bat b. Убедитесь в исполнении файла.
Команда FOR. Команда FOR обеспечивает циклическое выполнение команд DOS. При этом можно задать формальный параметр и список фактических параметров (обычно – имен файлов), которые последовательно подставляются вместо формального параметра в текст исполняемой команды.
Спецификация команды:
for %%<переменная> in <значение> do <команда>
Пример:
for %%a in *.txt do type %a
Осуществляется просмотр содержимого файлов с расширением txt текущего каталога.
Команда SHIFT. Команда SHIFT вызывает сдвиг списка формальных параметров относительно списка фактических параметров. Так, если в командном файле фигурируют формальные параметры %1 и %2, а в обращении к командному файлу – фактические параметры A, B, C, D, то сначала соответствие формальных и фактических параметров выглядит следующим образом:
%1=A %2=B
Однократное применения команды SHIFT дает следующее соответствие:
%1=B %2=C
Двукратное применение вызывает дальнейший сдвиг:
%1=C %2=D
Пример:
:begin
type %1
shift
echo Enter ctrl+break for exit
goto begin
Практическое задание к выполнению лабораторной работы на тему «Пакетные файлы MSDOS»
В каталоге C:\BAT создать пакетные файлы, выполняющие следующие действия:
1. На первом этапе выполнения пакетного файла выводится сообщение-заголовок (на Ваше усмотрение). Далее осуществляется поочередная постраничная выдача на экран содержимого двух текстовых файлов по выбору. Затем после нажатия любой клавиши происходит очистка экрана монитора.
2. При выполнении пакетного файла создаются несколько txt-файлов в результате перенаправления справочной информации по некоторым командам (по выбору). Следующим действием пакетного файла является постраничный вывод на экран содержимого этих файлов (при выводе информации на экран использовать оператор for).
3. Задача аналогична предыдущей. Пакетный файл использует формальные параметры для указания команд, по которым необходимо получить справочную информацию.
4. Осуществляется просмотр содержимого файла, полученного путем конкатенации файлов type_nc, type_win. Файл type_nc содержит отсортированную по размеру информацию о содержании каталогом C:\NC exe-файлов. Файл type_win содержит отсортированную по дате создания информацию о содержании каталогом C:\Windows exe-файлов.
5. Создается многотомный архив каталога С:\Games (или любого другого). Тома архива защищены паролем. При нажатии любой клавиши на экран постранично выводится оглавление архива.
6. Осуществляется форматирование дискеты размером 3,5» емкостью 1,44 мБт (указать количество дорожек и секторов) с последующим копированием системных файлов на дискету.
7. Осуществляется печать несколько копий одного документа (выход из цикла – ^C, ^break). Использовать формальный параметр для указания имени файла для печати. Использовать команду перехода для организации цикла. Если принтер не настроен, можно использовать команду выдачи информации не на принтер, а на экран.
8. Задача аналогична предыдущей. Осуществляется печать несколько копий одного документа. Количество копий задается в наборе оператора for.
9. Осуществляется копирование указанного в качестве формального параметра файла на дискету. Первоначально проверяется наличие параметра в командной строке.
10. При выполнении пакетного файла в качестве параметров вводится несколько файлов для удаления. В результате выполнения пакетного файла указанные файлы поочередно удаляются. Использовать команду shift для организации сдвига параметров. Имена файлов для удаления задаются с помощью формальных параметров.
11. Осуществляется проверка наличия файла. В случае, если указанный файл существует, он копируется на дискету. Использовать формальный параметр для указания файла.
12. В качестве формального параметра указывается пароль. Если пароль введен верно, запускается текстовый редактор edit.com (или любая другая программа).
13. Удалить найденные tmp-файлы.
2 ПРОГРАММИРОВАНИЕ В ОС СЕМЕЙСТВА UNIX
2.1 Программирование на SHELL. Использование командных файлов
Цель лабораторной работы: изучение основных возможностей языка программирования Shell с целью автоматизации процесса администрирования системы за счет написания и использования командных файлов.
Основные понятия. Командный язык Shell – язык программирования высокого уровня. На этом языке пользователь осуществляет управление компьютером. После входа в систему Вы начинаете взаимодействовать с командной оболочкой. Shell не является единственным командным языком (хотя именно он стандартизирован в рамках POSIX – стандарта мобильных систем).
Процедура языка shell. Shell – одна из многих команд Unix. Процедура языка Shell – это командный файл. Для выполнения команд необходимо текстовый файл сделать исполнимым (с помощью команды chmod).
Запуск осуществляется следующим образом:
sh имя_исполняемого_файла
Структура команд. Команды в Shell имеют следующий формат:
<имя команды><флаги><аргументы>
В таблице 2.1 представлены некоторые средства группировки команд, которые могут быть использованы при создании командных файлов на shell.
Таблица 2.1 – Средства группировки команд
Средства группировки | Пояснение |
; | определяет последовательное выполнение команд |
& | определяет асинхронное (фоновое) выполнение команд |
&& | определяет выполнение последующей команды при нормальном завершении предыдущей |
|| | определяет выполнение последующей команды при ненормальном завершении предыдущей |
Например:
k1&&k2; k3
k2 будет выполнена при успешном выполнении k1; k3 будет выполнена после любого из исходов обработки k2
k1&&{k2;k3} – k2, k3 будут выполнены при успешном выполнении k1
{k1;k2}& – в фоновой режиме будет выполняться последовательность команд k1, k2
Перенаправление данных. Символы > >> обозначают перенаправление ввода/вывода
Например, ls>file1 // команда ls сформирует список файлов текущего каталога и поместит его в файл file1
wc -l < file1 // команда wc подсчитает число строк файла file1 и выдаст эту информацию на экран
Можно сочетать перенаправления
wc -l < file1>file2 // команда wc подсчитает число строк файла file1 и выдаст эту информацию в файл file2
Shell-переменные. Определение переменной содержит имя и значение var = value. Доступ к переменной осуществляется по имени (со знаком $ перед именем)
fruit = apple (определение)
echo $ fruit (доступ)
apple (результат)
Возможна конкатенация строк
fruit = apple
fruit = pine$ fruit
echo $ fruit
pineapple
Переменная может быть:
1. Частью полного имени файла, например d = /usr/bin
2. Частью команды, например, s = «sort +b filename» //наличие пробелов требует кавычек
Предопределенные переменные языка Shell. В таблице 2.2 представлены наиболее употребительные переменные.
Таблица 2.2 – Наиболее употребительные переменные
Название | Пояснение |
HOME | домашний каталог пользователя |
PATH | множество каталогов, в которых ОС ищет команды |
PS1 | первичная подсказка |
Изменение значения переменной PS1 осуществляется в login-файле. Изменение значения переменной PATH:
echo path | посмотреть |
:/bin :/usr/bin | значение path |
cd | домой |
mkdir bin | новый каталог |
echo $home | посмотреть |
/users/maryann | текущий каталог |
$path = :$home/bin:$path | изменение path |
echo path | посмотреть |
:/users/maryann/bin :/bin :/usr/bin | новое значение path |
Установка переменной Shell выводом из команды
Пример 1
now =’data’
echo $now
Sun Mart 21 12:00:01 PM 2001
Пример 2
menu =’cat file’
echo $menu
text
Пример 3. Для обеспечения видимости переменной используется команда export.
1) a = b; export a
echo $a
2) d = /home/sv; export d
echo $d
3) c = ‘pwd’; export c
echo $c
Структурные операторы shell. Оператор цикла FOR. Синтаксис:
for <переменная> in <список значений>
do <список команд>
done
Пример. Пусть имеется командный файл makelist:
cat makelist
sort +1 people | pr -h Distribution | lpr //Сортировка по второму полю, печать заголовка, распечатка файла
Если вместо одного файла people имеется несколько adminpeople, hardpeople, softpeople, то необходимо повторить выполнение процедуры с различными файлами с помощью оператора for
Пример 1
for file in adminpeople, hardpeople, softpeople
do
sort +1 $file | pr -h Distribution | lpr
done
Пример 2
for file in *people
do
sort $file
done
Синтаксис:
if <если эта команда выполняется успешно, то>
then <выполнить все последующие команды до else или, если его нет, до fi>
[else <иначе выполнить следующие команды до fi>]
fi
Пример
if test $# -eg 0
then echo «You must give a filename»
exit 1
else sort +1 $1| …| lpr
fi
// Если значение переменной # равно нулю, выводится сообщение «You must give a filename», выполнение программы прекращается. Иначе выполняется команда сортировки данных.
Команда TEST. Эта команда применяется внутри shell-процедур.
Имеется три типа проверок: оценка числовых значений; оценка типа файла; оценка строк.
Для чисел синтаксис следующий. N op M, где N, M -числовые переменные, операция op принимает следующие значения:
-eg | равно |
-ne | не равно |
-gt | больше |
-lt | меньше |
-ge | больше и равно |
-le | меньше или равно |
Для файла синтаксис такой:
op filename
операция op принимает следующие значения:
-s | файл существует и не пуст |
-f | файл, а не каталог |
-d | файл-директория |
-w | файл для записи |
-r | файл для чтения |
Для строк синтаксис такой:
S op R операция op принимает следующие значения:\
= | эквивалентность |
!= | неэквивалентность |
-z | строка нулевой длины |
-n | ненулевая длина строки |
Несколько проверок могут быть объединены логическими операциями -a (and) и -o (or).
Пример 1
if test -w $2 -a -r $1
then cat $1>> $2
else echo «can not append»
fi
Пример 2
echo «Vvedite a»
read a
echo «Vvedite b»
read b
if test $a -lt $b
then
echo «Hello»
else
echo «…»
fi
Синтаксис:
while <команда>
do <команда>
done
Пример 1
n = 0
while test $n -lt 5
do
cat myfile1|lpr
n=`expr$n+1`
done
Пример 2
while test $# -gt 0
do
if test -s $1
then echo «no file $1»> $2
else sort +1 $1 …
fi
do
Этот оператор инвертирует условие повторения по сравнению с оператором
while
until <команда>
do <команды>
done
Пока «команда» не выполнится успешно, выполнять «команды», завершаемые ключевым словом done
Пример
if test $# -eg 0
then echo «Usage …»>$2
exit
fi
until test $# -eg 0
do
if test -s $1
then echo «no file $1»>$2
else sort …
fi
shift
done
Синтаксис:
case
string1) <если string = string1, то выполнить все следующие команды до ;;> ;;
string2) <если string = string2, то выполнить все следующие команды до ;;> ;; string3) и т.д.
esac.
Пример 1
together = no
case $1 in
-t) together = yes
shift;;
-?) echo «$0: no option $1»
exit;;
esac
if test $ together = yes
then sort …
fi
Пример 2
while true
do
echo»Check menu your computer»
1) Disk space
2) Mounted file systems
3) System name
4) Who is logged in
5) Exit
«
echo «What do you want?»
read number
case $number in
1) df
;;
2) mount -t msdos dev/fd0 /mnt/floppy
;;
3) uname
;;
4) who
;;
5)break
;;
*) echo «you must enter a number (1 throught 5)»
continue
;;
esac
done
exit 0
На экране появляется меню. При выборе определенного пункта меню выполняется соответствующая команда.
1. Имеются три средства, позволяющие вести отладку процедур.
2. Размещение в теле процедуры команды echo для выдачи сообщений, являющихся трасой выполнения процедуры.
3. Опция -v (verbose – многословный) в команде Shell приводит к печати команды на экран перед ее выполнением.
4. Опция -x (execute) в команде Shell приводит к печати команды на экране по мере ее выполнения с заменой всех переменных их значениями.
Практическое задание к выполнению лабораторной работы на тему «Программирование на SHELL в ОС семейства UNIX»
1. Используя команды ECHO, PRINTF вывести информационные сообщения на экран.
2. Присвоить переменной А целочисленное значение. Просмотреть значение переменной А.
3. Присвоить переменной В значение переменной А. Просмотреть значение переменной В.
4. Присвоить переменной С значение «путь до своего каталога». Перейти в этот каталог с использованием переменной.
5. Присвоить переменной D значение «имя команды», а именно, команды DATE. Выполнить эту команду, используя значение переменной.
6. Присвоить переменной E значение «имя команды», а именно, команды просмотра содержимого файла, просмотреть содержимое переменной. Выполнить эту команду, используя значение переменной.
7. Присвоить переменной F значение «имя команды», а именно сортировки содержимого текстового файла. Выполнить эту команду, используя значение переменной.
Написать скрипты, при запуске которых выполняются следующие действия:
8. Программа запрашивает значение переменной, а затем выводит значение этой переменной.
9. Программа запрашивает имя пользователя, затем здоровается с ним, используя значение введенной переменной.
10. Программа запрашивает значения двух переменных, вычисляет сумму (разность, произведение, деление) этих переменных. Результат выводится на экран (использовать команды a) EXPR; б) ВС).,
11. Вычислить объем цилиндра. Исходные данные запрашиваются программой. Результат выводится на экран.
12. Используя позиционные параметры, отобразить имя программы, количество аргументов командной строки, значение каждого аргумента командной строки.
13. Используя позиционный параметр, отобразить содержимое текстового файла, указанного в качестве аргумента командной строки. После паузы экран очищается.
14. Используя оператор FOR, отобразить содержимое текстовых файлов текущего каталога поэкранно.
15. Программой запрашивается ввод числа, значение которого затем сравнивается с допустимым значением. В результате этого сравнения на экран выдаются соответствующие сообщения.
16. Программой запрашивается год, определяется, високосный ли он. Результат выдается на экран.
17. Вводятся целочисленные значения двух переменных. Вводится диапазон данных. Пока значения переменных находятся в указанном диапазоне, их значения инкрементируются.
18. В качестве аргумента командной строки указывается пароль. Если пароль введен верно, постранично отображается в длинном формате с указанием скрытых файлов содержимое каталога /etc.
19. Проверить, существует ли файл. Если да, выводится на экран его содержимое, если нет – выдается соответствующее сообщение.
20. Если файл есть каталог и этот каталог можно читать, просматривается содержимое этого каталога. Если каталог отсутствует, он создается. Если файл не есть каталог, просматривается содержимое файла.
21. Анализируются атрибуты файла. Если первый файл существует и используется для чтения, а второй файл существует и используется для записи, то содержимое первого файла перенаправляется во второй файл. В случае несовпадений указанных атрибутов или отсутствия файлов на экран выдаются соответствующие сообщения (использовать а) имена файлов; б) позиционные параметры).
22. Если файл запуска программы найден, программа запускается (по выбору).
23. В качестве позиционного параметра задается файл, анализируется его размер. Если размер файла больше нуля, содержимое файла сортируется по первому столбцу по возрастанию, отсортированная информация помещается в другой файл, содержимое которого затем отображается на экране.
24. Командой TAR осуществляется сборка всех текстовых файлов текущего каталога в один архивный файл my.tar, после паузы просматривается содержимое файла my.tar, затем командой GZIP архивный файл my.tar сжимается.
25. Написать скрипт с использованием функции, например, функции, суммирующей значения двух переменных.
Все скрипты выполнить, содержимое письменно отобразить в отчете по лабораторной работе.
2.2 Программирование в ОС с использованием AWK»
Цель лабораторной работы: изучение команды awk, использующей встроенный язык программирования, для работы с текстовыми файлами.
Основные понятия. AWK – утилита, предназначенная для простых, механических и вычислительных манипуляций над данными. Довольно несложные операции часто необходимо выполнить над целыми пакетами файлов, а писать для этого программу на одном из стандартных языков программирования является утомительным и, как правило, не очень простым делом. Оптимальное решение проблемы – использование специальной утилиты AWK, включающей в себя не громоздкий и удобный язык программирования, позволяющий решать задачи обработки данных с помощью коротких программ, состоящих из двух-трех строк.
Утилита AWK изначально объединяла свойства утилит UNIX – sed и grep. В дальнейшем ее возможности значительно расширились. Утилита AWK была создана в 1977г, американскими авторами: Alfred V.Aho, Brian W.Kernighan и Peter J.Weinberger. Подробное описание всех возможностей утилиты AWK для UNIX дает их издание: ``The AWK Programming Language'', 1988.
AWK сканирует input (стандартный или указываемый набор файлов), и над строками, удовлетворяющими заданному образцу, выполняет указываемые действия. Строка может содержать максимально до 256 символов.
Формат:
awk [-Fc] [-f file] [files]
awk [-Fc] [prog] [files]
prog – программа, вида: <образец> <действие>
file – файл с AWK-программой
files – файлы, предназначенные для AWK-обработки.
-Fc – устанавливает разделитель полей.
Общая структура AWK-программы
Язык программирования AWK допускает использование: полей; переменных (стандартных, массивов); арифметических выражений.
Язык программирования AWK допускает использование образцов следующего вида: регулярное выражение; выражение отношения; комбинация образцов; слова BEGIN и END.
Действие в AWK определяет: последовательность предложений, разделенных ``;'' или ``\n'' (новая строка).
Предложение определяет: вывод (печать); присваивание; встроенная функция; управляющая структура.
Поля. Каждая сканируемая строка input рассматривается как состоящая из полей, разделенных разделительными символами (по умолчанию – пробел).
На поля можно ссылаться из AWK программы следующим образом:
$1 – Первое поле;
$2 – Второе поле и т.д.
$0 – Ссылается на всю строку целиком.
Строка может содержать максимально до 100 полей.
Значения переменных
Переменные могут интерпретироваться как числовые или строковые. Они принимают значения в зависимости от контекста, например:
x = 1, x воспринимается как число;
x = " ", x – строка;
x + "abc" – результат операции интерпретируется как число независимо от того, было ли х числом или строкой. Если строка не может быть интерпретирована как число ("abc"), то ее значение становится 0.
Строка может содержать максимально до 256 символов.
Ссылки на поля $1, $2, ... могут интерпретироваться в качестве переменных, например:
$1 = "3" + $2 – первое поле принимает значение второго поля, увеличенного на 3.
$(i+1) – интерпретируется как поле, номер которого зависит от значения переменной i.
Допускается использование массивов. Массивы не объявляются, а принимают значения из контекста, например:
x[NR] = $0 – элементу массива x, индексированному NR, присваивается обрабатываемая строка (NR – number of records – номер записи, количество записей).
x["apple"] – элементы массива могут индексироваться не числовым значением, т.е. строкой.
Выражение включает: переменную; число; строку; встроенную функцию.
Арифметические выражения имеют вид:
Выражение < Операция> Выражение.
< Операция> : "+", "-", "*", "/", "%"
Для осуществления поиска в AWK языке допускается использование регулярных выражений, определенных в описании. Дополнения к использованию регулярных выражений, допускаемые в AWK-языке:
"( )" – скобки допускаются для группирования;
" |" – указание альтернативы "или";
" + " – плюс, стоящий за регулярным выражением означает любую последовательность вхождений этого выражения, начиная с 1;
" ? " – Знак вопроса за регулярным выражением означает 0 или 1 вхождений этого выражения;
[A-Z] – Допускается сокращенная форма записи для рангов ASCII символов;
Установленный порядок выполнения операторов на одном скобочном уровне: "[] * + ? конкатенация |".
Выражение отношение может быть двух типов:
< Выражение> < Принадлежность> < Выражение>
< Выражение> < Лог. Операция> < Выражение>
Принадлежность: ~ – Содержится; !~ – Не содержится.
Лог. Операция: < , < =, ==, !=, > =, > .
Допускается логическая комбинация образцов с использованием следующих знаков: || – ``или'', & & – ``и'', ! – ``не''.
Образец BEGIN указывает на начало input или на те действия, которые должны быть выполнены до какого бы то ни было анализа строк. Образец END указывает на конец input или на те действия, которые должны быть выполнены после обработки всех строк.
Например:
BEGIN {FS = ":"} – Устанавливает разделитель полей в ":" до начала обработки строк. Эквивалентно опции "-F:" при AWK вызове.
END { print NR } – Печатает номер последней строки input, т.е. количество обработанных входных строк.
Формат оператора печати:
PRINT [< список выражений> ] [ > < выражение1> ]
Если в списке выражения находятся через запятую, то значения этих выражений выводятся на output (печатаются) через символ-разделитель OFS (по умолчанию пробел). Если же выражения стоят через пробел, то на печати происходит их конкатенация.
Значение < выражения1> рассматривается как имя файла. Само его присутствие означает печать в файл. Если вместо ``> '' стоит ``> > '', то это означает добавление к уже существующему файлу. Можно использовать в одной программе максимально до 10 output файлов.
Оператор форматированной печати:
PRINTF формат [,список выражений] [ > выражение1]
формат: символьная строка в двойных кавычках. Идентичен формату, используемому в функции printf в языке С. Формат может содержать:
обычные символы, они копируются на output.
esc-последовательности, представляющие неграфические символы, например, "\n" – новая строка.
спецификации для вывода аргументов, они следуют после символа ``%''. Число спецификаций должно быть равно числу аргументов. (Если оно меньше числа аргументов, то лишние аргументы игнорируются, если же больше – то это ошибка).
Оператор присваивания имеет вид:
< переменная> = < выражение>
Начальное значение переменной 0 или `` '' (пробел). Допускаются другие типы присваивания в соответствии с языком С: "+=","-=","*=","/=","%=".
< переменная> ++, ++< переменная> – увеличение значения переменной на 1.
< переменная> --, --< переменная> – уменьшение значения переменной на 1.
length(arg) – Функция длины arg. Если arg не указан, то выдает длину текущей строки.
exp(),log(),sqrt() – Математические функции экспонента, логарифм и квадратный корень.
int() – Функция целой части числа.
substr(s,m,n) – Возвращает подстроку строки s, начиная с позиции m, всего n символов.
index(s,t) – Возвращает начальную позицию подстроки t в строке s. (Или 0, если t в s не содержится.)
sprintf(fmt,exp1,exp2,...) – Осуществляет форматированную печать (вывод) в строку, идентично PRINTF.
split(s,array,sep) – Помещает поля строки s в массив array и возвращает число заполненных элементов массива. Если указан sep, то при анализе строки он понимается как разделитель.
Условное предложение:
if ( < условие> ) < предложение>
\hskip 1cm [else < предложение> ]
Предложения цикла:
while ( < условие> ) < предложение>
for (< выражение> ; < условие> ; < выражение> )
\hskip 1cm < предложение>
Например:
for(i=1; i< =NF; i++) – Аналогично циклу for в языке С. NF – number of fields – номер поля, количество полей.
for (i in array) – Цикл по элементам массива. Элементы массива доступны в этом случае в случайном порядке.
break – Немедленный выход из цикла.
continue – Переход к выполнению следующего предложения.
next – Немедленный переход к анализу следующей строки.
exit – Выход из программы (на конец input).
# – Комментарий.
Примеры использования:
awk ‘{print $0}’ file1 – Сканируется содержимое файла file1. Печатаются все поля каждой записи.
awk ‘{print $1 «,» $2}’ file1 – Сканируется содержимое файла file1. Печатаются первое, второе поле каждой записи.
awk ‘$1==1970 {print $0}’ file1 – Сканируется содержимое файла file1. Печатаются все поля строк, удовлетворяющих заданному условию (год рождения есть 1970).
Практическое задание к выполнению лабораторной работы на тему
«ОС семейства UNIX. Сканирование текстов. Язык программирования AWK»
Создать в домашнем каталоге файл с информацией о сотрудниках. Данные расположить в табличном виде в следующей последовательности: фамилия, имя, название структурного подразделения (СП), оклад, год рождения. В качестве разделителя полей использовать табуляцию.
Используя команду awk:
1. Отобразить на экране всю информацию о сотрудниках из указанного файла в той последовательности, в какой она представлена в файле.
2. Отобразить на экране всю информацию о сотрудниках из указанного файла в обратной последовательности по сравнению с той, в какой она представлена в файле.
3. Отобразить только фамилии, имена сотрудников с нумерацией каждой записи. Информацию в строке выводить с использованием пробела.
4. Отобразить номера структурных подразделений, фамилии сотрудников. Информацию в строке выводить с использованием табуляции. Полученные данные перенаправить в другой файл домашнего каталога, отсортированные по первому столбцу данные отобразить поэкранно.
5. Отобразить все данные о конкретном сотруднике. Информацию в строке выводить с использованием двойной табуляции.
6. Отобразить фамилии сотрудников конкретного структурного подразделения.
7. Отобразить фамилии, названия СП сотрудников одного года рождения.
8. Отобразить названия СП, в которых есть сотрудники старше 1985 года рождения.
9. Определить суммарное значение по полю оклад сотрудников данной организации.
10. Определить суммарное значение по полю оклад сотрудников конкретного СП.
11. Отобразить оклад, фамилию сотрудника, имеющего максимальный оклад. При выводе данных использовать следующий формат: десятисимвольное поле для отображения фамилии, целочисленное четырехсимвольное поле для отображения оклада.
12. Задания выполнить:
а) в командной строке;
б) путем написания специальной программы для сканирования данных и формирования отчета
2.3 Программирование в ОС с использованием СИ»
2.3.1 СИ-функции работы с файлами
Цель лабораторной работы: изучение и использование СИ-функций работы с файлами.
Основные понятия. Рассмотрим основные системные вызовы, связанные с проведением операций ввода-вывода, которые наиболее часто используются в операционной системе UNIX. Ввод-вывод в ОС UNIX является крайне простой операцией и налагает на пользователя минимум ограничений.
Системный вызов ореn (открыть файл) имеет следующий формат:
#include
open(name, flags, mode)
char *name;
int flags, mode;
Системный вызов open открывает файл с именем name для чтения и/или записи. Режим открытия файла определяется значением параметра flags. Это значение может быть задано как результат логического сложения следующих признаков (в любой комбинации):
0_RDONLY – открыть только для чтения.
0_WRONLY -открыть только для записи.
0_RDWR – открыть для чтения и записи.
0_NDELAY – не блокировать при открытии. Если операция открытия задерживается по каким-либо причинам, например, при отсутствии готовности линии связи, процесс не приостанавливается. Возвращается код ошибки.
0_АРРЕND – открыть для дозаписи. Обычно, при открытии файла, указатель текущей позиции чтения/записи устанавливается на его начало, но, если задан режим 0_АРРЕND, этот указатель устанавливается на конец файла.
0_СRЕАТ – создать файл, если он не существует.
0_TRUNC – сократить размер файла. В режиме 0_ТRUNC, если указанный файл существует, его размер усекается до нуля.
0_ЕХСL – выдавать ошибку при попытке создания существующего файла. (Этот признак используется в сочетании с признаком 0_СRЕАТ). Режим может применяться для организации простого механизма блокировки.
В случае успешного завершения вызова Ореn, возвращается дескриптор открытого файла, иначе – значение -1 и в переменную еrrnо записывается код ошибки.
При неудачном завершении, переменная еrrnо может принимать следующие значения:
[ЕNOTDIR] – указанное имя, содержит компоненту, которая не является справочником;
[ЕNOENT] – указанный файл не существует и режим 0_СRЕАТ не был определен;
[ЕРЕКМ] – указанное имя содержит символ, отсутствующий в коде АSCП*);
[ЕLООР] – число косвенных ссылок в указанном имени превышает максимально допустимое значение;
[ЕROFS] – указанный файл содержится в файловой системе закрытой по записи и не может быть модифицирован;
[ЕTXTBSY] – попытка открыть на запись файл, содержащий загрузочный модуль выполняющейся реентерабельной программы;
[ЕАССЕS] – режим доступа указанного файла не соответствует
запросу;
[ЕFAULТ] – адрес параметра системного вызова выходит за границы адресного пространства процесса;
[ЕISDIR] Попытка открыть на запись справочник;
[ЕМFILЕ] – переполнена таблица дескрипторов открытых файлов процесса;
[ЕNXIO] – указанный файл является внешним устройством, которое в данный момент не готово к работе.
Системный вызов сrеаt (создать файл) имеет следующий формат:
сreat(name,mode)
сhar *name;
int mode;
Функция сгеаt создает новый (или подготавливает к повторной записи уже существующий) файл с именем name. Если файл еще не существует, значение параметра mode используется для формирования режимов доступа создаваемого файла, при этом учитывается значение маски режимов процесса. Значение параметра mode составляется по правилам, приведенным в описание системного вызова chmod. Если указанный файл существует, то его владелец и режим доступа остаются прежними, а файл усекается до нулевой длины. Кроме того, файл открывается для записи и возвращается его дескриптор.
При неудачном завершении, операции сгеаt возвращается значение -1, в остальных случаях возвращается дескриптор открытого файла (целое положительное число).
После неудачного завершения системного вызова сгеаt переменная еrrnо может принимать следующие значения:
[ЕNOTDIR] – указанное имя содержит компоненту, которая не является справочником;
[ЕNOENТ] – задано слишком длинное или пустое имя файла, или указанный файл не существует или какой-либо из справочников, входящих в имя файла, не доступен для просмотра;
[ЕРЕКМ] – указанное имя содержит символ, отсутствующий в коде АSСП;
[ELООР] – число косвенных ссылок в указанном имени превышает максимально допустимое значение;
[ЕROFS] – попытка создания файла в файловой системе, закрытой на запись;
[ЕТХТВSУ] – попытка сократить длину файла, содержащего загрузочный модуль реентерабельной программы (разделяемый текстовый сегмент), которая в настоящей момент выполняется;
[ЕАССЕS] – режим доступа указанного файла не соответствует запросу;
[ЕFAULТ] – адреса аргументов системного вызова выходят за границы памяти, доступной данному процессу;
[ЕISDIR] – указанное имя файла является именем справочника;
[ЕМFILЕ] – переполнилась таблица открытых файлов процесса;
[ЕNXIO] – указано имя специального файла, для которого нет соответствующего устройства.
Параметр mode задается произвольно, в нем не обязательно должно быть разрешение на запись. Эта возможность используется программами, которые работают с временными файлами с фиксированными именами. Создание производится с режимом, запрещающим запись. Затем, если другая программа пытается выполнить вызов сгеаt, возвращается ошибка и программе становится известно, что в данный момент это имя использовать нельзя. Все действия, перечисленные для вызова сгеаtе, можно выполнить с помощью системного вызова ореn. Вызов сгеаtе оставлен для совместимости с ранними версиями ОС Unix.
Системный вызов геаd (чтение файла) имеет следующий формат:
read (fd, buf, nbytes)
char *buf;
int fd, nbytes;
Системный вызов read обеспечивает считывание nbytes данных в массив buf из файла с дескриптором fd. Информация читается из файла по текущему указателю позиции чтения/записи. После завершения пересылки данных значение указателя увеличивается на число считанных байт. Для некоторых файлов значение указателя позиции чтения/записи не имеет смысла (например, для терминала), тем не менее, данные передаются. При успешном завершении вызова, возвращается число считанных байт, в случае ошибки – значение -1, при достижении конца файла в процессе чтения – число 0.
При возникновении ошибки чтения, переменная еrrnо может принимать следующие значения:
[ЕВАDF] – указанный дескриптор не является дескриптором файла, открытого для чтения;
[ЕFAULТ] – адрес параметра системного вызова не входит в адресное пространство процесса;
[ЕINTR] – чтение с медленного устройства прервано до передачи данных.
Системный вызов write (запись в файл) имеет следующий формат:
write (fd, buf, nbytes)
char *buf;
int fd, nbytes;
Системный вызов write записывает nbytes данных из массива buf в файл с дескриптором fd. Информация записывается в файл по текущему указателю позиции чтения/записи. После завершения пересылки данных, значение указателя увеличивается на число записанных байт. Для некоторых файлов значение указателя позиции чтения/записи не имеет смысла, (например, для терминала), тем не менее, данные передаются.
Если статус файла, в который записывается информация, содержит признак set-UID и процесс работает в непривилегированном режиме, данный признак удаляется (в целях защиты информации). При успешном завершении вызова возвращается число записанных байт, в случае ошибки – значение -1. При возникновении ошибки, переменная еrrnо может принимать следующие значения:
[ЕВАDF] – указанный дескриптор не является дескриптором файла, открытого для записи;
[ЕРIРЕ] – попытка записи в программный канал, который никто не читает;
[ЕРIРЕ] – запись в файл типа "гнездо" в режиме S0СК_SТRЕАМ, при отсутствии соединения;
[ЕFВIG] – при записи в файл превышается допустимый размер файла;
[ЕFAULТ] – адрес параметра системного вызова не входит в адресное пространство процесса.
Системный вызов сlose (закрыть файл) имеет следующий формат:
аns = сlоsе (fd)
int fd;
Системный вызов сlosе удаляет дескриптор fd из таблицы дескрипторов открытых файлов процесса. Если удаленный дескриптор был последним ссылающимся на данный файл, то весь контекст работы с файлом теряется. Для обычного файла это указатель позиции чтения/записи и режим блокировки. Хотя, при завершении процесса, все открытые им файлы автоматически закрываются, число одновременно открытых файлов ограничено, поэтому данный вызов может оказаться необходимым для программ, работающих с большим количеством файлов.
При порождении нового процесса (см описание вызова fork) все его дескрипторы указывают на те же объекты, что и дескрипторы процесса-предка. После выполнения вызова ехесvе в порожденном процессе, новая программа также наследует все активные дескрипторы. Для того, чтобы сделать недоступными новой программе уже открытые файлы, соответствующие дескрипторы можно переопределить с помощью dup2 или удалить с помощью системного вызова unlink. Однако бывают ситуации, в которых уже открытые файлы могут потребоваться при неудачном завершении системного вызова execvе. В таких случаях, применение вызова fcntl обеспечивает закрытие определенных файлов после успешного старта новой программы. В случае успешного завершения, системный вызов с1оsе возвращает значение 0, иначе – значение -1 и код ошибки в переменной еrrnо. Код ошибки:
[ЕВАDF] – указанный дескриптор не является дескриптором открытого файла.
Системный вызов lsееk
Системный вызов lsееk (установка указателя чтения/записи) имеет следующий формат:
#define L_SЕТ 0 /* установка * /
# define L_INCR 1 /* смещение */
# define L_ХТND 2 /* увеличение размера файла */
long lseek (fd, offset, whence)
int fd, whence;
long offset;
Системный вызов lsееk изменяет значение указателя позиции чтения/записи дескриптора fd следующим образом: если значение параметра whence равно L_SЕТ, то указателю присваивается значение параметра, если значение параметра whence равно L_INCR, значение указателя увеличивается на значение offset, если значение параметра whence равно L_XTND, то указателю присваивается значение (offset + fsize), где fsize- размер файла.
Следует отметить, что если установить указатель текущей позиции за конец файла, а затем записать что-либо, в файле получается промежуток, который физически не занимает места, а при чтении дает нули.
В случае успешного завершения, вызов lseek возвращает значение указателя текущей позиции чтения/записи (целое положительное число), определяющее смещение от начала файла (в байтах).
При возникновении ошибки, возвращается значение -1 и код ошибки в переменной еrrnо, которая может принимать следующие значения:
[ЕВАDF] – некорректный дескриптор файла;
[ЕSРIРЕ] – дескриптор относится не к файлу, а к программному каналу или файлу типа "гнездо";
[ЕINVAL] – недопустимое значение параметра.
Дополнительную информацию смотри в методическом пособии «СИ++ для UNIX», лекциях по дисциплине «Системное программное обеспечение».
Практическое задание к выполнению лабораторной работы на тему «СИ-функции работы с файлами»
2.3.2 СИ-функции управления процессами
Цель лабораторной работы: изучение системных функций, обеспечивающих управление процессами в среде ОС семейства UNIХ: их создание, удаление, изменение приоритетности и т.п.
Основные понятия
Системный вызов fork (порождение нового процесса) имеет следующий формат:
pid = fork()
int pid;
Системный вызов fork служит для создания нового процесса. Новый процесс (процесс-потомок) является полной копией процесса-предка, за исключением того, что процесс-потомок имеет свой уникальный идентификатор процесса (РID). Поскольку новый процесс сам может выступать в качестве порождающего, его идентификатор процесса-предка (РРID), естественно, отличается от соответствующего идентификатора породившего его процесса.
Новый процесс имеет собственную копию таблицы дескрипторов открытых файлов, но эти дескрипторы ссылаются на те же самые файлы, что и дескрипторы процесса-предка, и имеют с ним общие указатели позиций чтения/записи. Так, при выполнении операции 1sееk в порожденном процессе, может измениться и позиция чтения/записи файла в процессе-предке. Это свойство, в частности, используется командными языками SН СSН для переопределения файлов стандартного ввода/вывода и организации конвейеров команд. Счетчики использованных ресурсов порожденного процесса инициализируются нулевыми значениями. В случае успешного завершения, системный вызов fork возвращает значение 0 порожденному процессу и идентификатор нового процесса – породившему. При неудачном завершении вызова возвращается значение -1.
Системный вызов wait (ожидание завершения процесса-потомка) имеет следующий формат:
pid = wait (status)
int pid;
int *status;
pid = wait(0)
int = pid;
Системный вызов wait задерживает вызвавший его процесс до поступления сигнала или завершения одного из порожденных им процессов. Если какой-нибудь порожденный процесс завершился в период времени с момента последней выдачи команды wait производится немедленный возврат. Если порожденные процессы отсутствуют, производится немедленный возврат с установкой бита ошибки (соответственно, с возвратом -1). При нормальном возврате, системный вызов wait получает идентификатор завершившегося порожденного процесса. В случае нескольких порожденных процессов нужно произвести несколько вызовов wait , чтобы отследить признаки завершения всех порожденных процессов. При успешном завершении вызова wait , значение status всегда не равно нулю и содержит код возврата и статус завершения порождённого процесса. Если порождающий процесс завершается, не ожидая своих потомков, их наследует стартовый процесс (РID=1). Вызов автоматически перезапускается, если процесс получает сигнал во время ожидания своих потомков. При нормальном завершении выдается идентификатор завершившегося процесса. В случае ошибки – значение -1 и код ошибки в переменной errnо.
Системный вызов exit (завершить процесс) имеет следующий формат:
exit (arg)
int arg;
Параметр arg имеет смысл, определенный в описании вызова wait.
Системный вызов ехit завершает процесс. При этом выполняется очистка некоторых областей памяти, например буферов ввода-вывода. Восемь младших битов аргумента передаются процессу-предку. Возвращаемое значение равно нулю.
Ниже приводится пример использования системных вызовов fork, wait, exit
main ()
{
int pid, status, died;
switch (pid=fork()) /* порождаем новый процесс */
{
саsе -1: /* аварийное завершение */
printf («Can’t fork\n»);
ехit(-1);
саsе 0: /* процесс-потомок */
рrintf («I am the child\n»);
exit (3);
default: /* процесс предок ожидает окончание процесса-потомка */
died = wait (&status);
}
printf («Child was %d\n», pid);
printf (« %d died \n», died);
printf («Exit value %d\n», status>>8);
printf («Exit status %d\n», status &0377);
exit (0);
}
Системные вызовы ехес1, ехес1е, ехесv и ехесvе
Системные вызовы ехес1, ехес1е, ехесv и ехесvе (выполнить файл) имеют форматы:
execl (name, arg0, arg1, arg2, …, 0)
char *name;
char *arg0, *arg1, *arg2, …
execle (name, arg0, arg1, arg2, …, 0, envp)
char *name;
char *arg0, *arg1, *arg2, …
charn *envp[ ];
execv (name, argv)
char *name, *arg[ ];
execve (name, argv, envp)
char *name, *arg[ ], *envp[ ];
Системные вызовы ехес1, ехес1е, ехесv и ехесvе заменяют программу текущего процесса. Новая программа загружается из файла с именем namе, который либо является исполняемым, либо содержит интерпретируемую программу.
Исполняемый файл должен иметь соответствующий формат. Значения передаваемых параметров содержатся:
- для системных вызовов ехес1 и ехес1е – в списке указателей на строки аrg0, arg1...;
- для системных вызовов ехесv и ехесvе – в массиве argv, в виде текстовых строк.
По принятому в системе UNIX соглашению, программе должен передаваться хотя бы один параметр – имя этой программы. Обычно, в качестве имени программы используется базовое (без указания "пути") имя файла name.
Массив envp содержит имена и значения макропеременных среды процесса. Новая программа наследует все открытые файлы, за исключением тех, для которых установлен флаг с1оsе-оn-ехес. Все сигналы, которые игнорировались до выполнения вызовов ехес1, ехес1е, ехесv и ехесvе, будут игнорироваться и после их выполнения. Однако, все. установленные ранее варианты реакций на сигналы заменяются на стандартные.
Каждый процесс имеет реальные и эффективные идентификаторы пользователя и группы. Реальные идентификаторы соответствуют идентификаторам пользователя, который запустил данный процесс, а эффективные определяют права доступа процесса.
Если статус файла с именем name содержит признак set-UID, то при выполнении новой программы изменяются права доступа процесса, т.е. эффективные идентификаторы процесса заменяются на значение идентификаторов владельца файла с именем name. Когда программа начинает выполняться, она вызывается следующим образом:
main (argc, argv, envp)
int argc;
char **argv, **envp;
где argc – количество аргументов в массиве argv, а argv – массив символьных указателей на сами аргументы.
Возврат из системных вызовов ехес1, ехес1е, ехесv, ехесvе всегда означает ошибку. При этом возвращается значение -1 и код ошибки в переменной еггnо. Если данный процесс выполняется в привилегированном режиме, то его полномочия не изменяются, даже если статус файла содержит признак set UID (set-GID).
Ниже приводится пример использования системных вызовов fork, wait, exit, execl.
main()
{
int pid, status;
switch(pid=fork()) /* порождаем новый процесс */
{
case -1: /* аварийное завершение */
printf («Can’ t fork\n»);
exit(1);
case 0: /* процесс-потомок */
printf («I am the child\n»);
execl («/bin/echo», «echo», «Hello mike!», 0);
/* запускаем команду echo «Hello mike!» */
printf («Exec error\n»); /* процесс предок */
wait (&status);
/* ожидаем завершение процесса-потомка */
}
/* Процесс-отец выводит на экран код завершения и статус завершения
процесса-потомка */
printf («Exit value %d\n», status>>8);
printf («Exit status %d\n, status & 0377);
exit(0);
}
Системный вызов getpid возвращает значение идентификатора текущего процесса. Системный вызов getpid (запрос идентификатора текущего процесса) имеет следующий формат:
int getpid( )
Системные вызовы getgid, getegid
Системные вызовы getgid, getegid (запрос идентификатора группы) имеют форматы:
int getgid( )
int getegid( )
Вызов getgid возвращает реальный идентификатор группы текущего процесса, а вызов getegid – эффективный идентификатор группы. Реальный идентификатор группы определяется при регистрации в системе. Эффективный идентификатор определяет дополнительные права доступа при выполнении программы в режиме set-GID (установка идентификатора группы владельца выполняемого файла).
Системные вызовы getuid, geteuid
Системные вызовы getuid, geteuid (запрос идентификатора пользователя) имеют следующие форматы:
int getuid ( )
int geteuid ( )
Системный вызов getuid возвращает реальный идентификатор пользователя для текущего процесса, a geteuid возвращает эффективный идентификатор пользователя. Реальный идентификатор пользователя совпадает с идентификатором, под которым пользователь зарегистрирован в системе. Эффективный идентификатор определяет права доступа пользователя в текущий момент. Такой механизм позволяет программе, работающей в режиме set-UID (установка прав доступа владельца объектного файла), определять, кто ее вызвал.
Системный вызов setgid (установить реальный идентификатор группы процесса) имеет формат:
setgid (rgid) int rgid;
Системный вызов setgid устанавливает идентификатор группы текущего процесса в соответствии с значением параметра rgid. Изменять реальный идентификатор группы можно только в процессе, работающем в привилегированном режиме. В обычном режиме допускает только замена эффективного идентификатора на значение соответствующее реальному идентификатору группы процесса. При успешном завершении, возвращается значение 0, иначе -значение -1 и код ошибки в переменной еrrnо. Код ошибки может принимать значение
[EPERM] (текущий процесс не является привилегированным, и были специфицированы изменения, отличные от замены эффективного идентификатора группы на реальный).
Системный вызов setuid (установить реальный идентификаторы пользователя) имеет следующий формат:
setuid (ruid) int ruid;
Системный вызов setuid устанавливает текущему процессу реальный идентификатор пользователя в соответствии со значением параметра ruid. Изменять реальный идентификатор пользователя можно только в процессе, работающем в привилегированном режиме. В обычном режиме допускается только замена эффективного идентификатора на значение, соответствующее реальному идентификатору. При успешном завершении вызова, возвращается значение О, иначе – значение -1 и код ошибки в переменной еrrnо.
Код ошибки:
[EPERM] – текущий процесс не является привилегированным, и были специфицированы изменения, отличные от замены эффективного идентификатора на реальный.
Ниже приведен пример программы, распечатывающей на стандартный вывод информации о реальных и эффективных идентификаторах пользователя и группы для текущего выполняемого процесса, а также его идентификатор.
main ( )
{
int pid,uid, gid;
int euid, egid;
pid = getpid();
uid •= getuid();
gid = getgid;
euid = geteuid();
egid = getegid();
printf("\tProcess: PID = %d\n", pid);
printf («uid = %d gid = %d\n", uid, gid);
printf("euid = %d egid = %d\n", euid, egid);
}
Системный вызов nice (установить процессу приоритет) имеет следующий формат:
nice (incr)
Системный вызов nice устанавливается текущему процессу новый приоритет, равный текущему приоритету плюс значение аргумента incr. Значение аргумента incr должно лежать в определенном диапазоне, конкретные границы которого зависят от версии ОС UNIX.
UNIX 7. Диапазон значений incr лежит в пределах от -20 до 20. Отрицательное приращение может задавать только привилегированный пользователь.
UNIX System V. Диапазон значений incr лежит в пределах от 0 до 39. Приращения, выходящие за границы этого диапазона, уменьшаются до граничных значений. Чем выше значение аргумента incr, тем ниже устанавливаемый приоритет.
При успешном завершении вызова, возвращается новое значение приоритета минус 20, иначе – значение -1 и код ошибки в переменной еrrnо.
Код ошибки:
[EPERM] Значение incr не лежит в пределах установленного диапазона и эффективный идентификатор владельца процесса не является идентификатором суперпользователя.
Приведенная ниже программа является исходным текстом команды nice UNIX версии System V (вызова какой-либо команды на выполнение с измененным приоритетом):
nice {приращение приоритета} команда
#inc1ude
#include
main (argc, argv) int argc; char *argv [];
{
int nicarg = 10; /* приращение приоритета по умолчанию */
extern errno;
/* Разбираем аргументы команды */
if(argc > 1 && argv[l][0] = ‘-‘) { /* если задано приращение приоритета */
register char *p = argv[l];
if(*++p != ‘-‘) --р;
whi1e(*++p)
if(!isdigit(*p)) { /* указано не числовое значение */
fprintf(stderr, "nice: argument must be numeric.\n");
exit(2);
}
nicarg == atoi (&argv[l] [1]);
/* в переменной nicarg записываем значение приращения приоритета */
argc--;
argv++;
}
if (argc < 2) { /* если не задана команда */
fprintf(stderr, "nice: usage: nice [-num] command\n");
exit(2);
}
nice(nicarg); /* изменяем приоритет процесса */
execvp(argv [1], &argv[l]); /* выполняем команду */
fprintf(stderr. "%s: %d\n", argv[l], errno);
/* если ошибка при запуске команды, то печатаем переменную errno */
exit(2);
}
Дополнительно: Для просмотра запущенных в системе процессов используется команда ps, команда top делает моментальный снимок запущенных в системе процессов, команда nice позволяет изменить приоритетность процесса, команда kill служит для уничтожения процесса.
Практическое задание к выполнению лабораторной работы на тему «СИ. Управление процессами»
1. Просмотреть запущенные в системе процессы.
2. Просмотреть запущенные в системе процессы с указанием их идентификаторов,
3. На втором терминале запустить редактор vi.
4. Определить идентификатор этого процесса.
5. Войти в систему непривилегированным пользователем на третьем терминале.
6. Уничтожить данный процесс.
7. Написать на shell сценарий. Меню выбора: 1 – Просмотр процессов. 2 – Выход. Запуск сценария обеспечивает просмотр запущенных в системе процессов.
8. Написать СИ-программу с использованием функций fork(), execl(), wait(), exit(). Откомпилировать программу и запустить на выполнение.
2.4 Управление оперативной памятью
Цель лабораторной работы: изучение возможностей языка программирования СИ, СИ++ для обращения к ячейкам оперативной памяти, управления ОП.
Основные понятия. Указатели на простые переменные
Указатель – это адрес памяти, распределяемой для размещения идентификатора (в качестве идентификатора может выступать имя переменной, массива, структуры, строкового литерала). В том случае, если переменная объявлена как указатель, то она содержит адрес памяти, по которому может находиться скалярная величина любого типа. При объявлении переменной типа указатель, необходимо определить тип объекта данных, адрес которых будет содержать переменная, и имя указателя с предшествующей звездочкой (или группой звездочек). Формат объявления указателя: спецификатор-типа [модификатор] * описатель
Спецификатор-типа задает тип объекта и может быть любого основного типа, типа структуры, смеси. Задавая вместо спецификатора-типа ключевое слово void, можно своеобразным образом отсрочить спецификацию типа, на который ссылается указатель. Переменная, объявляемая как указатель на тип void, может быть использована для ссылки на объект любого типа. Однако для того, чтобы можно было выполнить арифметические и логические операции над указателями или над объектами, на которые они указывают, необходимо при выполнении каждой операции явно определить тип объектов. Такие определения типов может быть выполнено с помощью операции приведения типов.
В качестве модификаторов при объявлении указателя могут выступать ключевые слова const, near, far, huge. Ключевое слово const указывает, что указатель не может быть изменен в программе. Размер переменной объявленной как указатель, зависит от архитектуры компьютера и от используемой модели памяти, для которой будет компилироваться программа. Указатели на различные типы данных не обязательно должны иметь одинаковую длину.
Для модификации размера указателя можно использовать ключевые слова near, far, huge.
Примеры:
unsigned int * a; // переменная а представляет собой указатель
// на тип unsigned int (целые числа без знака)
double * x; // переменная х указывает на тип данных с
// плавающей точкой удвоенной точности //
char * fuffer ; // объявляется указатель с именем fuffer,
// который указывает на переменную типа char
double nomer;
void *addres;
addres = & nomer;
(double *)addres ++;
Переменная addres объявлена как указатель на объект любого типа. Поэтому ей можно присвоить адрес любого объекта (& – операция вычисления адреса). Однако, как было отмечено выше, ни одна арифметическая операция не может быть выполнена над указателем, пока не будет явно определен тип данных, на которые он указывает. Это можно сделать, используя операцию приведения типа (double *) для преобразования addres к указателю на тип double, а затем увеличение адреса.
const * dr;
Переменная dr объявлена как указатель на константное выражение, т.е. значение указателя может изменяться в процессе выполнения программы, а величина, на которую он указывает, нет.
unsigned char * const w = &obj.
Переменная w объявлена как константный указатель на данные типа char unsigned. Это означает, что на протяжении всей программы w будет указывать на одну и ту же область памяти. Содержание же этой области может быть изменено.
Указатель на величину одного типа может быть преобразован к указателю на величину другого типа. Однако результат может быть не определен из-за отличий в требованиях к выравниванию и размерах для различных типов.
Указатель на тип void может быть преобразован к указателю на любой тип, и указатель на любой тип может быть преобразован к указателю на тип void без ограничений. Значение указателя может быть преобразовано к целой величине. Метод преобразования зависит от размера указателя и размера целого типа следующим образом:
- если размер указателя меньше размера целого типа или равен ему, то указатель преобразуется точно так же, как целое без знака;
- если указатель больше, чем размер целого типа, то указатель сначала преобразуется к указателю с тем же размером, что и целый тип, и затем преобразуется к целому типу.
Целый тип может быть преобразован к адресному типу по следующим правилам:
- если целый тип того же размера, что и указатель, то целая величина просто рассматривается как указатель (целое без знака);
- если размер целого типа отличен от размера указателя, то целый тип сначала преобразуется к размеру указателя (используются способы преобразования, описанные выше), а затем полученное значение трактуется как указатель.
Массивы и указатели на массивы
С++ и С интерпретируют имя массива как адрес его первого элемента. Таким образом, если x – массив, то выражения &x[0] и x эквивалентны. В случае матрицы – назовем ее mat – выражения &mat[0][0] и mat также эквивалентны.
С++ позволяет использовать указатели для обращения к разным элементам массива. Когда Вы вызываете элемент x[i] массива x , то выполняются две задачи: получит базовый адрес массива, т.е. узнать где находится первый элемент массива и использовать i для вычисления смещения базового адреса массива. Фактически, если есть указатель ptr на базовый адрес массива, т.е.
prt = x;
то можно записать :
адрес элемента x[i] = адрес x + i * sizeof(базовый тип)
или
адрес элемента x[i] = ptr + i * sizeof(базовый тип)
В С++ это записывается более коротким образом
адрес элемента x[i] = ptr + i
При последовательном обращении к элементам массива можно использован метод инкремента/декремента указателя, т.е. операцию ++ и --, например
ptr++
a = * ptr++
a = * (ptr--)
С++ поддерживает объявление и использование указателей на структуры. Для присвоения адреса структурной переменной указателю того же типа используется тот же синтаксис, что и в случае простых переменных. После того, как указатель получит адрес структурной переменной, для обращения к элементам структуры нужно использовать операцию ->.
Общий синтаксис для доступа к элементам структуры с помощью указателя имеет вид
structPtr -> aMember
где structPtr -указатель на структуру, aMember – элемент структуры.
Пример:
struct point
{
double x;
double y;
};
point p;
point* ptr = & p;
ptr->x = 23.3;
ptr->y = ptr->x + 12.3;
Операции new и delete. Существует много приложений, в которых необходимо создавать новые переменные и динамически распределять для них память во время выполнения программы. В языке С для этого имеются функции динамической памяти, такие как malloc, calloc, free. В С++ введены новые операции – new и delete, которые лучше контролируют тип создаваемых динамических данных. К тому же эти операции работают с конструкторами и деструкторами ( раздел объектно-ориентированное программирование).
Операции new и delete имеют следующий синтаксис:
указатель = new тип;
delete указатель;
Операция new возвращает адрес динамически распределенной переменной. Операция delete освобождает динамически распределенную память, на которую ссылается указатель.
Если динамическое распределение памяти с помощью операции new потерпело неудачу, оно выбрасывает исключение типа xalloc, объявленное в заголовочном файле EXCEPT.H, поэтому часто динамическое распределение памяти осуществляется внутри блока try. Пример:
try
{
int *pint;
pint = new int;
*pint = 33;
cout << «Указателю выделена память и в ней хранятся данные» << *pint << endl;
delete pint;
}
catch (xalloc&)
{
cout << «Ошибка при выделении памяти» << endl;
Практическое задание к выполнению лабораторной работы на тему «СИ++. Управление оперативной памятью»
1. Написать программу, в которой инициализация переменных различного типа осуществляется с помощью указателей. Значения переменных выводятся на экран.
2. Написать программу, определяющую минимальное, максимальное значения элементов одномерного массива. Элементы массива вводятся с клавиатуры с использованием указателей.
3. Вывести на экран номер элемента одномерного массива, его значение, адрес ячейки памяти с использованием указателей. Элементы массива вводятся с клавиатуры.
4. Написать программу, суммирующую элементы одномерного массива. Элементы массива вводятся с клавиатуры. Ввод данных, обращение к элементам массива осуществляется с помощью указателей.
5. Отсортировать элементы массива. Ввод данных осуществляется с использованием указателей.
6. Написать программу с использованием переменной типа структура. Ввод/вывод, обращение к элементам структуры осуществляется с помощью указателей.
7. Написать программу с использованием операций new, delete (например, просуммировать элементы массива, память под массив распределить динамически).
КОНТРОЛЬНЫЕ ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
1. Что изучает курс «Системное программное обеспечение».
2. Основной принцип модульного программирования.
3. Почему в системном программировании используется язык СИ?
4. Исходный код, объектный код, исполняемый код. Что это такое?
СИ++:
5. Как определить константы с использованием директивы #define?
6. Как определить формальные константы?
7. Как определить размер данных, занимаемых переменной?
8. Как обратиться к элементу массива?
9. Как объявить двумерный массив?
10. Как объявить массив и присвоить начальные значения для матрицы?
11. Какие бывают форматы объявления перечисления?
12. Что такое структура?
13. Какой синтаксис имеет определение структуры? Приведите пример определения структуры.
14. Приведите пример определения экземпляра структуры с использованием тега.
15. Как обратиться к элементу структуры? Приведите пример.
16. Чем отличается объединение от структуры с точки зрения использования памяти?
17. Приведите пример объединения.
18. Приведите пример инициализации составного объекта: структуры, объединения.
19. Для чего используются указатели?
20. Какой синтаксис объявления указателя? Приведите пример объявления указателя.
21. Приведите пример присвоения указателю конкретного значения.
22. Приведите пример объявления указателя на структуры и его использования в тексте программы.
23. Для чего в СИ используется ключевое слово typedef?
24. Что такое функция?
25. Чем функция main отличается от других функций?
26. Что находится в заголовочных файлах?
27. Каким образом они подключаются к программе?
28. Что происходит, если выполнение функции не заканчивается командой return?
29. Данные какого типа не может возвращать функция?
30. Какой тип используется для функции, не возвращающей значения?
31. Что такое список формальных параметров?
32. Что такое спецификатор типа функции?
33. Что содержит тело функции?
34. Что такое рекурсивная функция?
35. Могут ли передаваться данные функции main?
36. Для чего используются глобальные внешние переменные?
37. Что такое время жизни объекта?
38. Что такое область видимости объекта?
39. Какие бывают спецификаторы класса памяти? Чем они отличаются?
40. Чем отличается использование локальных и глобальных переменных?
41. Что такое директивы препроцессора?
42. Что такое макроподстановки? Приведите пример.
43. Что такое встроенные функции?
44. Классы. Пример объявления.
45. Конструкторы. Пример объявления.
46. Деструкторы. Пример объявления.
47. Наследование. Пример объявления производного класса.
48. Системные вызовы creat, read, open, write, close. Примеры использования.
49. Системные вызовы fork, execl, wait, nice, exit. Примеры использования.
СПИСОК ЛИТЕРАТУРЫ
1. Герхард Франкен, Сергей Молявко MS DOS для пользователя. – Киев, 1993.
2. Теренс Чан Системное программирование на СИ++ для Unix. / Под ред. Коломыцева, Киев, 1997.
3. Э. Немет, Г. Снайдер Unix. Руководство системного администратора. – Киев: BHV, 1997.
4. Дегтярев Е.К. Введение в Unix. – М.: Память, 1992.
5. Свиридов С.В. Системные вызовы ОС UNIX. – М.: Память, 1992.
6. Страуструп Б. Язык программирования СИ++/ Пер с англ. – М.: Радио и связь, 1991.
7. Дунаев С. UNIX-сервер. Настройка, конфигурирование, работа в операционной среде, Internet-возможности: в 2-х томах. Том 1. – М.: Диалог-МИФИ, 1999.
8. Дунаев С. UNIX-сервер. Настройка, конфигурирование, работа в операционной среде, Internet-возможности: в 2-х томах. Том 2. – М.: Диалог-МИФИ, 1999.
9. Шамер Л., Негус К. UNIX (серия «Без проблем») / Пер. с англ. – М.: Бином, 1998.
10. Д. Такет, С. Барнет Специальное издание. Использование LINUX / Пер. с англ.-4-е изд. – К.:, Н.:, СПб.: Издательский дом «Вильямс», 1999.
Размещено на Allbest.ru
Программирование в ОС Федорова Н.В.
По теме: методические разработки, презентации и конспекты
![](/sites/default/files/pictures/2015/09/22/picture-625395-1442916469.jpg)
Учебно-методический комплекс учебной дисциплины "Иностранный язык" для подготовки по специальности СПО 260807"Технология продукции общественного питания"
Учебно -методический комплекс учебной дисциплины" Иностранный язык" предназначен для подготовки студентов 2-4 курса по специальности СПО "Технология продукции общественного питания" к самостоятельным ...
![](/sites/default/files/pictures/2015/09/22/picture-625395-1442916469.jpg)
Учебно-методический комплекс учебной дисциплины "Иностранный язык" для подготовки по специальности СПО 260807"Технология продукции общественного питания"
Учебно -методический комплекс учебной дисциплины" Иностранный язык" предназначен для подготовки студентов 2-4 курса по специальности СПО "Технология продукции общественного питания" к самостоятельным ...
![](/sites/default/files/pictures/2015/09/08/picture-663613-1441713249.jpg)
Методические рекомендации учебной дисциплины «Основы технического черчения» по выполнению внеаудиторной самостоятельной работы профессии35.01.13 «Тракторист- машинист сельскохозяйственного производства».
Методические рекомендации учебной дисциплины «Основы технического черчения» по выполнению внеаудиторной самостоятельной работы разработаны на основе Федерального государс...
![](/sites/default/files/pictures/2021/10/07/picture-531607-1633591867.jpg)
Учебно-методическое обеспечение учебной дисциплины Прикладная электроника
Учебно-методическое обеспечение учебной дисциплины Прикладная электроника...
Комплект контрольно-оценочных средств по учебной дисциплине Объектно-ориентированное программирование основной профессиональной образовательной программы по специальности СПО 230401 Информационные системы (по отраслям)
Комплект контрольно-оценочных средств разработан на основе Федерального государственного образовательного стандарта среднего профессионального образования по специальности СПО 230401 Инфор...
![](/sites/default/files/pictures/2013/01/04/picture-149271-1357311305.jpg)
Инновационные образовательные ресурсы в методическом обеспечении учебной дисциплины «Информатика и ИКТ»
Высокие темпы развития приводят к тому, что преподавателю приходится постоянно осваивать большой объем информации из различных источников, перерабатывать, выбирать главное и систематизировать. На осно...
![](/sites/default/files/pictures/2020/02/10/picture-1217328-1581328125.jpg)
Лекция по теме "Учебно – методический комплекспо учебным дисциплинам учителя начальных классов и начальных классов компенсирующего и коррекционно-развивающего образования"
Рассматриваются такие вопросы, как:1. Что такое методическая деятельность?2. Виды методической деятельности.3. Виды методических умений.4. И другое....