65828

Основы работы в среде операционной системы UNIX

Лабораторная работа

Информатика, кибернетика и программирование

Цель работы — изучение среды операционной системы (ОС) UNIX, возможностей программирования командного интерпретатора SHELL, а также принципов работы с неинтерактивным текстовым редактором SED.

Русский

2014-08-06

65.5 KB

0 чел.

Санкт-Петербургский государственный политехнический университет

Факультет технической кибернетики

—————————

Кафедра информационной безопасности компьютерных систем

ОТЧЕТ

по лабораторной работе №1

«Основы работы в среде операционной системы UNIX»

по курсу «Операционные системы»

Студент:

Никитин А. С.

гр. 2088/1

Преподаватель:

Степанова Т. В.

Санкт-Петербург — 2011

1. Формулировка задания

Цель работы — изучение среды операционной системы (ОС) UNIX, возможностей программирования командного интерпретатора SHELL, а также принципов работы с неинтерактивным текстовым редактором SED.

2. Использованные теоретические сведения

3. Результаты работы

3.1. Выполнение примеров

  1.  Выполнить создание, запуск и отладку программы, представленной в примере 1.
    Были созданы исходные файлы, представленные в примере. Для создания объектных файлов был использован компилятор
    gcc:
    gccc main.c
    gccc reciprocal.cpp
    Так как второй файл был написан на C++, то для связи объектных файлов и библиотек использовался компилятор g++:
    g++ -o reciprocal main.o reciprocal.o
    Запуск программы показал, что она была создана успешно:
    ./reciprocal 9
    The reciprocal of 9 is 0.111111
    Для проведения отладки программы на стадии компиляции в неё была добавлена служебная информация для отладчика. Это было выполнено компиляцией с ключом g:
    gccgc main.c
    gccgc reciprocal.cpp
    g++ -g -o reciprocal main.o reciprocal.o
    Затем отладчик был запущен командой gdb reciprocal.
    После запуска программы без параметров произошла ошибка сегментации. Команда where показала место ошибки:
    #0  0x002997bc in ?? () from /lib/tls/i686/cmov/libc.so.6
    #1  0
    x00299520 in strtol () from /lib/tls/i686/cmov/libc.so.6
    #2  0
    x00296891 in atoi () from /lib/tls/i686/cmov/libc.so.6
    #3  0
    x0804854d in main (argc=1, argv=0xbffff4a4) at main.c:6
    С помощью команды up 3 была найдена строка в файле main.c, которая привела к ошибке:
    #3  0x0804854d in main (argc=1, argv=0xbffff4a4) at main.c:6
    6  i = atoi(argv[1]);
    Для выяснения причины ошибки было просмотрено содержимое переменной argv[1]:
    print argv[1]
    $1 = 0
    x0
    Установка контрольной точки была выполнена командой break main.
    После запуска программа останавливается на первой строке файла
    main.c:
    run 9
    Starting program: /home/user/Share/labs/lab_1/example_1/reciprocal 9

    Breakpoint 1, main (argc=2, argv=0xbffff494) at main.c:6
    6  
    i = atoi(argv[1]);
    Далее были использованы команды, предназначенные для пошагового выполнения программы:
    next
    7  
    printf("The reciprocal of %d is %g\n", i, reciprocal(i));
    step
    reciprocal (i=9) at reciprocal.cpp:5
    5  
    assert(i != 0);
    continue
    Continuing.
    The reciprocal of 9 is 0.111111
    Program exited normally.
  2.  Выполнить создание makefile для проекта, представленного в примере 2, и генерацию исполняемого файла проекта под управлением утилиты make.
    Созданы файлы со следующим содержанием:
    main.с

    #include <stdio.h>
    int main(int argc, char *argv[]) {
    puts("main() from main.c");
    create();
    return 0;
    }

    create.c

    #include <stdio.h>

    void create() {
    puts("create() from create.c");
    update();
    return;
    }

    update.c

    #include <stdio.h>
    #include "update.h"

    void update() {
    puts(upd);
    return;
    }

    update.h

    #ifndef UPDATE
    #define UPDATE
    char *upd = "This string defined in update.h";
    #endif

    makefile

    CC= gcc
    LDFLAGS= -Wl,-Map,mapfile
    baseline: main.o create.o update.o
    $(
    CC) $(LDFLAGS) -o baseline main.o create.o update.o
    main.o: main.c
    create.o: create.c
    update.o: update.c update.h
    После запуска утилиты make была сгенерирована программа baseline. Запуск программы подтвердил её работоспособность:
    main() from main.c
    create() from create.c
    This string defined in update.h
  3.  Составить makefile для трансляции проекта, исходные файлы которого указаны в Табл.3.
    CC = gcc #компилятор
    FLAGS =  #флаги
    PROG = myprog #имя конечного файла
    TOOLLIB = ./tool  #директория библиотеки tool
    SUBDIRS = ./tool ./module1  #поддиректории, где есть makefile
    OBJDIRS = ./module1 #директории, где есть объектные файлы
       #необходимые для сборки проекта
    INCLUDE = -I./tool -I./module1 -I../include #директории с .h
    LIBFILES = ../lib/elib.a tool.a  #файлы библиотек
    OBJC = $(patsubst %.c, %.o, $(wildcard ./*.c)) #объектные файлы
            #получающиеся из *.
    c
    OBJS = $(patsubst %.s, %.o, $(wildcard ./*.s)) #объектные файлы
            #получающиеся из *.
    s
    OBJ = $(OBJC) $(OBJS)  #объектные файлы для удаления
    all: subdirs $(OBJ)
    $(
    CC) $(FLAGS) -o $(PROG) $(INCLUDE) $(LIBS) $(OBJ) $(foreach DIR, $(OBJDIRS), $(wildcard $(DIR)/*.o)) $(LIBFILES)
    fun1.o:
    $(
    CC) $(FLAGS) $(INCLUDE) -c fun1.c
    fun2.o:
    $(
    CC) $(FLAGS) $(INCLUDE) -c fun2.s
    main.o:
    $(
    CC) $(FLAGS) $(INCLUDE) -c main.c
    subdirs:
    for s in $(SUBDIRS);\
    do\
     
    cd $$s;\
     
    make;\
     
    cd ..;\
    done
    toollib:
    cd $(TOOLLIB);\
    make $@
    clean:
    @
    for o in $(OBJ);\
    do\
     
    rm -f $$o;\
    done;\
    for s in $(SUBDIRS);\
    do\
     
    cd $$s;\
     
    make $@;\
     
    cd ..;\
    done
    cleanall:
    @
    for o in $(OBJ);\
    do\
     
    rm -f $$o;\
    done;\
    for s in $(SUBDIRS);\
    do\
     
    cd $$s;\
     
    make $@;\
     
    cd ..;\
    done
    rm -f $(PROG)

    CC = gcc
    FLAGS =
    OBJ = $(patsubst %.c, %.o, $(wildcard ./*.c))
    LIB = tool.a
    toollib: tool_read.o tool_write.o
    ar -rv ../$(LIB) tool_read.o tool_write.o;\
    ranlib ../$(LIB)
    tool_read.o:
    $(
    CC) $(FLAGS) -c tool_read.c
    tool_write.o:
    $(
    CC) $(FLAGS) -c tool_write.c
    clean:
    @
    for o in $(OBJ);\
    do\
     
    rm -f $$o;\
    done
    cleanall: clean
    rm -f ../$(LIB)

    CC = gcc
    FLAGS =
    OBJ = $(patsubst %.c, %.o, $(wildcard ./*.c))
    all: mod11.o mod12.o
    mod11.o:
    $(
    CC) $(FLAGS) -c mod11.c
    mod12.o:
    $(
    CC) $(FLAGS) -c mod12.c
    clean:
    @
    for o in $(OBJ);\
    do\
     
    rm -f $$o;\
    done
    cleanall: clean

3.2. Выполнение индивидуального задания

  1.  Написать скрипт на языке shell, показывающий PID процесса, который использовал на данный момент процессорное время больше других процессов.
    ps h opid k-cputime -e | grep -m1 ""
    #вывод списка
    pid без заголовка с сортировкой по времени в порядке
    #убывания
    #вывод первой строки
  2.  Написать скрипт на языке shell, выполняющий периодический поиск и уничтожение всех процессов определенной программы, которые не превысили некоторый лимит времени исполнения (имя исполняемого файла программы и лимит времени должны являться параметрами скрипта).
    #TIME TIMEOUT PROGRAM
    while true
    do
    PS=$(ps otime,pid --no-heading -C $3) #
    получаем список процессов
    echo $PS
    PTYPE=0
    KILLFLAG=0
    for PARAM in $PS
    do
    if
    test $PTYPE = 0 #
    если текущий параметрвремя
    then     #
    переводим время в секунды
    HRS=$(echo $PARAM | grep -o -e '^[0-9][0-9]')
    PARAM=$(echo $PARAM | grep -o -e '[0-9][0-9]:[0-9][0-9]$')
    MIN=$(echo $PARAM | grep -o -e '^[0-9][0-9]')
    SEC=$(echo $PARAM | grep -o -e '[0-9][0-9]$')
    HRS=$(expr $HRS '*' 3600)
    MIN=$(expr $MIN '*' 60)
    TIME=$(expr $HRS + $MIN)
    TIME=$(expr $TIME + $SEC)
    echo $TIME
    if
     test $1 -ge $TIME #
    нужно ли убивать процесс?
    then
     KILLFLAG=1
    fi
    PTYPE=1
    else  #
    если параметр – pid
    if
     test $KILLFLAG = 1 #
    нужно ли убивать?
    then
     echo "Kill $PARAM"
     kill -9 $PARAM  #
    убить
    fi
    KILLFLAG=0
    PTYPE=0
    fi
    done
    sleep $2
    done
  3.  Разработать shell скрипт, использующий sed для анализа готового файла журнала аудита.
    sort -u $1 > temp.tmp  #сортировка записей по времени + удаление
        #
    повторяющихся записей
    sed -n '/login/p' temp.tmp  #
    вывод событий типа login
    sed -n '/logout/p' temp.tmp
    sed -n '/open/p' temp.tmp
    sed -n '/read/p' temp.tmp
    sed -n '/write/p' temp.tmp
    sed -n '/exec/p' temp.tmp
    echo users count
    USERS=$(sed -n '/^[^\t]*\t[^\t]*\t\([^\t]*\).*/s//\1/p' temp.tmp | sort -u) #
    составление списка пользователей
    for u in $USERS
    do
    echo $u
    sed -n '/^[^\t]*\t[^\t]*\t\([^\t]*\).*/s//\1/p' temp.tmp | grep -c $u #
    подсчёт количества команд пользователя
    done
    echo days count
    sed -n '/^\([^\t]*\).*/s//\1/p' temp.tmp | sort -u | grep -c ""
     #
    подсчёт различных дней
    echo logout count
    sed -n '/logout/p' temp.tmp | grep -c "" #
    подсчёт событий logout
    rm -f temp.tmp
  4.  Используя редактор SED и скриптовый язык SHELL, разработать программу, которая осуществляет просмотр текущего каталога и выводит на экран его содержимое группами в порядке уменьшения числа ссылок на файлы (в том числе имена каталогов).
    ls -l | sed -n '2,$'p | sort -rk2,2
    #вывод списка файлов
    #первая строка вывода не относится к файлам, её надо убрать
    #сортировка в обратном порядке по второму полю (кол-во ссылок)

3.3. Ответы на контрольные вопросы

  1.  Чем отличаются команды вида: lsli, lsil, lsil, lsli ?
    Ничем, кроме варианта записи опций.
  2.  Каким образом можно ввести новую или удалить существующую переменную среды окружения для текущего сенса shell?
    С помощью команды
    export имяпеременной=значение или set имяпеременной=значение можно задать новую пременную, с помощью unset имяпеременной можно удалить переменную.
  3.  Для чего служат конструкции $#, $* и &&?
    $# - переменная, содержащая число параметров, переданных при запуске текущему сеансу
    shell.
    $* - переменная, эквивалентная строке вида "$1 $2 $3 ..."
    && - оператор, служащий для последовательного выполнения команд. При этом следующая команда выполняется только при завершении предыдущей команды без ошибок (код завершения равен нулю).

4. Выводы

Shell – достаточно мощный командный интерпретатор, позволяющий писать простые скрипты для выполнения определённых заданий.
Утилита
make облегчает программирование в ОС UNIX, так как при грамотно написанном makefile достаточно одной команды для построения новой версии программы.
Редактор
sed позволяет значительно расширить возможности для обработки файлов в shell-скриптах путём использования регулярных выражений и достаточно широкого выбора команд редактирования.

Приложение 

Исходные тексты программ