diff --git a/semester-4/ОС/lb-6/README.md b/semester-4/ОС/lb-6/README.md new file mode 100644 index 0000000..03a2c87 --- /dev/null +++ b/semester-4/ОС/lb-6/README.md @@ -0,0 +1,7 @@ +> [!NOTE] +> Викладач: Мельникова Р. В. +> +> Оцінка: - + +> [!TIP] +> Виконано для Linux в команді. diff --git a/semester-4/ОС/lb-6/doc.yaml b/semester-4/ОС/lb-6/doc.yaml new file mode 100644 index 0000000..a963875 --- /dev/null +++ b/semester-4/ОС/lb-6/doc.yaml @@ -0,0 +1,21 @@ +title: Керування пам'яттю. Частина 2 +subject: ОС +doctype: ЛБ +worknumber: 6 +mentors: + - name: Мельнікова Р. В., + gender: f, + degree: доц. каф. ПІ, +edu_program: &EDU ПЗПІ +university: ХНУРЕ +authors: + - name: Ситник Є. С. + course: 2 + edu: *EDU + gender: m + group: 23-2 + - name: Малишкін. А. С. + course: 2 + edu: *EDU + gender: m + group: 23-2 diff --git a/semester-4/ОС/lb-6/img/cache-lru.png b/semester-4/ОС/lb-6/img/cache-lru.png new file mode 100644 index 0000000..7b3e8fb Binary files /dev/null and b/semester-4/ОС/lb-6/img/cache-lru.png differ diff --git a/semester-4/ОС/lb-6/img/cache-result.png b/semester-4/ОС/lb-6/img/cache-result.png new file mode 100644 index 0000000..d949d69 Binary files /dev/null and b/semester-4/ОС/lb-6/img/cache-result.png differ diff --git a/semester-4/ОС/lb-6/img/cache-test.png b/semester-4/ОС/lb-6/img/cache-test.png new file mode 100644 index 0000000..5291045 Binary files /dev/null and b/semester-4/ОС/lb-6/img/cache-test.png differ diff --git a/semester-4/ОС/lb-6/img/pages-clock.png b/semester-4/ОС/lb-6/img/pages-clock.png new file mode 100644 index 0000000..e12b99d Binary files /dev/null and b/semester-4/ОС/lb-6/img/pages-clock.png differ diff --git a/semester-4/ОС/lb-6/img/pages-lru.png b/semester-4/ОС/lb-6/img/pages-lru.png new file mode 100644 index 0000000..330093f Binary files /dev/null and b/semester-4/ОС/lb-6/img/pages-lru.png differ diff --git a/semester-4/ОС/lb-6/img/pages-optimal.png b/semester-4/ОС/lb-6/img/pages-optimal.png new file mode 100644 index 0000000..2c8d08e Binary files /dev/null and b/semester-4/ОС/lb-6/img/pages-optimal.png differ diff --git a/semester-4/ОС/lb-6/img/pages-result.png b/semester-4/ОС/lb-6/img/pages-result.png new file mode 100644 index 0000000..7e0c917 Binary files /dev/null and b/semester-4/ОС/lb-6/img/pages-result.png differ diff --git a/semester-4/ОС/lb-6/img/pages-test.png b/semester-4/ОС/lb-6/img/pages-test.png new file mode 100644 index 0000000..daa4a4d Binary files /dev/null and b/semester-4/ОС/lb-6/img/pages-test.png differ diff --git a/semester-4/ОС/lb-6/img/pass-check.png b/semester-4/ОС/lb-6/img/pass-check.png new file mode 100644 index 0000000..7b643c6 Binary files /dev/null and b/semester-4/ОС/lb-6/img/pass-check.png differ diff --git a/semester-4/ОС/lb-6/img/pass-hash.png b/semester-4/ОС/lb-6/img/pass-hash.png new file mode 100644 index 0000000..75457ec Binary files /dev/null and b/semester-4/ОС/lb-6/img/pass-hash.png differ diff --git a/semester-4/ОС/lb-6/img/pass-lock.png b/semester-4/ОС/lb-6/img/pass-lock.png new file mode 100644 index 0000000..b37efa8 Binary files /dev/null and b/semester-4/ОС/lb-6/img/pass-lock.png differ diff --git a/semester-4/ОС/lb-6/img/pass-table.png b/semester-4/ОС/lb-6/img/pass-table.png new file mode 100644 index 0000000..bd3774a Binary files /dev/null and b/semester-4/ОС/lb-6/img/pass-table.png differ diff --git a/semester-4/ОС/lb-6/src/.clangd b/semester-4/ОС/lb-6/src/.clangd new file mode 100644 index 0000000..5273bda --- /dev/null +++ b/semester-4/ОС/lb-6/src/.clangd @@ -0,0 +1,17 @@ +CompileFlags: + Add: [-Wall, -Wextra, -std=c++23, -DBUILD_SHARED] + CompilationDatabase: build/ + +Diagnostics: + UnusedIncludes: Strict + +InlayHints: + Enabled: Yes + ParameterNames: Yes + DeducedTypes: Yes + +Index: + Background: Build + +Hover: + ShowAKA: Yes diff --git a/semester-4/ОС/lb-6/src/Makefile b/semester-4/ОС/lb-6/src/Makefile new file mode 100644 index 0000000..f2fb18a --- /dev/null +++ b/semester-4/ОС/lb-6/src/Makefile @@ -0,0 +1,15 @@ +CXX := clang++ +CXXFLAGS := -std=c++23 -Iinclude -Wall -Wextra +LDFLAGS := -lcrypto + +TARGET := build/app +SRC := main.cpp + +.PHONY: all clean + +all: + @mkdir -p $(dir $(TARGET)) + @$(CXX) $(CXXFLAGS) $(SRC) -o $(TARGET) $(LDFLAGS) + +clean: + rm -rf build diff --git a/semester-4/ОС/lb-6/src/include/cache.hpp b/semester-4/ОС/lb-6/src/include/cache.hpp new file mode 100644 index 0000000..9adb821 --- /dev/null +++ b/semester-4/ОС/lb-6/src/include/cache.hpp @@ -0,0 +1,37 @@ +#pragma once + +#ifndef CACHE_LRU_HPP + #define CACHE_LRU_HPP + + #include + #include + #include + #include + +namespace cache { + +class lru { +public: + lru(int32_t line_count, int32_t associativity); + ~lru() = default; + + bool access(uint64_t address); + +private: + struct block_entry { + uint64_t tag; + }; + + int32_t _lines; + int32_t _assoc; + + std::vector> _cache_lines; + std::vector::iterator>> + _lookup; +}; + +} // namespace cache + + #include "../src/cache.cpp" + +#endif diff --git a/semester-4/ОС/lb-6/src/include/locked_buffer.hpp b/semester-4/ОС/lb-6/src/include/locked_buffer.hpp new file mode 100644 index 0000000..ee7d7bf --- /dev/null +++ b/semester-4/ОС/lb-6/src/include/locked_buffer.hpp @@ -0,0 +1,84 @@ +#pragma once + +#ifndef SEC_LOCKED_BUFFER_HPP + #define SEC_LOCKED_BUFFER_HPP + + #include + #include + #include + #include + #include + +namespace sec { + +template class locked_buffer { +public: + locked_buffer() { + this->size_ = N * sizeof(T); + this->ptr_ = static_cast(std::malloc(this->size_)); + if (!this->ptr_) + throw std::bad_alloc(); + if (mlock(this->ptr_, this->size_) != 0) { + std::free(this->ptr_); + throw std::runtime_error("mlock failed"); + } + } + + ~locked_buffer() noexcept { + cleanse(); + if (this->ptr_) { + munlock(this->ptr_, this->size_); + std::free(this->ptr_); + } + } + + locked_buffer(const locked_buffer &) = delete; + locked_buffer &operator=(const locked_buffer &) = delete; + + locked_buffer(locked_buffer &&other) noexcept + : ptr_(other.ptr_), size_(other.size_) { + other.ptr_ = nullptr; + other.size_ = 0; + } + + locked_buffer &operator=(locked_buffer &&other) noexcept { + if (this != &other) { + cleanse(); + if (this->ptr_) { + munlock(this->ptr_, this->size_); + std::free(this->ptr_); + } + this->ptr_ = other.ptr_; + this->size_ = other.size_; + other.ptr_ = nullptr; + other.size_ = 0; + } + return *this; + } + + T *data() noexcept { return this->ptr_; } + const T *data() const noexcept { return this->ptr_; } + std::size_t size() const noexcept { return N; } + + T &operator[](std::size_t i) { return this->ptr_[i]; } + const T &operator[](std::size_t i) const { return this->ptr_[i]; } + + T *begin() noexcept { return this->ptr_; } + T *end() noexcept { return this->ptr_ + N; } + const T *begin() const noexcept { return this->ptr_; } + const T *end() const noexcept { return this->ptr_ + N; } + +private: + void cleanse() noexcept { + if (this->ptr_) { + std::memset(this->ptr_, 0, this->size_); + } + } + + T *ptr_{nullptr}; + std::size_t size_{0}; +}; + +} // namespace sec + +#endif diff --git a/semester-4/ОС/lb-6/src/include/paging.hpp b/semester-4/ОС/lb-6/src/include/paging.hpp new file mode 100644 index 0000000..8cc60df --- /dev/null +++ b/semester-4/ОС/lb-6/src/include/paging.hpp @@ -0,0 +1,44 @@ +#pragma once + +#ifndef PAGE_REPLACEMENT_HPP + #define PAGE_REPLACEMENT_HPP + + #include + #include + +namespace paging { + +class replacer { +public: + explicit replacer(int32_t frame_count) : _frames(frame_count) {} + virtual ~replacer() = default; + + virtual int32_t run(const std::vector &pages) = 0; + +protected: + int32_t _frames; +}; + +class optimal_replacer : public replacer { +public: + using replacer::replacer; + int32_t run(const std::vector &pages) override; +}; + +class clock_replacer : public replacer { +public: + using replacer::replacer; + int32_t run(const std::vector &pages) override; +}; + +class lru_replacer : public replacer { +public: + using replacer::replacer; + int32_t run(const std::vector &pages) override; +}; + +} // namespace paging + + #include "../src/paging.cpp" + +#endif diff --git a/semester-4/ОС/lb-6/src/include/password.hpp b/semester-4/ОС/lb-6/src/include/password.hpp new file mode 100644 index 0000000..623bdbe --- /dev/null +++ b/semester-4/ОС/lb-6/src/include/password.hpp @@ -0,0 +1,68 @@ +#pragma once + +#ifndef PASSWORD_HPP + #define PASSWORD_HPP + + #include + #include + #include + + #include "locked_buffer.hpp" + +namespace sec { + +enum class strength_t : uint8_t { + very_weak = 0, + weak, + moderate, + strong, + very_strong +}; + +class password_hash; + +class password { +public: + explicit password(std::string pass); + + std::string_view view() const noexcept; + + static sec::password from_console(); + static sec::password from_string(const std::string &pass); + + sec::password_hash to_hash() const; + +private: + sec::locked_buffer _buf; + std::size_t _len{}; +}; + +class password_hash { +public: + explicit password_hash(std::string hash); + const std::string &get() const noexcept; + + bool verify(const sec::password &pwd) const; + +private: + std::string _hash; +}; + +class manager { +public: + static bool has_lower(const sec::password &pwd); + static bool has_upper(const sec::password &pwd); + static bool has_digit(const sec::password &pwd); + static bool has_spec_symbol(const sec::password &pwd); + + static std::string hash_password(const sec::password &pwd); + static sec::strength_t evaluate_strength(const sec::password &pwd); + static uint64_t time_to_crack(const sec::password &pwd); + static std::string format_duration(uint64_t seconds); +}; + +} // namespace sec + + #include "../src/password.cpp" + +#endif diff --git a/semester-4/ОС/lb-6/src/main.cpp b/semester-4/ОС/lb-6/src/main.cpp new file mode 100644 index 0000000..e38f140 --- /dev/null +++ b/semester-4/ОС/lb-6/src/main.cpp @@ -0,0 +1,73 @@ +#include +#include +#include + +#include "include/cache.hpp" +#include "include/paging.hpp" +#include "include/password.hpp" + +#include + +int main() { + std::vector pages = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3}; + int frames = 3; + + paging::optimal_replacer opt(frames); + paging::clock_replacer clk(frames); + paging::lru_replacer lru(frames); + + std::println("Optimal faults: {}", opt.run(pages)); + std::println("Clock faults: {}", clk.run(pages)); + std::println("LRU faults: {}", lru.run(pages)); + + std::println("\nCache LRU Simulation:"); + cache::lru cache(128, 4); + std::vector addresses = { + 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, + }; + int32_t hits = 0, misses = 0; + for (auto addr : addresses) { + if (cache.access(addr)) { + ++hits; + std::println("Address 0x{:x}:\t HIT", addr); + } else { + ++misses; + std::println("Address 0x{:x}:\t MISS", addr); + } + } + std::println("Hits: {}, Misses: {}\n", hits, misses); + + auto pwd = sec::password::from_console(); + auto strength = sec::manager::evaluate_strength(pwd); + auto crack_time = sec::manager::time_to_crack(pwd); + auto crack_str = sec::manager::format_duration(crack_time); + + std::print("Password strength: "); + switch (strength) { + case sec::strength_t::very_weak: + std::print("Very Weak"); + break; + case sec::strength_t::weak: + std::print("Weak"); + break; + case sec::strength_t::moderate: + std::print("Moderate"); + break; + case sec::strength_t::strong: + std::print("Strong"); + break; + case sec::strength_t::very_strong: + std::print("Very Strong"); + break; + } + std::print("\nEstimated time to crack: {} secs\n({})\n", crack_time, + crack_str); + + std::string input; + std::print("\nEnter password to verify: "); + std::getline(std::cin, input); + auto input_pwd = sec::password::from_string(input); + if (pwd.to_hash().verify(input_pwd)) { + std::print("Password verified successfully.\n"); + } +} diff --git a/semester-4/ОС/lb-6/src/src/cache.cpp b/semester-4/ОС/lb-6/src/src/cache.cpp new file mode 100644 index 0000000..2c5b8bd --- /dev/null +++ b/semester-4/ОС/lb-6/src/src/cache.cpp @@ -0,0 +1,38 @@ +#pragma once + +#include "../include/cache.hpp" + +#include + +namespace cache { + +cache::lru::lru(int32_t line_count, int32_t associativity) + : _lines(line_count), _assoc(associativity), _cache_lines(line_count), + _lookup(line_count) {} + +bool cache::lru::access(uint64_t address) { + uint64_t line = (address >> 6) % this->_lines; + uint64_t tag = + address >> (6 + static_cast(std::log2(this->_lines))); + + auto &line_list = this->_cache_lines[line]; + auto &line_map = this->_lookup[line]; + + auto it = line_map.find(tag); + if (it != line_map.end()) { + line_list.splice(line_list.begin(), line_list, it->second); + line_map[tag] = line_list.begin(); + return true; + } + + if (static_cast(line_list.size()) >= this->_assoc) { + auto last = line_list.back(); + line_map.erase(last.tag); + line_list.pop_back(); + } + line_list.push_front({tag}); + line_map[tag] = line_list.begin(); + return false; +} + +} // namespace cache diff --git a/semester-4/ОС/lb-6/src/src/paging.cpp b/semester-4/ОС/lb-6/src/src/paging.cpp new file mode 100644 index 0000000..7876dc9 --- /dev/null +++ b/semester-4/ОС/lb-6/src/src/paging.cpp @@ -0,0 +1,115 @@ +#pragma once + +#include "../include/paging.hpp" + +#include +#include +#include +#include + +namespace paging { + +int32_t paging::optimal_replacer::run(const std::vector &pages) { + int32_t faults = 0; + std::vector frames; + frames.reserve(static_cast(this->_frames)); + for (size_t i : std::views::iota(size_t(0), pages.size())) { + int32_t p = pages[i]; + if (std::find(frames.begin(), frames.end(), p) != frames.end()) + continue; + ++faults; + if (static_cast(frames.size()) < this->_frames) { + frames.push_back(p); + } else { + int32_t idx_to_replace = 0; + size_t farthest = 0; + for (int32_t j : std::views::iota(0, this->_frames)) { + size_t k = i + 1; + while (k < pages.size() && pages[k] != frames[j]) + ++k; + size_t dist = + (k < pages.size() ? k : std::numeric_limits::max()); + if (dist > farthest) { + farthest = dist; + idx_to_replace = j; + } + } + frames[idx_to_replace] = p; + } + } + return faults; +} + +int32_t paging::clock_replacer::run(const std::vector &pages) { + int32_t faults = 0; + struct entry { + int32_t page; + bool ref; + }; + std::vector frames; + frames.reserve(static_cast(this->_frames)); + int32_t hand = 0; + + for (int32_t p : pages) { + bool hit = false; + for (auto &e : frames) { + if (e.page == p) { + e.ref = true; + hit = true; + break; + } + } + if (hit) + continue; + ++faults; + if (static_cast(frames.size()) < this->_frames) { + frames.push_back({p, true}); + } else { + while (true) { + if (!frames[hand].ref) { + frames[hand] = {p, true}; + hand = (hand + 1) % this->_frames; + break; + } + frames[hand].ref = false; + hand = (hand + 1) % this->_frames; + } + } + } + return faults; +} + +int32_t paging::lru_replacer::run(const std::vector &pages) { + int32_t faults = 0; + std::vector frames; + std::unordered_map last_used; + frames.reserve(static_cast(this->_frames)); + + for (int32_t i : std::views::iota(0, static_cast(pages.size()))) { + int32_t p = pages[i]; + if (std::find(frames.begin(), frames.end(), p) != frames.end()) { + last_used[p] = i; + continue; + } + ++faults; + if (static_cast(frames.size()) < this->_frames) { + frames.push_back(p); + } else { + int32_t lru_page = frames[0]; + int32_t min_idx = last_used[lru_page]; + for (int32_t q : frames) { + if (last_used[q] < min_idx) { + min_idx = last_used[q]; + lru_page = q; + } + } + auto it = std::find(frames.begin(), frames.end(), lru_page); + if (it != frames.end()) + *it = p; + } + last_used[p] = i; + } + return faults; +} + +} // namespace paging diff --git a/semester-4/ОС/lb-6/src/src/password.cpp b/semester-4/ОС/lb-6/src/src/password.cpp new file mode 100644 index 0000000..f270a51 --- /dev/null +++ b/semester-4/ОС/lb-6/src/src/password.cpp @@ -0,0 +1,151 @@ +#pragma once + +#include "../include/password.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sec { + +sec::password::password(std::string pass) { + if (pass.size() > _buf.size()) { + throw std::length_error("Password too long"); + } + _len = pass.size(); + std::copy(pass.data(), pass.data() + _len, _buf.begin()); +} + +std::string_view sec::password::view() const noexcept { + return std::string_view(_buf.data(), _len); +} + +sec::password sec::password::from_console() { + std::string p1, p2; + while (true) { + std::print("Enter password: "); + std::getline(std::cin, p1); + std::print("Re-enter password: "); + std::getline(std::cin, p2); + if (p1 != p2) { + std::print("Passwords do not match. Try again.\n"); + continue; + } + if (sec::manager::evaluate_strength(sec::password(p1)) == + sec::strength_t::very_weak) { + std::print("Password is too weak. Try again.\n"); + continue; + } + break; + } + return sec::password(p1); +} + +sec::password sec::password::from_string(const std::string &pass) { + if (sec::manager::evaluate_strength(sec::password(pass)) == + sec::strength_t::very_weak) { + std::print("Password is too weak. Try again.\n\n"); + throw std::invalid_argument("Weak password"); + } + return sec::password(pass); +} + +sec::password_hash::password_hash(std::string hash) : _hash(std::move(hash)) {} + +const std::string &sec::password_hash::get() const noexcept { return _hash; } + +bool sec::password_hash::verify(const sec::password &pwd) const { + return sec::manager::hash_password(pwd) == _hash; +} + +sec::password_hash sec::password::to_hash() const { + return sec::password_hash(sec::manager::hash_password(*this)); +} + +bool sec::manager::has_lower(const sec::password &pwd) { + auto sv = pwd.view(); + return std::any_of(sv.begin(), sv.end(), ::islower); +} + +bool sec::manager::has_upper(const sec::password &pwd) { + auto sv = pwd.view(); + return std::any_of(sv.begin(), sv.end(), ::isupper); +} + +bool sec::manager::has_digit(const sec::password &pwd) { + auto sv = pwd.view(); + return std::any_of(sv.begin(), sv.end(), ::isdigit); +} + +bool sec::manager::has_spec_symbol(const sec::password &pwd) { + auto sv = pwd.view(); + return std::any_of(sv.begin(), sv.end(), + [](unsigned char c) { return std::ispunct(c); }); +} + +sec::strength_t sec::manager::evaluate_strength(const sec::password &pwd) { + uint8_t score = 0; + + if (has_lower(pwd)) + ++score; + if (has_upper(pwd)) + ++score; + if (has_digit(pwd)) + ++score; + if (has_spec_symbol(pwd)) + ++score; + if (pwd.view().size() >= 8) + ++score; + + if (score != 0) + score--; + + uint8_t max_val = static_cast(sec::strength_t::very_strong); + uint8_t idx = std::min(score, max_val); + + return static_cast(idx); +} + +uint64_t sec::manager::time_to_crack(const sec::password &pwd) { + auto sv = pwd.view(); + if (sv.empty()) + return 0; + int charset = (has_lower(pwd) ? 26 : 0) + (has_upper(pwd) ? 26 : 0) + + (has_digit(pwd) ? 10 : 0) + (has_spec_symbol(pwd) ? 33 : 0); + constexpr double RATE = 1e7; + double combos = std::pow(static_cast(charset), sv.size()); + return static_cast(combos / 2.0 / RATE); +} + +std::string sec::manager::format_duration(uint64_t seconds) { + const uint64_t u[] = {31536000, 2592000, 86400, 3600, 60, 1}; + const char *lbl[] = {"years", "months", "days", "hours", "mins", "secs"}; + std::string s; + for (int i : std::views::iota(0, 6)) { + uint64_t v = seconds / u[i]; + if (v) { + s += std::to_string(v) + " " + lbl[i] + ((i == 5) ? "" : " "); + seconds %= u[i]; + } + } + return s.empty() ? "0 secs" : s; +} + +std::string sec::manager::hash_password(const sec::password &pwd) { + auto sv = pwd.view(); + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256(reinterpret_cast(sv.data()), sv.size(), hash); + std::ostringstream oss; + for (int32_t i : std::views::iota(0, SHA256_DIGEST_LENGTH)) { + oss << std::hex << std::setw(2) << std::setfill('0') + << static_cast(hash[i]); + } + return oss.str(); +} + +} // namespace sec diff --git a/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.pdf b/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.pdf new file mode 100644 index 0000000..613619c Binary files /dev/null and b/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.pdf differ diff --git a/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.typ b/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.typ new file mode 100644 index 0000000..935116d --- /dev/null +++ b/semester-4/ОС/lb-6/Лр_6_Ситник_Малишкін_ПЗПІ_23_2.typ @@ -0,0 +1,60 @@ +#import "@local/nure:0.1.0": * + +#show: pz-lb.with(..yaml("doc.yaml")) + +#v(-spacing) + +== Мета роботи +Вивчити особливості захисту критичних даних, використання динамічної та кеш пам'яті. + +== Хід роботи +#v(-spacing) +=== Порівняти алгоритми заміщення сторінок (оптимальний, годинник, LRU). +Заміщення сторінок - це процес, який використовується в операційних системах для керування віртуальною пам'яттю, коли фізичної пам'яті недостатньо. Коли потрібна сторінка, якої немає в оперативній пам'яті, операційна система вибирає одну зі сторінок, що вже знаходяться в пам'яті, і замінює її потрібною сторінкою. + +Сучасні операційні системи використовують різні підходи для визначення сторінок, які можна замістити. + +Розглянемо деякі алгоритми заміщення сторінок: ++ оптимальний алгоритм (також відомий як алгоритм Беладі) -- теоретичний алгоритм, який досягає найменшої кількості промахів сторінок. Він працює, замінюючи сторінку, яка не буде використовуватися найдовший період часу в майбутньому. Хоча цей алгоритм є оптимальним, він не може бути реалізований на практиці, оскільки вимагає знання майбутньої послідовності звернень до сторінок; ++ алгоритм годинник (також відомий як алгоритм "другого шансу") -- зберігає список сторінок у пам'яті, кожна з яких має біт використання. Коли відбувається промах сторінки і потрібно замінити сторінку, алгоритм перевіряє біт використання поточної сторінки, на яку вказує покажчик. Якщо біт використання дорівнює 1, він скидається до 0, і покажчик переміщується до наступної сторінки. Цей процес повторюється до тих пір, поки не буде знайдено сторінку з бітом використання, що дорівнює 0, яка і замінюється. Такий підхід надає "другий шанс" сторінкам, які нещодавно використовувалися, запобігаючи їхньому швидкому витісненню; ++ алгоритм LRU (Least Recently Used) -- замінює сторінку, яка найдовше не використовувалася. Він базується на припущенні, що сторінки, які використовувалися нещодавно, ймовірно, будуть використовуватися знову в найближчому майбутньому, а ті, що давно не використовувалися, мають меншу ймовірність повторного звернення. Для реалізації LRU необхідно відстежувати час останнього звернення до кожної сторінки в пам'яті. Коли виникає потреба у заміщенні, вибирається сторінка з найдавнішим часом останнього використання. + +#figure(image("img/pages-optimal.png", width: 90%), caption: [Оптимальний алгоритм заміщення сторінок]) +#figure(image("img/pages-clock.png", width: 100%), caption: [Алгоритм заміщення сторінок "Годинник"]) +#figure(image("img/pages-lru.png", width: 80%), caption: [Алгоритм заміщення сторінок "LRU"]) + +Протестуємо всі алгоритми із однаковими тестовими даними. + +#figure(image("img/pages-test.png", width: 80%), caption: [Код тестування алгоритмів]) + +#figure(image("img/pages-result.png"), caption: [Результати тестування]) + +Можемо побачити, що оптимальний алгоритм показує найкращі результати. + +=== Реалізувати алгоритм LRU для роботи з кешем для стандартних параметрів кешу +Кешування - це техніка збереження часто використовуваних даних у швидшій пам'яті (кеші) для зменшення часу доступу. Оскільки кеш має обмежений розмір, при його заповненні виникає потреба у визначенні того, які дані слід видалити для звільнення місця для нових. + +#figure(image("img/cache-lru.png", width: 87%), caption: [Алгоритм "LRU" для доступу до кешу]) +#figure(image("img/cache-test.png", width: 90%), caption: [Код тестування]) +#figure(image("img/cache-result.png", width: 45%), caption: [Результати тестування]) + +=== Реалізувати функції встановлення паролю та перевірки паролю. При складанні функцій забезпечте безпечне зберігання паролів. + +Безпечність пароля можна визначити за часом, що потрібен для його зламу. Чим більше часу необхідно на злам, тим безпечніший пароль. +#figure( + image("img/pass-table.png", width: 70%), + caption: [Таблиця відповідності складності паролю до часу, що необхідний на злам], +) +Критерії надійності паролю зазначені в таблиці детально обговорюються в дослідженні Hive Systems, яке оновлюється кожен рік починаючи з 2020 (#link("https://www.hivesystems.com/blog/are-your-passwords-in-the-green")) +#figure(image("img/pass-check.png", width: 70%), caption: [Функція перевірки надійності пароля]) + +Для забезпечення безпеки пароля в пам'яті під час гешування було використано стандартні POSIX функції "mlock" та "munlock". +#figure(image("img/pass-lock.png", width: 74%), caption: [Функції блокування та розблокування пам'яті]) + +Для гешування паролю ми використали алгоритм "SHA256" із бібліотеки "openssl", яка є стандартним вибором для всього, що так чи інакше пов'язано із криптографією. +#figure(image("img/pass-hash.png", width: 74%), caption: [Функція гешування паролю]) + +== Висновки +Під час даної лабораторної роботи ми вивчили особливості захисту критичних даних, використання динамічної та кеш пам'яті. + +#show: appendices_style