Оригинальный адрес видео:Woohoo.YouTube.com/watch?V=F групповая покупка…
Обзор содержания этой статьи:
- файловый дескриптор
- Основы операционной системы
- Файловые дескрипторы и процессы
- Сетевые и розетки
файловый дескриптор
Я полагаю, вы знакомы с «В Unix все является файлом», например/dev
содержание,/proc
Каталог и т. д., вы можете получить почти все данные, которые может получить система, манипулируя файлами. Для взаимодействия с файлами необходимо использовать файловые дескрипторы (файловые дескрипторы, сокращенно fd, — это число, уникальное внутри процесса).
С файлами вы можете делать эти вещи.
С визуальной точки зрения файловый дескриптор подобен билету: каждый раз, когда вам нужно что-то сделать, вы даете билет операционной системе, и операционная система делает то, что вы хотите сделать за вас.
Существует несколько системных стандартных файловых дескрипторов:
- 0: стандартный ввод, соответствующий Python
sys.stdin
- 1: Стандартный выход, соответствующий
sys.stdout
- 2: Стандартный вывод ошибок, соответствующий
sys.stderr
Затем мы закрепим его несколькими примерами:
with open('example.txt') as f:
print(f.read())
Вышеприведенная программа использует два fd, один из которых создается функцией открытия, а другой является fd стандартного вывода, который равен 1 при печати.
Вы также можете изменить права доступа к файлам на основе fd:
with open('example.txt') as f:
stat = os.stat(f.fileno())
os.chmod(f.fileno(), 0o640)
Есть даже контроль над оборудованием: приведенный ниже код можно использовать для извлечения компакт-диска.
Основы операционной системы
в темное средневековье. . . Прикладная программа может напрямую управлять оборудованием, а это значит, что если программа выйдет из строя, она выведет из строя всю систему, и тогда компьютер необходимо будет перезагрузить.
Теперь благодаря операционной системе достигается эффект изоляции, и прикладная программа не сможет получить прямой доступ к оборудованию, и должна обращаться к операционной системе для доступа к аппаратным ресурсам через системные вызовы. Операционная система имеет набор механизмов управления разрешениями, которые могут не принимать ваш запрос.
syscall
Каждый системный вызов будет передаваться из пользовательского пространства в пространство ядра, а затем возвращаться обратно в пользовательское пространство после запуска. Это означает, что требуется переключение контекста, поэтому скорость относительно низкая (количество необходимых тактов составляет порядка сотен).
Вернемся к предыдущему примеру:
# read.py
with open('example.txt') as f:
print(f.read())
Существует инструмент, чтобы узнать, вызывает ли программа системный вызов:
$ strace ./read.py
открыть таблицу файлов и таблицу fd
Таблица открытых файлов является глобальной, здесь находятся все файлы, открытые процессом. У каждого процесса есть своя таблица fd, которая фактически указывает на таблицу открытых файлов:
Тот же процесс открывает один и тот же файл во второй раз, а fd другой.
Содержимое таблицы fd очень простое, а фактические подробные данные хранятся в таблице открытых файлов.
fork()
fork создает дочерний процесс, дочерний процесс наследует fd родительского процесса, и в то же времяcopy opn write
На самом деле то, как основана память родительского процесса, можно рассматривать как то же самое содержимое, что и у родительского процесса. Наследование fd означает:
pid = os.fork()
После этого дочерний процесс наследует файловый дескриптор родителя:f
, они указывают на один и тот же файл в таблице открытых файлов, что означает, что их смещения одинаковы:
exec()
Замените память текущей программы, fd также будет унаследован, если не установленоcloexec
. Существуют определенные проблемы в дочернем процессе, наследующем fd родительского процесса, что фактически эквивалентно утечке fd родительского процесса дочернему процессу, что принесет определенные риски безопасности. Так кто-то нарисовалпредложение pwp446, который предоставляет возможность закрыть родительский процесс fds:subprocess
модуль имеетclose_fds
параметр, установленный наTrue
означает вызовexec
, Кроме0,1,2
Все fds, кроме трех, закрыты. Подробности можно узнатьpep446
оригинальный текст иОфициальная документация подпроцесса.
Сеть и сокеты
Для сетевого взаимодействия требуется пара сетевых сокетов, один из которых работает на сервере, а другой — на клиенте. Процесс сокета на стороне сервера обычно привязан к определенному порту, например 80, 3306, 5432 и т. д. Он всегда будет прослушивать этот порт и запускать соответствующую логику после прослушивания запроса. Наконец, результат будет возвращен клиенту. Сокет клиента обычно временно привязывается к высокоуровневому порту.После завершения запроса (то есть завершения процесса) список будет аннулирован и драгоценные ресурсы порта будут освобождены.
в Питонеsocket
модуль, в основном нужно указать два параметра: выбрать IPV4 или IPV6, использовать UDP или TCP? Простой пример сервера:
пример клиента:
unix sockets
Сокеты Unix и сетевые сокеты на самом деле похожи, за исключением того, что они могут разрешать взаимодействие только процессам на одном компьютере. Одна сторона сокета домена UNIX знает, что другой процесс находится на машине, поэтому такие операции, как меры проверки и операции маршрутизации, не требуются, поэтому он относительно быстрее и легче.
В Python это используется так:bind
а такжеconnect
теперь не IP-адрес и номер порта, а файл.Поскольку это файл, вы можете установить права на чтение и запись!Например, вы можете запретить пользователям определенной группы читать данные из этого сокета.
Если вы действительно любите компьютерные науки, как и я, и хотите изучать лежащую в их основе логику, добро пожаловать в мой публичный аккаунт WeChat: