This commit is contained in:
nik
2025-10-01 22:52:39 +03:00
parent 52eacca48c
commit c10f32f1a5
25 changed files with 337 additions and 0 deletions

BIN
labs/lab2/assets/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
labs/lab2/assets/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
labs/lab2/assets/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
labs/lab2/assets/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
labs/lab2/assets/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
labs/lab2/assets/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
labs/lab2/assets/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
labs/lab2/assets/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
labs/lab2/assets/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
labs/lab2/assets/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

BIN
labs/lab2/assets/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

BIN
labs/lab2/report.pdf Normal file

Binary file not shown.

254
labs/lab2/report.typ Normal file
View File

@@ -0,0 +1,254 @@
#set text(size: 1.3em)
#show raw.where(block: false): box.with(
fill: luma(240),
inset: (x: 3pt, y: 0pt),
outset: (y: 3pt),
radius: 2pt,
)
#show raw.where(block: true): block.with(
fill: luma(240),
inset: 10pt,
radius: 4pt,
)
// title
#align(center)[Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики]
\
\
\
#align(center)[Факультет инфокоммуникационных технологий]
#align(center)[Направление подготовки 11.03.02]
\
\
#align(center)[Лабораторная работа №2]
#align(center)[Создание и использование размерных типов данных]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверил:]
#align(right)[Береснев Артем Дмитриевич]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]
#pagebreak()
=== Цель работы:
Получить практические навыки программирования на bash, освоить практические приемы работы с командной оболочкой bash.
=== Часть 1. Работа в среде bash.
Для изменения приглашения командной строки я отредактировал файл `~/.bashrc`, добавив туда строку:
```bash
PS1='\t \u \w \$ '
```
Теперь приглашение отображает текущее время, имя пользователя, текущий каталог и символ `$`.
#align(center)[#image("assets/1.png")]
Создал алиас для вывода приветствия:
```bash
alias hi='echo "Have a nice day, $(whoami)!"'
```
После этого при вводе команды `hi` в терминале появляется строка с приветствием и именем текущего пользователя.
#align(center)[#image("assets/2.png")]
Чтобы изменения сохранились при перезапуске, эти строки были добавлены в файл `~/.bashrc`. Применил изменения без выхода из системы командой:
```bash
source ~/.bashrc
```
=== Часть 2. Простые задачи на bash.
1. Принимает две строки как параметры и сравнивает их.
```bash
#!/bin/bash
[ "$#" -ne 2 ] && echo "usage: $0 str1 str2" && exit 1
[ "$1" = "$2" ] && echo "equal" || echo "not equal"
```
#align(center)[#image("assets/3.png")]
2. Принимает три целых числа и находит максимальное из них.
```bash
#!/bin/bash
[ "$#" -ne 3 ] && echo "usage: $0 a b c" && exit 1
a=$1
b=$2
c=$3
max=$a
(( b > max )) && max=$b
(( c > max )) && max=$c
echo "$max"
```
#align(center)[#image("assets/4.png")]
3. Считывает строки до тех пор, пока не встретится строка `q`. После завершения цикла все введённые строки объединяются и выводятся в одну строку.
```bash
#!/bin/bash
arr=()
while IFS= read -r line; do
[ "$line" = "q" ] && break
arr+=("$line")
done
printf "%s" "${arr[*]}"
```
#align(center)[#image("assets/5.png")]
4. Считывает последовательность целых чисел. Чтение продолжается, пока не встретится чётное число. После этого выводится количество введённых чисел до него.
```bash
#!/bin/bash
count=0
while IFS= read -r n; do
r=$(( n % 2 ))
[ "$r" -eq 0 ] && break
count=$(( count + 1 ))
done
echo "$count"
```
#align(center)[#image("assets/6.png")]
5. Создано текстовое меню с четырьмя пунктами: запуск редактора `nano`, редактора `vi`, браузера `links`, или выход. Перед выполнением команда `command -v` проверяет наличие программ. Если программа не установлена выводится сообщение и скрипт завершается.
```bash
#!/bin/bash
for cmd in nano vi links; do
command -v "$cmd" >/dev/null 2>&1 || { echo "$cmd is not installed"; exit 1; }
done
echo "1) nano"
echo "2) vi"
echo "3) links"
echo "4) exit"
read -r -p "choose 1-4: " choice
case "$choice" in
1) exec nano ;;
2) exec vi ;;
3) exec links ;;
4) exit 0 ;;
*) echo "invalid choice" ; exit 1 ;;
esac
```
#align(center)[#image("assets/7.png")]
#align(center)[#image("assets/8.png")]
6. Принимает три параметра: имя файла, режим (`h` или `t`), и число строк. В режиме `h` печатаются первые N строк файла (`head -n`). В режиме `t` последние N строк (`tail -n`). Ошибки при отсутствии файла подавляются перенаправлением `2>/dev/null`.
```bash
#!/bin/bash
[ "$#" -ne 3 ] && echo "usage: $0 file h|t N" && exit 1
file=$1
mode=$2
num=$3
case "$mode" in
h) head -n "$num" -- "$file" 2>/dev/null ;;
t) tail -n "$num" -- "$file" 2>/dev/null ;;
*) echo "mode must be h or t" ; exit 1 ;;
esac
```
#align(center)[#image("assets/6.png")]
=== Часть 3. Разработка скрипта расчета производительности.
1. В этой части требовалось написать скрипт `script23`, который измеряет производительность CPU в FLOPS (Floating Point Operations Per Second). Для этого необходимо было реализовать большое количество операций с плавающей запятой и зафиксировать время их выполнения.
2. Для вычислений использовалась утилита `bc`, так как она позволяет работать с произвольной точностью. В скрипте выставлена точность `scale=10`.
3. В скрипте организована функция `bench`, в которой выполняется $N$ умножений двух одинаковых чисел. Параметр $N$ можно передать в скрипт, по умолчанию используется 1 000 000.
4. С помощью команды `date +%s.%N` время сохраняется до и после выполнения функции. Далее определяется разница во времени и вычисляется показатель FLOPS по формуле:
$
F L O P S = frac(N, Delta t)
$
5. В завершении программа выводит три значения: количество итераций, время выполнения в секундах, и рассчитанный FLOPS.
```bash
#!/bin/bash
n=${1:-1000000}
command -v bc >/dev/null 2>&1 || { echo "bc is required"; exit 1; }
bench() {
printf 'scale=10\na=1.2345678901\nb=1.2345678901\nfor(i=0;i<%s;i++) x=a*b\n' "$n" | bc >/dev/null
}
start=$(date +%s.%N)
bench
end=$(date +%s.%N)
dur=$(echo "$end - $start" | bc -l)
flops=$(echo "$n / $dur" | bc -l)
printf "iterations=%s\ntime_s=%s\nFLOPS=%s\n" "$n" "$dur" "$flops"
```
#align(center)[#image("assets/10.png")]
=== Вопросы.
==== 1. Как определить сколько параметров пользователь передал в скрипт при запуске?
В bash для этого используется специальная переменная `$#`.
Она хранит количество аргументов, переданных скрипту.
Пример:
```bash
echo "amount of params: $#"
```
==== 2. Что выведет простой скрипт с постдекрементом?
Код:
```bash
count=10
echo $(( count-- ))
echo $(( count-- ))
```
#align(center)[#image("assets/11.png")]
Первая строка напечатает `10`, потому что оператор постдекремента возвращает старое значение, а потом уменьшает переменную. После этой операции `count=9`. Вторая строка напечатает `9` аналогично.
==== 3. Недостатки подхода к определению FLOPS в нашем скрипте
- Измеряется не только операция умножения, но и работа интерпретатора bash и программы `bc`.
- Не используется SIMD (векторные инструкции) и многопоточность, поэтому результат сильно занижен.
- Выполняется только умножение одинаковых чисел, что не отражает реальную работу CPU.
- На результат влияют другие процессы в системе, частота процессора, троттлинг, кэш.
- Такой метод больше демонстрационный и не сопоставим с эталонными тестами на C/Fortran.
=== Вывод.
В ходе проделанной работы я получил практические навыки программирования на bash, освоил практические приемы работы с командной оболочкой bash.

3
labs/lab2/scripts/q.sh Executable file
View File

@@ -0,0 +1,3 @@
count=10
echo $(( count-- ))
echo $(( count-- ))

3
labs/lab2/scripts/script221.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
[ "$#" -ne 2 ] && echo "usage: $0 str1 str2" && exit 1
[ "$1" = "$2" ] && echo "equal" || echo "not equal"

9
labs/lab2/scripts/script222.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
[ "$#" -ne 3 ] && echo "usage: $0 a b c" && exit 1
a=$1
b=$2
c=$3
max=$a
(( b > max )) && max=$b
(( c > max )) && max=$c
echo "$max"

8
labs/lab2/scripts/script223.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
arr=()
while IFS= read -r line; do
[ "$line" = "q" ] && break
arr+=("$line")
done
printf "%s" "${arr[*]} "

9
labs/lab2/scripts/script224.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
count=0
while IFS= read -r n; do
r=$(( n % 2 ))
[ "$r" -eq 0 ] && break
count=$(( count + 1 ))
done
echo "$count"

17
labs/lab2/scripts/script225.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
for cmd in nano vi links; do
command -v "$cmd" >/dev/null 2>&1 || { echo "$cmd is not installed"; exit 1; }
done
echo "1) nano"
echo "2) vi"
echo "3) links"
echo "4) exit"
read -r -p "choose 1-4: " choice
case "$choice" in
1) exec nano ;;
2) exec vi ;;
3) exec links ;;
4) exit 0 ;;
*) echo "invalid choice" ; exit 1 ;;
esac

11
labs/lab2/scripts/script226.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
[ "$#" -ne 3 ] && echo "usage: $0 file h|t N" && exit 1
file=$1
mode=$2
num=$3
case "$mode" in
h) head -n "$num" -- "$file" 2>/dev/null ;;
t) tail -n "$num" -- "$file" 2>/dev/null ;;
*) echo "mode must be h or t" ; exit 1 ;;
esac

17
labs/lab2/scripts/script23.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
n=${1:-1000000}
command -v bc >/dev/null 2>&1 || { echo "bc is required"; exit 1; }
bench() {
printf 'scale=10\na=1.2345678901\nb=1.2345678901\nfor(i=0;i<%s;i++) x=a*b\n' "$n" | bc >/dev/null
}
start=$(date +%s.%N)
bench
end=$(date +%s.%N)
dur=$(echo "$end - $start" | bc -l)
flops=$(echo "$n / $dur" | bc -l)
printf "iterations=%s\ntime_s=%s\nFLOPS=%s\n" "$n" "$dur" "$flops"

6
labs/lab2/scripts/test Normal file
View File

@@ -0,0 +1,6 @@
1
2
3
4
5
6

BIN
labs/lab2/task.pdf Normal file

Binary file not shown.

BIN
labs/lab3/task.pdf Normal file

Binary file not shown.

BIN
labs/lab4/task.pdf Normal file

Binary file not shown.