Загрузка данных


Вот полный план от начала до конца. Просто копируй команды по очереди в терминал.

**ЧАСТЬ 1. Подготовка папки**

```
mkdir -p ~/lab5_threads
cd ~/lab5_threads
```

**ЧАСТЬ 2. Проверка что есть gcc и gdb**

```
which gcc
which gdb
```

Если что-то не найдено, ставим:

```
sudo apt update
sudo apt install gcc gdb build-essential
```

**ЧАСТЬ 3. Задание 1 — bash скрипт monitor_system.sh**

Создаем файл:

```
nano monitor_system.sh
```

Вставляем туда этот код:

```
#!/bin/bash
echo "Системный монитор"

monitor_processes() {
    while true; do
        clear
        echo "Системный монитор"
        echo "Время: $(date '+%Y-%m-%d %H:%M:%S')"
        echo
        echo "--- Топ-5 процессов по CPU ---"
        ps aux --sort=-%cpu | head -6
        echo
        echo "--- Топ-5 процессов по RAM ---"
        ps aux --sort=-%mem | head -6
        echo
        echo "Всего процессов: $(ps -e | wc -l)"
        sleep 2
    done
}

monitor_processes &
MONITOR_PID=$!
echo "PID фонового процесса: $MONITOR_PID"
echo "Нажмите Ctrl+C для остановки"

trap 'kill $MONITOR_PID > /dev/null 2>&1; echo "Мониторинг остановлен"; exit 0' SIGINT

wait $MONITOR_PID
```

Сохраняем: Ctrl+O, Enter, Ctrl+X.

Делаем исполняемым и запускаем:

```
chmod +x monitor_system.sh
./monitor_system.sh
```

Смотришь как обновляется экран каждые 2 секунды. Жмешь Ctrl+C. Должно написать "Мониторинг остановлен".

**ЧАСТЬ 4. Задание 2 — C программа с потоками**

Создаем файл:

```
nano thread_demo.c
```

Вставляем код:

```
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>

#define NUM_THREADS 3
#define NUM_ITERATIONS 5

typedef struct {
    int thread_id;
} thread_data_t;

void* worker_thread(void* arg) {
    thread_data_t* data = (thread_data_t*)arg;
    pid_t tid = syscall(SYS_gettid);
    
    printf("Поток %d запущен. PID: %d, TID: %ld\n",
           data->thread_id, getpid(), (long)tid);
    
    for (int i = 0; i < NUM_ITERATIONS; i++) {
        printf("Поток %d: шаг %d\n", data->thread_id, i);
        sleep(1);
    }
    
    printf("Поток %d завершен\n", data->thread_id);
    pthread_exit(NULL);
}

int main() {
    printf("=== Демонстрация работы потоков ===\n");
    printf("Основной процесс PID: %d\n", getpid());
    
    pthread_t threads[NUM_THREADS];
    thread_data_t thread_data[NUM_THREADS];
    
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_data[i].thread_id = i;
        int result = pthread_create(&threads[i], NULL, worker_thread, &thread_data[i]);
        if (result != 0) {
            fprintf(stderr, "Ошибка создания потока %d: %d\n", i, result);
            exit(EXIT_FAILURE);
        }
    }
    
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    printf("Все потоки завершены\n");
    return 0;
}
```

Сохраняем: Ctrl+O, Enter, Ctrl+X.

**ЧАСТЬ 5. Компиляция и обычный запуск**

```
gcc -pthread -o thread_demo thread_demo.c
chmod +x thread_demo
./thread_demo
```

Смотришь как 3 потока работают по 5 шагов.

**ЧАСТЬ 6. Запуск в фоне**

```
./thread_demo > output.txt 2>&1 &
cat output.txt
ps -eLf | grep thread_demo
```

**ЧАСТЬ 7. Наблюдение через ps**

```
./thread_demo &
PID=$!
ps -L -p $PID
kill $PID
```

**ЧАСТЬ 8. Наблюдение через top**

```
./thread_demo &
top -H -p $(pgrep thread_demo)
```

Выходишь из top клавишей q.

**ЧАСТЬ 9. Отладка в gdb**

Компилируем с отладкой:

```
gcc -g -pthread -o thread_demo_debug thread_demo.c
```

Запускаем gdb:

```
gdb ./thread_demo_debug
```

Внутри gdb по очереди вводишь:

```
break main
run
info threads
thread 2
break worker_thread
continue
next
quit
```

**ВСЁ.** Лабораторная выполнена полностью.