Найти тему
ПРОГРАММНАЯ ИНЖЕНЕРИЯ

ПРОГРАММНАЯ ИНЖЕНЕРИЯ

Мои методы программной инженерии. Модели и приёмы написания исходных кодов для back-end программирования
подборка · 8 материалов
1 прочтение · 3 недели назад
LINUX. ДВА ВИДА ЗОМБИ ПОТОКОВ .. Набираем в поисковике в яндексе что такое зомби потоки/процессы: "Процесс-зомби — это дочерний процесс в Unix-системе, завершивший своё выполнение, но ещё присутствующий в списке процессов операционной системы, чтобы дать родительскому процессу считать код завершения." Значит, какие два вида зомби потоков могут быть. И что значит "завершивший своё выполнение". 1й вид. Это поток, который ещё действительно существует, но перескочил в режим бездействия и выполняет ту часть программного кода, которая ничего не делает и не может ничего делать в принципе. Такой поток может возобновить своё нормальное выполнение если перескочит в свой рабочий режим. 2й вид. Этот вид зомби потока, это полностью уничтоженный поток в системе как сущность и он естественно уже не сможет "воскреснуть" как первый. Но он ещё зомби, а не мёртвый т.к. у него (как и у зомби потока 1го вида) сохранился рабочий объект с данными (см. схему), поэтому зомби, а не мёртвый. Рассмотрим схему ниже. Независимо от тип зомби потока в системе есть объект данных (или их группа, пусть будет объект данных для простоты), который выделяется ядром операционной системы (ОС) для потока и этот объект не может быть уничтожен зомби потоком любого типа. Почему? Для того чтобы не завалилось ядро ОС. Так работает межпоточное/межпроцессорное взаимодействие. Если поток перед тем как стать зомби уничтожит свой объект данных, то ядро ОС не будет знать об этом и при попытке доступа к несуществующему объекту получит критическую ошибку доступа и будет аварийно остановлено. Для того чтобы этого не происходило в объекте данных потока есть флаг "zmb". При переходе в зомби режим поток выставляет этот флаг, а ядро ОС читает. Ядро ОС само освобождает память под объект когда посчитает нужным. Первый тип зомби потока ядро ОС следует остановить самостоятельно. В ОС linux вроде используется 1й вид зомби потока.
3 прочтения · 2 месяца назад
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. УПРОЩЁННЫЕ УКАЗАТЕЛЬНЫЕ УЗЛЫ .. В этом посте будет изложена инфа про упрощённые указательные узлы. Для чего нужны узлы и почему не использовать обычные массивы. Массивы данных имеют фиксированную длину и содержат данные одного типа. Узлы позволяют хранить неограниченное число данных, а при их отсутствии не занимать память попусту. Плюс узлы одного типа могут содержать данные разного типа. .. Узлы представляют собой логические объекты для хранения единиц данных, так что один узел хранит одну единицу данных, напрямую или через указатели на данные во внешней памяти или даже в сети. Между собой узлы соединены в цепочки через указатели, так что предыдущий указывает на следующий и наоборот. В таких цепочках узлов для доступа к последнему нужно перебрать все предыдущие узлы начиная с первого. Это минус узлов, зато такая организация хранения данных позволяет их хранить неограниченное число. .. Итак, для организации хранения данных, размер и число единиц которых неизвестно даже приблизительно упрощённые указательные узлы (как и все) выстраиваются в списки, так что предыдущий узел указывает на последующий через указатель. Доступ к последующему узлу производится через указатель, а последующий узел НЕ УКАЗЫВАЕТ на предидущий, - этим и отличаются упрощённые указательные узлы от обычных. Такой подход позволяет экономить память и свести накладные расходы к минимуму. Так если в массивах указателей используется 8 байт для указателя на объект данных (в система x64), то в обычных узлах это 24 байта, а в упрощённых всего 16, - указатель на данные и указатель на последующий узел. Здесь также, каждый из узлов указывает на свою единицу данных: структуру, экземпляр класса, строка и прочее. .. Несмотря на то что нет обратных указателей на предыдущий узел в цепочке, а есть только указатели на последующие, на практике в 99% случаев это не приводит как каким-либо трудностям, например, при составлении списка узлов, при сортировке и пр. Ниже на схеме представлена организация упрощённых указательных узлов, каждый из них содержит указатель на последующий такой же узел "pnext" и указатель на свои данные "pdata". .. @ Ярошенко О. Ю. 2024
4 прочтения · 5 месяцев назад
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. ИНДЕКСАЦИЯ В ТЕЛЕФОНИИ
.. Доброго здравия всем. Часто наверно мноие слышали, что после переиндексации базы данных она работает быстрее и т.п. А в некоторых случаях без переиндексации она неправильно работает или вообще не работает! Как известно индексация используется для более быстрого доступа к данным, обычно к статическим, в справочниках или в уже накопленных данных. Предположим что в базе данных есть таблица с клиентами, в которой хранится такая информация как фамилия, имя, телефонный номер и прочее. Величина по которой выполняется индексация называется индексом...
13 прочтений · 7 месяцев назад
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. ГАСИМ ПОДБОР ПАРОЛЕЙ .. Всех приветствую. У некоторых авторов в статьях и прочих публикациям есть такое что они сваливают всё сразу в кучу и даже подготовленному читателю разбираться в этой каше тяжеловато. Поэтому в своих методах программной инженерии я в каждой публикации озвучиваю что то одно, какой-либо один момент. Плюс если исходный код максимально разделить на более мелкие составляющие, то получиться более эффективно, хотя и сложнее. Это уже другой ментод будет. .. Не раз наверно все замечали, что после пары неуспешных вводов пароля на сайте или даже при входе в Windows начинается задержка с ответом что пароль неверный. Это для гашения подбора паролей, чтобы снизить вероятность угадывания паролей. Такая же практика есть в программной инженерии чтобы для неавторизованных и подозрительных запросов в сети (в т.ч. с подозрительных сетевых адресов) делать задержу ответа о неудачной авторизации (такие запросы можно вообще отбрасывать, но сейчас речь идёт о задержке ответов). .. Но если поток обработчик таких запросов авторизации (и ответов на них) будет делать паузу для каждого такого запроса в несколько секунд, то сервер повиснет просто. Чтобы этого не происходило для таких ответов с задержкой делаем специальный поток (или несколько), который будет из очереди отправлять ответы таймаут отправки которыйх наступил. .. Основной поток из своей очереди вх. запросов для подозрительных или любых неавторизованных запросов генерирует ответ и помещает его в очередь овтетов на отправку. Поток отправщик отправляет ответы для которых наступил таймаут, например, 3 секунды, т.е. ч\з 3 секунды каждый, например. Поток отправщик таймаут и прочие настройки читает из конфигурации сервера. .. Доступ к очередям происходит через межпоточную блокировку доступа, поэтому они выделены ниже на схеме красным.
8 прочтений · 7 месяцев назад
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. БЕЗОПАСНЫЕ МЬЮТЕКСЫ .. Всем привет. В большом проекте делать отдельно мьютекс для блокировки доступа к каждой ф-и нецелесообразно, слишком много будет "затыков". Рассмотрим ситуацию когда доступ к глобальной структуре и её функциям блокируется одним из потоков, например, для загрузки и проверки конфигурации из файла и пр. .. Пусть у глобальной структуры (или класса, не принципиально) есть две функции "f1" и "f2", причём "f2" вызывается из "f1", т.е. входит в её состав и используется в ней. Блокировка доступа делается ч\з один и тот же глобальный мьютекс (здесь "mt" в "sm"), см. изображение. В программе может потребоваться сейчас вызвать "f1", а в другом месте "f2", и наоборот (для c++ они обе "public" и независимы). В начале ф-и "f1" захватывается этот мьютект и в начале "f2" он захватывается, но тут проблемы нет проверить был ли он захвачен этим потоком и пропустить повторный захват. Опасно когда этот мьютекст освобождается в конце "f2", здесь блокировка доступа снимается и оставшаяся часть ф-и "f1" будет выполняться без монопольного доступа, т.е. без блокировки и посыпятся ошибки. А такие плавающие ошибки также как и ошибки доступа к памяти очень трудно выловить, сейчас всё работает, но в определённые моменты они вылазиют. .. Вот простой метод как обойти это. Сделать структуру ("struct smx", см. изображение), в которой есть posix-мьютекс "mt" и счётчик вложенности блокировки "cl". У этой структуры также будут свои функции для блокировки поверх posix-функций. Эти свои ф-и скрывают механизм правильной блокировки и берёт эту задачу на себя. Как это работает, или принцип короче. Когда блокируется мьютекс физически при вызове ф-и "f1", то счётчик "cl" изменяется с 0 на 1. В момент вызова ф-и "f2" он меняется с 1 на 2. Когда ф-я "f2" завершается, то проверяется этот счётчик "cl", блокировка снимается только если он был равен "1". Но когда "f2" завершается "cl" уже равен 2, поэтому физически блокировка не снимается, а только декрементируется "cl" с 2 на 1. Таким образом блокировка не будет снята и ф-и "f1" будет продолжать выполнятся в монопольном режиме. В её конце "cl" равен 1 и блокировка снимается физически, так что остальные потоки смогут использовать эти ф-и "f1" и "f2". .. Как уже отметил, этот механизм вынесен в наши методы структуры "struct smx", например в функции "smx_lock" и "smx_unlock", в которых системные ф-и "pthread_mutex_lock" и "pthread_mutex_unlock" (т.е. физическая блокировка и разблокировка) выполняются по условиям, которые описал выше. Счётчик "cl" может менять только поток который выполнил блокировку, для этого его ид. потока сохраняется в поле "tl" нашей структуры "struct smx". ..
5 прочтений · 7 месяцев назад
МЕТОДЫ ПРОГ. ИНЖЕНЕРИИ. ТЕК. ВРЕМЯ В МНОГОПОТОЧНОСТИ .. Всем привет. Часто в логах нужно добавить текущее время перед строкой с логом в файл, например, так "13:41:12.257901", текущее время с указанием микросекунд. Для использования функции, которая будет возвращать текущее время в строке как указано выше совместно несколькими потоками обычно нужно делать разделение доступа ч\з мьютексы и т.п. .. Предполагается что несколько потоков будут использовать одну и ту же ф-ю совместно для того чтобы подставлять текущее время в свои логи или в консоль. Но, текущее время для всех потоков и для всей системы одно и то же. Поэтому для максимального быстродействия можно переменные в ф-и сделать вообще статические. Плюс сделать такую реализацию что одна переменная устанавливается один раз и в один проход. .. Как это работает. См. изображение схемы ниже. Есть три статические переменные, грубо говоря 3 ячейки памяти, которые видны всем потокам одновременно и каждый из них может в неё "залезть". В этой ф-и ("get_str_curr_time_ptr") каждая переменная выставляется только один раз (системной ф-ей или ч\з системный вызов), а читатся может несколько раз. Предположим что у нас около сотни потоков и эту ф-ю каждый поток выполняет на одной из 3х стадий, т.е. на одной из 3х атомарных системных функций (или выражений). .. Несмотря на то что разделения доступа между потоками нет это не приводит к ошибке и к неверному результату. В определённый момент один из потоков обновляет одну из переменных, а поскольку каждая из них обновляется в одном месте программы, то это не приводит к ошибке, а приводит к обновлению текущего системного времени в них. .. Зачем всё это надо если можно использовать мьютексы, например. А затем что межпоточное разделение доступа выполняется ч\з системные вызовы, а это накладно даже для потоков, а не процессов. А здесь никаких доп. инстурментов нет, даже три переменные статические, т.е. общие для всех потоков. В резльтате ф-я возвращает текущее время в строке, например, "16:30:31.773012". .. Как это реализовано на СИ изображено справа на изображении. ..