You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
25 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"id": "c89738cc",
"metadata": {},
"source": [
"# Процесс и его характеристики #"
]
},
{
"cell_type": "markdown",
"id": "1dc01923",
"metadata": {},
"source": [
"На этой лекции мы поговорим о том, что такое процесс, узнаем, какие процессы запущены в вашей операционной системе, а также попробуем запустить свой первый Python процесс и поизучаем его характеристики.\n",
"\n",
"Итак, процесс — это программа, которая запущена в оперативной памяти компьютера. Другими словами, процесс — это набор инструкций, которые выполняются последовательно. В общем случае это действительно так, но в реальности всё немного сложнее. Мы будем погружаться в детали по мере обучения. Итак, каждый процесс, который запущен в операционной системе, имеет свои характеристики.\n",
"\n",
"Одна из главных характеристик — это идентификатор процесса, или `PID`. При помощи `PID` можно узнать многое о процессе. Каждый процесс занимает некий объем оперативной памяти. Он запрашивает её у системы, она ему её возвращает и аллоцирует. Также у процесса есть стек. Стек используется для вызова функций, для создания локальных переменных у этих функций. А также у каждого процесса есть список открытых файлов, стандартный ввод и стандартный вывод. В своих примерах я буду использовать операционную систему класса Linux и Python 3.\n",
"\n",
"Давайте попробуем узнать, какие процессы запущены в нашей операционной системе. Для этого нам потребуется консоль и команда `top`. Набираем команду `top`, вводим `enter` и видим результаты в виде таблицы. Команда `top` отображает нам список процессов, которые сейчас функционируют в операционной системе."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "6f3f3dc1",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[?1h\u001b=\u001b[H\u001b[2J\u001b[mtop - 13:11:15 up 415 days, 5:01, 1 user, load average: 0.00, 0.01, 0.05\u001b[m\u001b[m\u001b[m\u001b[m\u001b[K\n",
"Tasks:\u001b[m\u001b[m\u001b[1m 305 \u001b[m\u001b[mtotal,\u001b[m\u001b[m\u001b[1m 1 \u001b[m\u001b[mrunning,\u001b[m\u001b[m\u001b[1m 304 \u001b[m\u001b[msleeping,\u001b[m\u001b[m\u001b[1m 0 \u001b[m\u001b[mstopped,\u001b[m\u001b[m\u001b[1m 0 \u001b[m\u001b[mzombie\u001b[m\u001b[m\u001b[m\u001b[m\u001b[K\n",
"%Cpu(s):\u001b[m\u001b[m\u001b[1m 0.9 \u001b[m\u001b[mus,\u001b[m\u001b[m\u001b[1m 0.7 \u001b[m\u001b[msy,\u001b[m\u001b[m\u001b[1m 0.0 \u001b[m\u001b[mni,\u001b[m\u001b[m\u001b[1m 98.5 \u001b[m\u001b[mid,\u001b[m\u001b[m\u001b[1m 0.0 \u001b[m\u001b[mwa,\u001b[m\u001b[m\u001b[1m 0.0 \u001b[m\u001b[mhi,\u001b[m\u001b[m\u001b[1m 0.0 \u001b[m\u001b[msi,\u001b[m\u001b[m\u001b[1m 0.0 \u001b[m\u001b[mst\u001b[m\u001b[m\u001b[m\u001b[m\u001b[K\n",
"KiB Mem :\u001b[m\u001b[m\u001b[1m 65805548 \u001b[m\u001b[mtotal,\u001b[m\u001b[m\u001b[1m 23929780 \u001b[m\u001b[mfree,\u001b[m\u001b[m\u001b[1m 1447684 \u001b[m\u001b[mused,\u001b[m\u001b[m\u001b[1m 40428084 \u001b[m\u001b[mbuff/cache\u001b[m\u001b[m\u001b[m\u001b[m\u001b[K\n",
"KiB Swap:\u001b[m\u001b[m\u001b[1m 33030140 \u001b[m\u001b[mtotal,\u001b[m\u001b[m\u001b[1m 33030140 \u001b[m\u001b[mfree,\u001b[m\u001b[m\u001b[1m 0 \u001b[m\u001b[mused.\u001b[m\u001b[m\u001b[1m 63250272 \u001b[m\u001b[mavail Mem \u001b[m\u001b[m\u001b[m\u001b[m\u001b[K\n",
"\u001b[K\n",
"\u001b[7m PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND \u001b[m\u001b[m\u001b[K\n",
"\u001b[m11923 root 20 0 0 0 0 S 5.9 0.0 0:36.59 kworker/12+ \u001b[m\u001b[m\u001b[K\n",
"\u001b[m17818 mikhayl+ 20 0 495792 68184 8240 S 5.9 0.1 3:52.91 jupyter-no+ \u001b[m\u001b[m\u001b[K\n",
"\u001b[m19235 mikhayl+ 20 0 773876 47736 7784 S 5.9 0.1 0:01.98 python3 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m\u001b[1m19251 mikhayl+ 20 0 157848 2216 1436 R 5.9 0.0 0:00.04 top \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 1 root 20 0 191788 4784 2420 S 0.0 0.0 20:00.34 systemd \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 2 root 20 0 0 0 0 S 0.0 0.0 0:04.01 kthreadd \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 3 root 20 0 0 0 0 S 0.0 0.0 0:00.62 ksoftirqd/0 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+ \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 8 root rt 0 0 0 0 S 0.0 0.0 0:00.04 migration/0 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 10 root 20 0 0 0 0 S 0.0 0.0 20:57.39 rcu_sched \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 11 root rt 0 0 0 0 S 0.0 0.0 2:53.67 watchdog/0 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 12 root rt 0 0 0 0 S 0.0 0.0 2:42.47 watchdog/1 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 13 root rt 0 0 0 0 S 0.0 0.0 0:01.13 migration/1 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 14 root 20 0 0 0 0 S 0.0 0.0 0:00.66 ksoftirqd/1 \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/1:+ \u001b[m\u001b[m\u001b[K\n",
"\u001b[m 17 root rt 0 0 0 0 S 0.0 0.0 2:42.38 watchdog/2 \u001b[m\u001b[m\u001b[K\u001b[?1l\u001b>\u001b[25;1H\n",
"\u001b[K"
]
}
],
"source": [
"! top"
]
},
{
"cell_type": "markdown",
"id": "497b15f7",
"metadata": {},
"source": [
"Справа мы видим командную строку, при помощи которой были запущены процессы, и в виде колонок в таблице мы видим характеристики процессов. `PID` — идентификатор процесса, пользователь, из-под которого был запущен процесс. Пользователь определяет права, которые будут доступны этому процессу в операционной системе. Также такие важные колонки, как размер виртуальной и физической памяти. Не будем пока вдаваться в подробности, чем она отличается, а также процентные соотношения использования центрального процессора и памяти в процентах.\n",
"\n",
"Как мы видим, процессов в операционной системе достаточно много, и все они работают параллельно, на первый взгляд, но на самом деле это не так. Планировщик операционной системы выделяет небольшой квант времени каждому процессу, исполняет его и затем происходит переключение между другими процессами. Таким образом, процессы выполняются все последовательно, но из-за того, что квант времени небольшой, нам кажется, что все они выполняются параллельно.\n",
"\n",
"Давайте попробуем запустить наш первый Python процесс и изучим его характеристики средствами операционной системы."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "af56a5b0",
"metadata": {},
"outputs": [],
"source": [
"# простой Python процесс\n",
"import time\n",
"import os\n",
"\n",
"pid = os.getpid()\n",
"while True:\n",
" print(pid, time.time())\n",
" time.sleep(2)"
]
},
{
"cell_type": "markdown",
"id": "9c56ce33",
"metadata": {},
"source": [
"Программа, представленная на слайде, достаточно простая. В ней импортируется пара модулей — `time` и `os`. Затем при помощи вызова функции модуля `os.getpid` мы получаем идентификатор процесса, запоминаем его в переменную `pid` и в бесконечном цикле выводим `pid` нашего процесса, системное время, и спим пару секунд. Давайте попробуем запустить этот код. Посмотрим, как он выполняется в консоли. Я подготовил заранее код. Вот наш код. Исполняем его при помощи команды Python 3."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f5f49ba6",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"19255 1642062336.8886158\n",
"19255 1642062338.8908966\n",
"^C\n",
"Traceback (most recent call last):\n",
" File \"ex1.py\", line 7, in <module>\n",
" time.sleep(2)\n",
"KeyboardInterrupt\n"
]
}
],
"source": [
"! python ex1.py"
]
},
{
"cell_type": "markdown",
"id": "ebd43ffd",
"metadata": {},
"source": [
"Мы видим, что запустился процесс. Он вывел `pid 19287`, системное время, и продолжает это делать бесконечно в цикле. Давайте попробуем найти наш процесс в списке всех процессов. Для этого нам поможет команда `ps` с флагами `aux`. Подробную информацию о флагах можно посмотреть в документации. Итак, эта команда отобразила нам список всех процессов. Для того чтобы найти конкретно наш процесс, можно его отфильтровать при помощи команды `grep`. Итак, мы видим наш процесс."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "e9ea1a7f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"mikhayl+ 19287 0.5 0.0 125020 5696 pts/6 S+ 13:28 0:00 python ex1.py\r\n",
"mikhayl+ 19293 0.0 0.0 113128 1176 pts/7 Ss+ 13:29 0:00 /bin/bash -c ps aux | grep 19287\r\n",
"mikhayl+ 19295 0.0 0.0 112660 924 pts/7 S+ 13:29 0:00 grep 19287\r\n"
]
}
],
"source": [
"! ps aux | grep 19287"
]
},
{
"cell_type": "markdown",
"id": "329bbdd3",
"metadata": {},
"source": [
"Для того чтобы посмотреть название характеристик, можно вывести первую строчку от результатов вывода команды `ps` при помощи вот такой команды"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "f2c50933",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\n",
"mikhayl+ 19287 0.6 0.0 125020 5696 pts/6 S+ 13:28 0:00 python ex1.py\n",
"mikhayl+ 19288 0.0 0.0 113128 1304 pts/7 Ss+ 13:29 0:00 /bin/bash -c ps aux| head -1 ; ps aux | grep 19287\n",
"mikhayl+ 19292 0.0 0.0 112660 924 pts/7 S+ 13:29 0:00 grep 19287\n"
]
}
],
"source": [
"! ps aux| head -1 ; ps aux | grep 19287"
]
},
{
"cell_type": "markdown",
"id": "2be4f197",
"metadata": {},
"source": [
"Итак, еще раз, наш процесс с `pid`'ом `19287` виден в результатах вывода команды `ps`. Вот его `pid`. Он потребляет немного центрального процессора. А также одна из важных характеристик — это объем физической памяти. Мы видим, что он занимает почти 6 килобайт. Такой маленький процесс, а уже занимает 6 килобайт памяти. Видим командную строчку, при помощи которой он был запущен.\n",
"\n",
"Давайте поймем, какую же последовательность команд выполняет наш процесс. Что он вообще делает? Вообще, процессы, когда выполняются в операционной системе, они делают системные вызовы. Системные вызовы выполняют непосредственно ядро операционной системы, а результаты этих системных вызовов возвращаются к процессу, который их вызвал. Например, вывод в консоль, или стандартный вывод — это системный вызов. Для того чтобы посмотреть, какие системные вызовы делает наш процесс, можно воспользоваться командой `strace`, указать ей `pid` нашего процесса. Нужны дополнительные права для этой команды."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "78edff8a",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"strace: Process 19287 attached\n",
"select(0, NULL, NULL, NULL, {1, 430074}) = 0 (Timeout)\n",
"write(1, \"19287 1642062820.0185373\\n\", 25) = 25\n",
"select(0, NULL, NULL, NULL, {2, 0}) = 0 (Timeout)\n",
"write(1, \"19287 1642062822.0211146\\n\", 25) = 25\n",
"select(0, NULL, NULL, NULL, {2, 0}^C\n",
"strace: Process 19287 detached\n",
" <detached ...>\n"
]
}
],
"source": [
"! strace -p 19287"
]
},
{
"cell_type": "markdown",
"id": "cc4fc432",
"metadata": {},
"source": [
"В результатах `strace`'а мы как раз видим то, что вызывается системный вызов `write`. У него есть в аргументах файловый дескриптор 1. Это как раз наш стандартный вывод. А также мы видим, что в этот стандартный вывод попадает `pid` нашего процесса и системное время. Также видим, что для вызова `sleep` используются другие дополнительные системные вызовы. Для выхода используем `Ctrl+C`.\n",
"\n",
"Итак, мы видим, что процесс во время исполнения наш общается с операционной системой при помощи системных вызовов. Давайте посмотрим еще на список файлов, которые открыты в нашем процессе. Для этого мы можем воспользоваться командой `lsof`. Опять же, указываем `pid` нашего процесса."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "4bb300a6",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\r\n",
"python 19287 mikhaylovaf cwd DIR 253,2 113 1611044178 /home/mikhaylovaf/projects/python/5. Многопоточное и асинхронное программирование/1. Процессы и потоки\r\n",
"python 19287 mikhaylovaf rtd DIR 253,0 262 64 /\r\n",
"python 19287 mikhaylovaf txt REG 253,0 11328 610823 /usr/bin/python3.6\r\n",
"python 19287 mikhaylovaf mem REG 253,0 106070960 2704 /usr/lib/locale/locale-archive\r\n",
"python 19287 mikhaylovaf mem REG 253,0 2127336 33577165 /usr/lib64/libc-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 1139680 33577173 /usr/lib64/libm-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 14872 33577199 /usr/lib64/libutil-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 19776 33577171 /usr/lib64/libdl-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 144792 33577191 /usr/lib64/libpthread-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 3144192 34017354 /usr/lib64/libpython3.6m.so.1.0\r\n",
"python 19287 mikhaylovaf mem REG 253,0 164112 33577158 /usr/lib64/ld-2.17.so\r\n",
"python 19287 mikhaylovaf mem REG 253,0 26254 33577463 /usr/lib64/gconv/gconv-modules.cache\r\n",
"python 19287 mikhaylovaf 0u CHR 136,6 0t0 9 /dev/pts/6\r\n",
"python 19287 mikhaylovaf 1u CHR 136,6 0t0 9 /dev/pts/6\r\n",
"python 19287 mikhaylovaf 2u CHR 136,6 0t0 9 /dev/pts/6\r\n"
]
}
],
"source": [
"! lsof -p 19287"
]
},
{
"cell_type": "markdown",
"id": "7e2b8b4d",
"metadata": {},
"source": [
"Список достаточно большой. Как минимум, когда наш Python интерпретатор запускает нашу программу, открываются дополнительные системные библиотеки. Они отображены тоже в результатах команды `lsof`. Но самое главное, что нас сейчас интересует, — это стандартный поток ввода, вывода и поток ошибок. Это файловые дескрипторы 0, 1 и 2. Мы видим, что они равны терминалу.\n",
"\n",
"Давайте попробуем прервать выполнение программы при помощи `Ctrl+C` и перенаправим стандартный вывод в файл. Делается это при помощи такой команды в любой файл."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "af824409",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"^C\r\n",
"Traceback (most recent call last):\r\n",
" File \"ex1.py\", line 7, in <module>\r\n",
" time.sleep(2)\r\n",
"KeyboardInterrupt\r\n"
]
}
],
"source": [
"! python ex1.py > log.txt"
]
},
{
"cell_type": "markdown",
"id": "0861b697",
"metadata": {},
"source": [
"Снова поищем наш процесс при помощи команды ps. Его pid = 19347."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "444d66fc",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\n",
"mikhayl+ 19347 0.0 0.0 125028 5700 pts/6 S+ 13:38 0:00 python ex1.py\n",
"mikhayl+ 19366 0.0 0.0 113128 1300 pts/8 Ss+ 13:40 0:00 /bin/bash -c ps aux| head -1 ; ps aux | grep ex1.py\n",
"mikhayl+ 19370 0.0 0.0 112660 924 pts/8 S+ 13:40 0:00 grep ex1.py\n"
]
}
],
"source": [
"! ps aux| head -1 ; ps aux | grep ex1.py"
]
},
{
"cell_type": "markdown",
"id": "06385847",
"metadata": {},
"source": [
"И при помощи `lsof` выведем список открытых файлов."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "9282bc58",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\r\n",
"python 19347 mikhaylovaf cwd DIR 253,2 128 1611044178 /home/mikhaylovaf/projects/python/5. Многопоточное и асинхронное программирование/1. Процессы и потоки\r\n",
"python 19347 mikhaylovaf rtd DIR 253,0 262 64 /\r\n",
"python 19347 mikhaylovaf txt REG 253,0 11328 610823 /usr/bin/python3.6\r\n",
"python 19347 mikhaylovaf mem REG 253,0 106070960 2704 /usr/lib/locale/locale-archive\r\n",
"python 19347 mikhaylovaf mem REG 253,0 2127336 33577165 /usr/lib64/libc-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 1139680 33577173 /usr/lib64/libm-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 14872 33577199 /usr/lib64/libutil-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 19776 33577171 /usr/lib64/libdl-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 144792 33577191 /usr/lib64/libpthread-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 3144192 34017354 /usr/lib64/libpython3.6m.so.1.0\r\n",
"python 19347 mikhaylovaf mem REG 253,0 164112 33577158 /usr/lib64/ld-2.17.so\r\n",
"python 19347 mikhaylovaf mem REG 253,0 26254 33577463 /usr/lib64/gconv/gconv-modules.cache\r\n",
"python 19347 mikhaylovaf 0u CHR 136,6 0t0 9 /dev/pts/6\r\n",
"python 19347 mikhaylovaf 1w REG 253,2 0 1611044181 /home/mikhaylovaf/projects/python/5. Многопоточное и асинхронное программирование/1. Процессы и потоки/log.txt\r\n",
"python 19347 mikhaylovaf 2u CHR 136,6 0t0 9 /dev/pts/6\r\n"
]
}
],
"source": [
"! lsof -p 19347"
]
},
{
"cell_type": "markdown",
"id": "8966c1e8",
"metadata": {},
"source": [
"Результат команды `lsof` доказывает нам, что стандартный вывод у нашего процесса поменялся на файл.\n",
"\n",
"Итак, на этой лекции мы посмотрели и узнали, что такое процесс, как выглядит процесс в нашей операционной системе. Мы узнали о том, как работает процесс, что он делает системные вызовы. Также изучили характеристики запущенного `python` процесса и узнали, как работают команды `top`, `ps`, `lsof` и `strace`.\n",
"\n",
"На следующей лекции мы продолжим изучать процессы и узнаем, как создавать дочерние процессы на Python."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}