Gathernetworkinfo.vbs в автозагрузке что это за программа? |
Всем привет. Господа, сегодня у нас не обычная задача, я должен узнать что такое gatherNetworkInfo.vbs, ибо это часто, вернее некоторые юзеры могут заметить в автозагрузке. Что это за дичь редкая, подумал я? Сразу мысли в голову полезли, может это вирус? Угроза.. ? Но если посмотреть внимательно на сам файл gatherNetworkInfo.vbs, то понятно сразу, это скрипт, ибо расширение vbs ведь… А вот само название… Ну первое слово gather, это не знаю что, но посмотрел в переводчик и узнал что это переводится как собирать. Ну а NetworkInfo это я уже знаю что, переводится как информация о сети… Так, хм, то есть это что, получается скрипт о сборе информации о сети? Ну другое в голову ничего не приходит… Окей, я еще пороюсь в пространстве интернета, может еще какую инфу найду…
Вот что мне удалось выяснить. Этот скрипт обычно расположен в системной папке System32, что как бы намекает на то, что он системный вроде как. В некоторых программах, где вы можете посмотреть автозагрузку, то там может также указываться что файл gatherNetworkInfo.vbs не имеет цифровой подписи. Вы можете прочитать в интернете, мол что если нет цифровой подписи, то это норм, ибо скриптовый файл типа нереально подписать. Я тоже так думал, но оказывается что его подписать все таки можно! Но почему тогда gatherNetworkInfo.vbs не подписан? Не знаю, может просто это не столь важно….
Еще узнал что скрипт gatherNetworkInfo.vbs обычно запускается при помощи запланированного задания, которое можно найти в планировщике виндовском. Этот скрипт присутствует вроде как во всех виндах начиная с Windows Vista. То есть первый вывод уже можем сделать, данный скрипт как я понимаю идет системным, то есть это не вирусня, это реально системный компонент винды.
Так, задание, при помощи которого запускается gatherNetworkInfo.vbs, то оно находится в разделе MicrosoftWindowsNetTrace в планировщике и называется оно GatherNetworkInfo. Там его можно отключить или даже удалить, лучше всего отключить его и проверить, если проблем не будет, то можно потом и удалить… Хотя лучше таки оставить, кушать то оно все равно не просит…
Кстати расширение vbs расшифровывается как Visual Basic Scripting Edition.
Вот еще узнал, что gatherNetworkInfo.vbs в автозагрузке обычно сидит потому что задача тупо включена и все. Но при этом в самом задании нужно посмотреть там где триггеры, там есть что-то? Там в триггерах может быть указана программа, которая требует выполнения задания. Ибо если нет программы, то задача получается есть, а кому ее выполнять, то тут нет никого и в итоге никакого действия она вообще не делает.
Еще на некоторых сайтах очень уверенно говорят что файл gatherNetworkInfo.vbs не имеет никакого отношения к винде. Откуда такая уверенность я ума не приложу, особенно учитывая то что антивирусы или антивирусные утилиты не видят ничего опасного в этом файле.
Как я понял, то задание gatherNetworkInfo.vbs можно удалить, вот один чел удалил и пишет что все норм, никаких проблем не заметил. Перед удалением я конечно же рекомендую создать точку восстановления, мало ли…
На другом сайте я нашел инфу, все подтвердилось. Да, есть такое задание как GatherNetWorkInfo, оно нужно для сбора инфы о использовании сети, также ведет статистику отправляемых пакетов, скорости соединения. И вроде таки можно отключить.
Я решил у себя тоже посмотреть, уж страшно интересно стало, есть ли у меня в планировщике задание GatherNetWorkInfo? Если что у меня Windows 10.. Итак, открыл я панель управления (кстати для этого можете зажать Win R и потом вставить команду control panel), потом там в правом верхнем углу написал слово план, и я увидел кнопку планировщика:
РЕКЛАМА
Запустил, немного подождав, потом все таки показалось окно планировщика:
РЕКЛАМА
Так, теперь переходим в раздел, где сидит задание GatherNetWorkInfo, ну то есть вот сюда:
MicrosoftWindowsNetTrace
То есть сначала открываем раздел Windows:
И в нем уже ищем раздел NetTrace:
Выбрали раздел, смотрим вправо и вот я вижу что у меня есть задание GatherNetworkInfo, смотрите:
Ну что, делаем самое интересненькое? Я нажимаю по заданию два раза.. Открывается вот такое окошко:
Ну как видите, тут так и написано, что это Сборщик сведений сети. Окей, окей… И еще внизу вижу что стоит галочка Выполнять с наивысшими правами.. Все признаки того что это системное задание.. Блин, я забыл. Это ведь моя рабочая винда, верно? Верно! А тут вирусов нет и быть не может, поверьте, у меня все продумано, тут я даже никакие проги никогда не ставлю, необходимые поставил и все. Игр вообще нет. Вирусы короче исключены, так что вам еще одно подтверждение того, что GatherNetworkInfo это СИСТЕМНОЕ И БЕЗОПАСНОЕ ЗАДАНИЕ, удалять можно, но смысл.. ? Так, ладно, мне еще оч любопытно посмотреть что там на вкладке Триггеры.. вот я ее открыл, и смотрите, тут тупо пусто:
То есть задание есть, но оно не выполняется, ибо нет потребности. Видимо выполняется оно таки по запросу. При этом всем, если перейти на вкладку Действия, то тут будет написано что есть действие, и это выполнение скрипта gatherNetworkInfo.vbs:
Ага, блин, я попутал немного! Блин, вот дела…!! В общем вкладка Триггеры, это там должно быть РАСПИСАНИЕ ВЫПОЛНЕНИЯ, но его нет, потому что это задание выполняется по запросу, а не при запуске винды! Это нужно понимать ребята. Другие вкладки я вам не показываю, там нет ничего особенного, ну то есть ничего интересного
А вот некоторые юзеры, у которых стоит AnVir Task Manager, то они там и увидели запись с gatherNetworkInfo.vbs:
Да, все верно, там оно может показывать что уровень риска 46%, но я все проверил, у меня тоже есть это задание, так что если у меня есть, то это реально стопудово безопасное задание и gatherNetworkInfo.vbs ну никак не вирус. Правда вы можете мне не верить, но смысл мне врать то….
Также я нашел в сети картинку, это открыты свойства файла gatherNetworkInfo.vbs, смотрите:
Видите тут дату? 2009-тый год, такой год и у остальных системных файлов, не у всех, но у многих… Я сам бывало смотрел свойства системных файлов, я имею ввиду именно в Windows 7, и там тоже был именно 2009-тый год.
Вот еще одна картинка, это снова AnVir Task Manager, тут он прям вообще говорит что файл gatherNetworkInfo.vbs то рискованный страшно капец:
Вы тут можете меня спросить, так что, AnVir Task Manager плохая прога? Нет! Просто AnVir Task Manager думает так: это файл vbs, то есть скрипт, что внутри непонятно, стоит в автозагрузке, это немного подозрительно. И все правильно, ибо такие мутки часто мутят именно вирусяки! Но тут все чисто, я думаю что вы уже это понимаете.
Ребята, накидаем выводов?
- gatherNetworkInfo.vbs это никак не вирус, это задание GatherNetworkInfo в планировщике, их там вообще этих заданий целая туча, много нам незнакомые, так что, теперь считать что это все вирусы?
- Задание GatherNetworkInfo есть в каждой винде, начиная с Windows Vista, в XP как я понимаю его нет.
- У меня на рабочем компе задание GatherNetworkInfo присутствует, ну а у меня вирусы исключены стопудово, ибо стоит фаервол и обновления регулярные и левак не качается воообще!
- Если вам все таки кажется что что-то не так, то советую проверить комп Dr.Web CureIt и AdwCleaner, это лучшие антивирусные утилиты, но ищут принципиально разные угрозы, поэтому проверять нужно двумя.
РЕКЛАМА
На этом все господа, надеюсь что я помог вам, что вы поняли что GatherNetworkInfo это штатное виндовское задание, бояться нечего. Однако антивирусными утилитами я бы комп все таки проверил на вашем месте… иди знай.. вдруг вирус маскируется… Хотя это маловероятно, но все же. Берегите себя дорогие ребята!
/proc/net/softnet_stat
Как мы видели в предыдущей главе, статистические счётчики инкрементируются при выходе из цикла net_rx_action, либо если осталась работа, которая могла быть выполнена, но мы упёрлись в ограничение бюджета или времени для SoftIRQ. Эта статистика отслеживается как часть структуры struct softnet_data, ассоциированной с CPU.
В Linux 3.13.0 можно выяснить, какие значения соответствуют каким полям в /proc/net/softnet_stat посредством чтения исходников ядра. Взято из net/core/net-procfs.c:
seq_printf(seq,
"x x x x x x x x x x xn",
sd->processed, sd->dropped, sd->time_squeeze, 0,
0, 0, 0, 0, /* was fastroute */
sd->cpu_collision, sd->received_rps, flow_limit_count);
Многие из этих счётчиков имеют странные имена и инкрементируются в неожиданных местах. Только изучив сетевой стек можно понять, когда и где инкрементируется каждый из них. Поскольку статистика squeeze_time встречалась в net_rx_action, мне кажется, есть смысла задокументировать сейчас этот файл.
Читаем /proc/net/softnet_stat, чтобы мониторить статистику обработки сетевых данных:
$ cat /proc/net/softnet_stat
6dcad223 00000000 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000
6f0e1565 00000000 00000002 00000000 00000000 00000000 00000000 00000000 00000000 00000000
660774ec 00000000 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000
61c99331 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
6794b1b3 00000000 00000005 00000000 00000000 00000000 00000000 00000000 00000000 00000000
6488cb92 00000000 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Важные подробности относительно /proc/net/softnet_stat:
- Каждая строка /proc/net/softnet_stat соответствует структуре struct softnet_data, по одной на каждый CPU.
- Значения разделены одиночными пробелами и отображаются в шестнадцатеричной форме.
- Первое значение, sd->processed, — это количество обработанных сетевых фреймов. Оно может превышать общее количество полученных фреймов, если вы используете связывание Ethernet (Ethernet bonding). Драйвер связывания может стать причиной повторной обработки данных, и тогда счётчик sd->processed для одного и того же пакета будет инкрементироваться больше одного раза.
- Второе значение, sd->dropped, — это количество отброшенных сетевых фреймов по причине нехватки места в очереди обработки. Об этом поговорим ниже.
- Третье значение, sd->time_squeeze, — это количество раз, когда цикл net_rx_action прерывался из-за истощения бюджета или достижения ограничения по времени, хотя работа ещё оставалась. Как объяснялось выше, помочь тут может увеличение budget.
- Следующие пять значений всегда равны 0.
- Девятое значение, sd->cpu_collision, — это количество коллизий, возникавших при попытках получения блокировки устройства в ходе передачи пакетов. Поскольку эта статья посвящена приёму пакетов, то мы эту статистику рассматривать не будем.
- Десятое значение, sd->received_rps, — это количество раз, когда посредством межпроцессорного прерывания будили CPU для обработки пакетов.
- Последнее значение, flow_limit_count, — это количество раз, когда было достигнуто ограничение потока (flow limit). Ограничение потока — это опциональная возможность управления принимаемыми пакетами (Receive Packet Steering), которую мы скоро рассмотрим.
Если вы решили мониторить этот файл и отображать результаты графически, то будьте крайне осторожны, чтобы не поменять порядок полей и сохранить их смысл. Для этого ознакомьтесь с исходниками ядра.
Dev_gro_receive
Эта функция сначала проверяет, включена ли GRO. Если да, то готовится к её применению: проходит по списку offload-фильтров, чтобы высокоуровневые стеки протоколов могли работать с данными, предназначенными для GRO. Это нужно для того, чтобы уровни протоколов могли сообщать уровню сетевого устройства, является ли пакет частью
, который в данный момент свободен, а также могли обрабатывать всё относящееся к протоколу, что должно произойти в рамках GRO. Например, TCP-протоколу нужно решить, можно ли/когда подтверждать объединение пакета с уже имеющимся.
Вот пример кода, который это делает, взятый из net/core/dev.c:
list_for_each_entry_rcu(ptype, head, list) {
if (ptype->type != type || !ptype->callbacks.gro_receive)
continue;
skb_set_network_header(skb, skb_gro_offset(skb));
skb_reset_mac_len(skb);
NAPI_GRO_CB(skb)->same_flow = 0;
NAPI_GRO_CB(skb)->flush = 0;
NAPI_GRO_CB(skb)->free = 0;
pp = ptype->callbacks.gro_receive(&napi->gro_list, skb);
break;
}
Если уровни протоколов сообщают, что пришло время сбросить GRO-пакет, то далее выполняется эта процедура. В этом случае вызывается napi_gro_complete, которая вызывает callback gro_complete для уровней протоколов, а затем передаёт пакет по стеку посредством вызова netif_receive_skb.
Пример кода из net/core/dev.c:
if (pp) {
struct sk_buff *nskb = *pp;
*pp = nskb->next;
nskb->next = NULL;
napi_gro_complete(nskb);
napi->gro_count--;
}
Если уровни протоколов объединили этот пакет с имеющимся потоком, то napi_gro_receive посто возвращается.
Если пакет не было объединён и в системе меньше MAX_GRO_SKBS (8) GRO-потоков, то в список gro_list NAPI-структуры данного CPU добавляется новая запись.
Пример кода из net/core/dev.c:
if (NAPI_GRO_CB(skb)->flush || napi->gro_count >= MAX_GRO_SKBS)
goto normal;
napi->gro_count ;
NAPI_GRO_CB(skb)->count = 1;
NAPI_GRO_CB(skb)->age = jiffies;
skb_shinfo(skb)->gso_size = skb_gro_len(skb);
skb->next = napi->gro_list;
napi->gro_list = skb;
ret = GRO_HELD;
Так работает система GRO в сетевом стеке Linux.
Enqueue_to_backlog
Эта функция сначала получает указатель на структуру softnet_data удалённого CPU, содержащую указатель на input_pkt_queue. Затем проверяется длина очереди input_pkt_queue этого удалённого CPU. Взято из
qlen = skb_queue_len(&sd->input_pkt_queue);
if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
Сначала длина очереди input_pkt_queue сравнивается с netdev_max_backlog. Если длина большего этого значения, то данные
отбрасываются
. Аналогично проверяется ограничение потока, и если оно достигнуто, то данные
отбрасываются
. В обоих случаях инкрементируется счётчик отбрасываний структуры softnet_data. Обратите внимание, что это структура того CPU, в чью очередь должны были быть помещены данные. Мониторинг счётчика отбрасываний описан в главе о /proc/net/softnet_stat.
enqueue_to_backlog вызывается при обработке пакетов с включённым RPS, а также из netif_rx. Большинству драйверов следует использовать не netif_rx, а netif_receive_skb. Если вы не применяете RPS и ваш драйвер не использует netif_rx, то увеличение backlog’а не окажет на систему заметного влияния, поскольку он и не используется.
Примечание: проверьте используемый драйвер. Если он вызывает netif_receive_skb и вы не используете RPS, то увеличение netdev_max_backlog никак не повысит производительность, потому что никакие данные не доберутся до input_pkt_queue.
Допустим, что input_pkt_queue достаточно мала и ограничение потока не достигнуто (или отключено), а данные могут быть помещены в очередь. Логика здесь немного смешная, её можно обобщить так:
Из-за использования goto код довольно хитрый, так что читайте внимательно. Взято из
if (skb_queue_len(&sd->input_pkt_queue)) {
enqueue:
__skb_queue_tail(&sd->input_pkt_queue, skb);
input_queue_tail_incr_save(sd, qtail);
rps_unlock(sd);
local_irq_restore(flags);
return NET_RX_SUCCESS;
}
/* Schedule NAPI for backlog device
* We can use non atomic operation since we own the queue lock
*/
if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) {
if (!rps_ipi_queued(sd))
____napi_schedule(sd, &sd->backlog);
}
goto enqueue;
Napi и napi_schedule
Давайте посмотрим, как работает вызов napi_schedule из обработчика аппаратных прерываний.
Как вы помните, NAPI существует именно для сбора сетевых данных без использования прерываний от сетевой карты, сигнализирующих о готовности данных к обработке. Выше упоминалось, что цикл poll загружается (bootstrapped) при получении аппаратного прерывания.
Иными словами, NAPI включён, но не активен до тех пор, пока не придёт первый пакет. В этот момент сетевая карта генерирует прерывание и NAPI стартует. Ниже мы рассмотрим и другие случаи, когда NAPI может быть выключен, и прежде чем его запустить, понадобится сгенерировать прерывание.
Цикл poll запускается, когда драйверный обработчик прерываний вызывает napi_schedule. Это просто функция-обёртка, заданная в заголовочном файле, которая в свою очередь вызывает __napi_schedule.
Взято из net/core/dev.c:
/**
* __napi_schedule – расписание получения
* @n: запись в расписании
*
* Будет задан старт функции получения записи
*/
void __napi_schedule(struct napi_struct *n)
{
unsigned long flags;
local_irq_save(flags);
____napi_schedule(&__get_cpu_var(softnet_data), n);
local_irq_restore(flags);
}
EXPORT_SYMBOL(__napi_schedule);
В этом коде для получения структуры softnet_data, зарегистрированной на текущий CPU, используется __get_cpu_var. Данная структура передаётся в ____napi_schedule вместе со взятой из драйвера структурой struct napi_struct. Как много нижних подчёркиваний.
Давайте посмотрим на ____napi_schedule, взято из net/core/dev.c:
/* Вызывается с отключённым IRQ */
static inline void ____napi_schedule(struct softnet_data *sd,
struct napi_struct *napi)
{
list_add_tail(&napi->poll_list, &sd->poll_list);
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}
Этот код делает две важные вещи:
- Структура struct napi_struct, взятая из кода драйверного обработчика прерываний, добавляется в poll_list, прикреплённый к структуре softnet_data, ассоциированной с текущим CPU.
- __raise_softirq_irqoff используется для запуска SoftIRQ NET_RX_SOFTIRQ. В результате начинает выполняться net_rx_action, зарегистрированная во время инициализации подсистемы сетевого устройства, если это ещё не сделано.
Как мы скоро увидим, SoftIRQ функция-обработчик net_rx_action для сбора пакетов вызовет функцию NAPI poll.
Net framework – для чего он нужен и можно ли удалить
Мы уже выяснили, что многие программы не будут нормально работать без кое-каких дополнительных модулей, таких как NET Framework. Пользователи Winfows 7/10, наверняка, не раз встречались с этим компонентом, однако вряд ли задумывались о его роли и выполняемых функциях. Спешим восполнить этот пробел.
Итак, что такое Microsoft .NET Framework, для чего он нужен и можно ли без него обойтись? Если говорить простым языком, то NET Framework представляет собой набор DLL-библиотек или универсальный программный код, используемый разными программами. Правда, такое определение вряд ли прольет достаточно света на тему предмета, поэтому мы немного углубимся в историю.
Дело в том, что изначально система Windows, как платформа, была ориентирована на язык программирования С, на котором должны были разрабатываться предназначенные для нее приложения. Однако этот язык оказался не слишком удобным и к тому же мало подходящим для создания сложных конструкций.
Нужна была некая общая платформа, позволявшая работать самым разным приложениям в разных версиях и редакциях Windows. На тот момент в системе уже имелся набор DLL-библиотек, но они опять же поддерживали только приложения, написанные на языке С. Имелись и более серьезные проблемы, которые предстояло решить Microsoft, например, неуправляемый код, препятствующий разграничению прав для запускаемых программ.
Решением стала интеграция виртуальной машины Java, разработанной компанией Sun и служивший как бы прослойкой между Windows, сторонними приложениями и аппаратной частью компьютера. Однако сотрудничество Microsoft и Sun оказалось недолгим, и в 2001 году компания Microsoft представила собственную универсальную платформу для разработки приложений, получившую название .NET Framework и поставившую точку в вопросе совместимости.
Будучи универсальным, модуль NET Framework позволяет запускать поддерживающие технологию NET программы не только на Windows, но и в других системах, причем программа может быть разработана на любом языке программирования, включая те языки, которая Windows не «понимает».
На вопрос, что это за программа NET Framework и нужна ли она, мы, надо полагать, ответили. Можно ли ее удалить, скажем, ради экономии места на жестком диске? Да, за исключением той версии, которая поставляется вместе с Windows. Делать это, однако, не рекомендуется без особой нужды, так как некоторые сторонние программы, зависящие от NET Framework, могут перестать запускаться.
Инициализация napi в драйвере igb
Драйвер igb делает это с помощью длинной цепочки вызовов:
- igb_probe вызывает igb_sw_init.
- igb_sw_init вызывает igb_init_interrupt_scheme.
- igb_init_interrupt_scheme вызывает igb_alloc_q_vectors.
- igb_alloc_q_vectors вызывает igb_alloc_q_vector.
- igb_alloc_q_vector вызывает netif_napi_add.
В результате выполняется ряд высокоуровневых операций:
- Если поддерживается MSI-X, то она включается с помощью вызова pci_enable_msix.
- Высчитываются и инициализируются различные настройки; например, количество очередей передачи и приёма, которые будут использоваться устройством и драйвером для отправки и получения пакетов.
- igb_alloc_q_vector вызывается однократно для каждой создаваемой очереди передачи и приёма.
- При каждом вызове igb_alloc_q_vector также вызывается netif_napi_add для регистрации функции poll для конкретной очереди. Когда функция poll будет вызвана для сбора пакетов, ей будет передан экземпляр struct napi_struct.
Давайте взглянем на igb_alloc_q_vector чтобы понять, как регистрируется callback poll и её личные данные (private data).
Взято из drivers/net/ethernet/intel/igb/igb_main.c:
static int igb_alloc_q_vector(struct igb_adapter *adapter,
int v_count, int v_idx,
int txr_count, int txr_idx,
int rxr_count, int rxr_idx)
{
/* ... */
/* размещает в памяти q_vector и кольца (rings) */
q_vector = kzalloc(size, GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
/* инициализирует NAPI */
netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
/* ... */
Выше приведён код размещения в памяти очереди приёма и регистрации функции igb_poll с помощью подсистемы NAPI. Мы получаем ссылку на struct napi_struct, ассоциированную с этой новой созданной очередью приёма (&q_vector->napi). Когда придёт время сбора пакетов из очереди и подсистемой NAPI будет вызвана igb_poll, ей передадут эту ссылку.
Важность описанного алгоритма мы поймём, когда изучим поток данных из драйвера в сетевой стек.
Инициализация pci
Сетевая карта Intel I350 — это устройство с интерфейсом
PCI-устройства идентифицируют себя с помощью серии регистров в конфигурационном пространстве PCI.
Когда драйвер устройства скомпилирован, то для экспорта таблицы идентификаторов PCI-устройств, которыми может управлять драйвер, используется макрос MODULE_DEVICE_TABLE (из include/module.h). Ниже мы увидим, что таблица также регистрируется как часть структуры.
Эта таблица используется ядром для определения, какой нужно загрузить драйвер для управления устройством. Таким образом операционная система понимает, какое устройство подключено и какой драйвер позволяет с ним взаимодействовать.
Вы можете найти таблицу и идентификаторы PCI-устройств для драйвера igb, соответственно, здесь drivers/net/ethernet/intel/igb/igb_main.c и здесь drivers/net/ethernet/intel/igb/e1000_hw.h:
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS), board_82575 },
/* ... */
};
MODULE_DEVICE_TABLE(pci, igb_pci_tbl);
Как мы видели выше, pci_register_driver вызывается драйверной функцией инициализации.
Эта функция регистрирует структуру указателей. Большинство из них являются указателями функций, но таблица идентификаторов PC-устройства тоже регистрируется. Ядро использует регистрируемые драйвером функции для запуска PCI-устройства.
Из drivers/net/ethernet/intel/igb/igb_main.c:
static struct pci_driver igb_driver = {
.name = igb_driver_name,
.id_table = igb_pci_tbl,
.probe = igb_probe,
.remove = igb_remove,
/* ... */
};
Как же заработать на тестнетах?
Проекты предлагают пользователям разные способы тестирования своих разработок: одни просят проверить коды или написать скрипты, а другие — совершить транзакции с токенами на платформе. За действия в пробной сети либо платят вознаграждение (Incentivised testnet), либо — нет (Non-Incentivised testnet).
Мы рассмотрим тестнеты, на которых получится заработать. Способы и размер вознаграждения зависят от возможностей, заявленных проектом. Одни предлагают всем участникам токены продукта, над которым работает команда, другие — определенную аллокацию на сейле, третьи — выборочно поощряют самых активных участников тестнета.

Чаще всего правила и инструкции публикуются на официальном канале проекта в Medium. Для тех, кто не владеет языками, есть 2 новости:
- Плохая — в большинстве случаев вся информация публикуется на английском.
- Хорошая — некоторые проекты заморачиваются и размещают инструкции на разных языках. Часто бывают и документы на русском.
После того как вы изучите инструкцию и удостоверитесь в том, что проект выплачивает вознаграждения, оцените их рентабельность.
Участие в тестнете = ваше время.
Если выплаты будут стоить «копейки», вряд ли есть смысл вкладывать свои силы в это мероприятие. Для оценки рентабельности можно использовать несколько факторов:
- Проверьте, торгуются ли токены проекта на биржах. Узнайте, сколько они стоят. Так вы сможете умножить цену цифровой единицы проекта на размер вознаграждения и понять, стоит ли овчинка выделки.
- Изучите площадки, с которыми работает стартап. Например, команда может запускать свой продукт на авторитетных лаунчпадах (CoinList, RedKite и т.д). Это значит, что у проекта хорошая поддержка со стороны инвесторов и сильных игроков рынка, и скорее всего, стартап ждет светлое будущее.
- Почитайте отзывы участников. Тестнеты могут длиться от 1 дня до 1 месяца. Участники успевают сформировать свое мнение по поводу мероприятия и поделиться им в интернете. Если большинство отзывов положительные, можно пробовать зарабатывать на испытаниях.
Сейчас участвую в UMEE тестнет. Бесплатное мероприятие с наградами. Это не первый тестнет. Был один ранее, за который всех участникам дали 600–4000 токенами проекта. На текущий момент сумма предыдущих вознаграждений равняется $40–$260. Судя по разговорам в сообществе, в этом тестнете награды будут не меньше. Посмотрим, чем нас побалуют после 28 апреля (окончание программы).
Мониторинг статистики уровня протокола ip
Читаем /proc/net/snmp, чтобы мониторить подробную статистику протокола IP:
$ cat /proc/net/snmp
Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
Ip: 1 64 25922988125 0 0 15771700 0 0 25898327616 22789396404 12987882 51 1 10129840 2196520 1 0 0 0
...
Этот файл содержит статистику по нескольким уровням протоколов. Первым идёт уровень IP. В первой строке представлены разделённые пробелами имена соответствующих значений из второй строки.
На уровне протокола IP можно найти ряд счётчиков статистики, которые используются в С-перечислении. Все валидные enum-значения и имена полей в /proc/net/snmp, которым они соответствуют, можно найти в include/uapi/linux/snmp.h:
enum
{
IPSTATS_MIB_NUM = 0,
/* часто записываемые напрямую поля, хранятся в той же кэш-строке */
IPSTATS_MIB_INPKTS, /* InReceives */
IPSTATS_MIB_INOCTETS, /* InOctets */
IPSTATS_MIB_INDELIVERS, /* InDelivers */
IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */
IPSTATS_MIB_OUTPKTS, /* OutRequests */
IPSTATS_MIB_OUTOCTETS, /* OutOctets */
/* ... */
Читаем /proc/net/netstat, чтобы мониторить расширенную статистику протокола IP:
$ cat /proc/net/netstat | grep IpExt
IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets InCsumErrors InNoECTPkts InECT0Pktsu InCEPkts
IpExt: 0 0 0 0 277959 0 14568040307695 32991309088496 0 0 58649349 0 0 0 0 0
Формат аналогичен /proc/net/snmp, за исключением строк с префиксом IpExt.
Некоторые любопытные метрики:
- InReceives: общее количество IP-пакетов, достигших ip_rcv до всех проверок целостности.
- InHdrErrors: общее количество IP-пакетов с повреждёнными заголовками. Заголовок был слишком маленьким или длинным, вообще не существует, содержал неправильный номер версии протокола IP и так далее.
- InAddrErrors: общее количество IP-пакетов, когда хост был недоступен.
- ForwDatagrams: общее количество IP-пакетов, которые были переадресованы (forwarded).
- InUnknownProtos: общее количество IP-пакетов с неизвестным или неподдерживаемым протоколом, указанным в заголовке.
- InDiscards: общее количество IP-пакетов, отклонённых в результате сбоя выделения памяти, или в результате сбоя контрольной суммы при обрезании пакета.
- InDelivers: общее количество IP-пакетов, успешно доставленных на более высокие уровни протоколов. Помните, что эти уровни могут отбрасывать данные, даже если этого не сделал уровень IP.
- InCsumErrors: общее количество IP-пакетов с ошибками контрольной суммы.
Все эти счётчики инкрементируются в специфических местах уровня IP. Время от времени код проходит по ним, и могут возникать ошибки двойного подсчёта и прочие баги. Если для вас важна эта статистика, то очень рекомендую изучить исходники этих метрик на уровне протокола IP, чтобы понимать, как они инкрементируются.
Перфоманс
Изменения в перфомансе — это самая заметная часть релиза. О них много писали на сайте Microsoft и рассказывали на .NET Conf. Давайте посмотрим внимательнее и определимся, где, насколько и за счет чего выросла производительность.
Измерения перфоманса с этого скрина основаны на бенчмарках от TechEmpower. Здесь Microsoft сравнивают результаты замеров производительности .NET 3.1 с ожидаемыми значениями для .NET 5. Стоит заметить, что это именно ожидаемые значения — реальных результатов от TechEmpower пока не было.
Помимо результатов бенчмарков от TechEmpower, Microsoft также рассказывает и о других улучшениях. Например, сериализация JSON стала работать на 20% быстрее, а сериализация больших коллекций и массивов ускорилась аж в три раза.
Также замеры производительности делал автор библиотеки Fusion Александр Якунин. В двух статьях на Medium он сначала измерил, насколько ускорилась работа демок его библиотеки (от 20 до 105 процентов), а затем проверил пятый .
За счет чего это происходит? В первую очередь, благодаря изменениям в GC, которые привели к уменьшению количества аллокаций и ускорению сборки мусора. Кстати, все эти изменения осуществляются одновременно с переписыванием GC на C#, а значит его код становится куда доступнее, понятнее и безопаснее. Подробности можно почитать в статье от Microsoft.
Другие изменения коснулись JIT компиляции, асинхронности и многих методов базовой библиотеки. Это касается методов, относящихся к работе со строками, регулярными выражениями и, что особенно важно, с коллекциями и сериализацией. Во все той же статье приводится много примеров таких изменений, с соответствующими пулл-реквестами и бенчмарками.
Изменения в JSON сериализации выглядят особенно впечатляюще. Только посмотрите на результаты бенчмарка по сериализации больших массивов!
private MemoryStream _stream = new MemoryStream();
private DateTime[] _array = Enumerable.Range(0, 1000).Select(_ => DateTime.UtcNow).ToArray();
[Benchmark]
public Task LargeArray()
{
_stream.Position = 0;
return JsonSerializer.SerializeAsync(_stream, _array);
}
Коротко — пятый дотнет сильно вырос в производительности и это важнейшая часть нового релиза. Большинство стандартных веб-приложений могут ожидать прирост производительности на 20% и выше, а отдельные приложения могут и вовсе ускориться в несколько раз.
Прочее
Помимо глобальных улучшений платформы Microsoft также неплохо поработали над отдельными библиотеками.
Например, в новой версии дотнета сильно улучшилась поддержка десктопа. WinForms и WPF наконец-то получили все преимущества .NET Core — классный перфоманс, упаковка всего приложения в один .exe, работа без установленного на машине дотнета и… и нет, не кроссплатформенность. Все это работает только под Windows.
Помимо прочего, для десктопной разработки под Windows также добавили нормальный визуальный дизайнер, тулинг, новые контролы и улучшенную поддержку для старых. Словом — если вы разрабатываете приложения с использованием WinForms или WPF, ваша жизнь станет лучше.
С кроссплатформенностью все осталось по-прежнему. Релиз MAUI перенесли на .NET 6, а других решений для кроссплатформенного десктопа Microsoft пока не предлагает. Так что продолжаем использользовать Авалонию (или можно обратить свое внимание на Uno Platform — перспективно выглядящий фреймворк для разработки на все и сразу).
Еще больше улучшений появилось для фулстек веб-разработки с использованием Blazor. Главное из них это улучшения производительности — Microsoft обещают, что WebAssembly версия Blazor ускорится аж в три раза. Одной из основных причин такого роста производительности стал пререндер на стороне сервера.
А еще добавили ленивую подгрузку зависимостей, изоляцию CSS/JS в рамках файла, новые контролы и многое другое. В общем, если вы собирались попробовать Blazor, но все никак не доходили руки — сейчас он выглядит куда более production-ready технологией.
Из оставшихся изменений заметнее всего смотрятся те, которые призваны помочь микросервисам и работе с облачными сервисами в целом. Здесь и уменьшение размеров Docker-контейнеров, и улучшенная поддержка gRPC, и поддержка OpenAPI по умолчанию, и многое другое. Кстати, Azure полностью поддерживает .NET 5 со дня релиза.
А еще Microsoft выкатили Project Tye, который как раз является инструментом для удобного управления микросервисами. На текущий момент трудно сказать, стоит ли использовать Tye в продакшене, но обратить внимание и поиграться с ним в свободное время определенно нужно.
Коротко — Microsoft улучшили поддержку отдельных инструментов и добавили приятных фич для облака. Если вы используете WinForms, WPF или Blazor — обновиться определенно стоит.
Регистрация ethtool
— это программа, управляемая из командной строки. С её помощью вы можете получать и настраивать различные драйверы и опции оборудования. Под Ubuntu эту программу можно установить так: apt-get install ethtool.
Обычно ethtool применяется для сбора с сетевых устройств детальной статистики. Другие способы применения будут описаны ниже.
Программа общается с драйверами с помощью системного вызова ioctl. Драйвер устройства регистрирует серию функций, выполняемых для операций ethtool, а ядро обеспечивает glue.
Когда ethtool вызывает ioctl, ядро находит структуру ethtool, зарегистрированную соответствующим драйвером, и выполняет зарегистрированные функции. Реализация функции драйвера ethtool может делать все что угодно — от изменения простого программного флага в драйвере до управления тем, как физическое оборудование NIC работает через записи значения регистров в устройство.
Драйвер igb с помощью вызова igb_set_ethtool_ops регистрирует в igb_probe операции ethtool:
static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
/* ... */
igb_set_ethtool_ops(netdev);
Весь ethtool-код драйвера igb вместе с функцией igb_set_ethtool_ops можно найти в файле
Взято из drivers/net/ethernet/intel/igb/igb_ethtool.c:
void igb_set_ethtool_ops(struct net_device *netdev)
{
SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops);
}
Помимо этого, вы можете найти структуру igb_ethtool_ops с поддерживаемыми драйвером igb функциями ethtool, настроенными в соответствующих полях.
Взято из drivers/net/ethernet/intel/igb/igb_ethtool.c:
static const struct ethtool_ops igb_ethtool_ops = {
.get_settings = igb_get_settings,
.set_settings = igb_set_settings,
.get_drvinfo = igb_get_drvinfo,
.get_regs_len = igb_get_regs_len,
.get_regs = igb_get_regs,
/* ... */
Каждый драйвер по своему усмотрению решает, какие функции ethtool релевантные и какие нужно реализовать. К сожалению, не все драйверы реализуют все функции ethtool.
Довольна интересна функция get_ethtool_stats, которая (если она реализована) создаёт подробные статистические счётчики, которые отслеживаются либо программно драйвером, либо самим устройством.
В посвящённой мониторингу части мы рассмотрим, как использовать ethtool для получения этой статистики.
Регистрация обработчика прерываний
После включения NAPI нужно зарегистрировать обработчика прерываний. Устройство может генерировать прерывания разными способами: MSI-X, MSI и легаси-прерывания. Поэтому код может быть различным, в зависимости от поддерживаемых способов.
Драйвер должен определить, какой способ поддерживается данным устройством, и зарегистрировать соответствующую функцию-обработчика, которая выполняется при получении прерывания.
Некоторые драйверы, в том числе и igb, пытаются зарегистрировать обработчика для каждого способа, в случае неудачи переходя к следующему неопробованному.
Предпочтительнее использовать прерывания MSI-X, особенно для сетевых карт, поддерживающих несколько очередей приёма. Причина в том, что каждой очереди присвоено собственное аппаратное прерывание, которая может быть обработано конкретным CPU (с помощью irqbalance или модифицирования /proc/irq/IRQ_NUMBER/smp_affinity).
Если MSI-X недоступна, то драйвер использует MSI (если поддерживается), которая всё ещё имеет преимущества по сравнению с легаси-прерываниями. Подробнее об этом читайте в английской Википедии.
В драйвере igb в качестве обработчиков прерываний MSI-X, MSI и легаси выступают соответственно функции igb_msix_ring, igb_intr_msi, igb_intr.
Код драйвера, пробующий каждый способ, можно найти в drivers/net/ethernet/intel/igb/igb_main.c:
static int igb_request_irq(struct igb_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
int err = 0;
if (adapter->msix_entries) {
err = igb_request_msix(adapter);
if (!err)
goto request_done;
/* переход к MSI */
/* ... */
}
/* ... */
if (adapter->flags & IGB_FLAG_HAS_MSI) {
err = request_irq(pdev->irq, igb_intr_msi, 0,
netdev->name, adapter);
if (!err)
goto request_done;
/* переход к легаси */
/* ... */
}
err = request_irq(pdev->irq, igb_intr, IRQF_SHARED,
netdev->name, adapter);
if (err)
dev_err(&pdev->dev, "Error %d getting interruptn", err);
request_done:
return err;
}
Как видите, драйвер сначала пытается использовать обработчика igb_request_msix для прерываний MSI-X, если не получается, то переходит к MSI. Для регистрации MSI-обработчика igb_intr_msi используется request_irq. Если и это не срабатывает, драйвер переходит к легаси-прерываниям. Для регистрации igb_intr снова используется request_irq.
Таким образом драйвер igb регистрирует функцию, которая будет выполняться при генерировании сетевой картой прерывания, сигнализирующего о получении данных и их готовности к обработке.
Фильтрование ntuple для управления сетевыми потоками
Некоторые сетевые карты поддерживают функцию «фильтрование ntuple» (ntuple filtering). Она позволяет указывать (посредством ethtool) набор параметров, используемых для фильтрования входных данных на уровне железа и адресации в конкретную очередь приёма. Например, можно прописать, чтобы TCP-пакеты, пришедшие на определённый порт, передавались в очередь 1.
В сетевых картах Intel эта функция обычно называется Intel Ethernet Flow Director. Другие производители могут давать другие названия.
Как мы увидим дальше, фильтрование ntuple — критически важный компонент другой функции, Accelerated Receive Flow Steering (aRFS). Это сильно облегчает использование ntuple, если ваша сетевая карта поддерживает его. aRFS мы рассмотрим позднее.
Эта функция может быть полезна, если операционные требования системы подразумевают максимизацию локальности данных (data locality) ради увеличения частоты успешных обращений (hit rates) к кэшу CPU при обработке сетевых данных. Например, так выглядит конфигурирование веб-сервера, работающего на порте 80:
Как упоминалось выше, фильтрование ntuple можно настроить с помощью ethtool, но для начала вам нужно удостовериться, что эта функция включена на вашем устройстве. Проверить это можно так:
$ sudo ethtool -k eth0
Offload parameters for eth0:
...
ntuple-filters: off
receive-hashing: on
Как видите, ntuple-filters в состоянии off.
Включим ntuple-фильтры:
$ sudo ethtool -K eth0 ntuple on
После их включения или проверки, что фильтры работают, можно проверить настроенные правила:
$ sudo ethtool -u eth0
40 RX rings available
Total 0 rules
Здесь фильтры не имеют настроенных правил. Вы можете добавить их через командную строку с помощью ethtool. Давайте пропишем, чтобы весь TCP-трафик, приходящий на порт 80, переадресовывался очередь приёма 2:
$ sudo ethtool -U eth0 flow-type tcp4 dst-port 80 action 2
Фильтрование ntuple можно использовать и для отбрасывания пакетов определённых потоков на аппаратном уровне. Это бывает удобно для снижения нагрузки по трафику от каких-то IP-адресов. Подробнее о конфигурации правил фильтрации читайте man ethtool.
Получать статистику о степени успешности своих ntuple-правил можно с помощью проверки выходных данных ethtool -S [device name]. Например, на сетевых картах Intel fdir_match и fdir_miss выдают количество совпадений и промахов правил фильтрования. По вопросам отслеживания статистики своего устройства сверьтесь с исходниками драйвера и спецификацией.
Цикл обработки net_rx_action
net_rx_action начинает обработку пакетов из памяти, которые были отправлены туда устройством посредством DMA.
Функция итерирует по списку структур NAPI, стоящих в очереди текущего CPU, поочерёдно извлекает каждую структуру работает с ней.
Цикл обработки ограничивает объём работы и время исполнения зарегистрированных NAPI-функций poll. Он делает это двумя способами:
- отслеживая рабочий бюджет (work budget) (который можно настраивать),
- а также проверяет затраченное время.
Взято из
while (!list_empty(&sd->poll_list)) {
struct napi_struct *n;
int work, weight;
/* Если исчерпалось окно SoftIRQ - отфутболиваем
* Выполняйте это в течение двух тиков, это позволит сделать
* среднюю задержку на уровне 1.5/Гц.
*/
if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit)))
goto softnet_break;
Таким образом ядро не позволяет обработке пакетов занять все ресурсы CPU. budget — это весь доступный бюджет, который будет разделён на все доступные NAPI-структуры, зарегистрированные на этот CPU.
Это ещё одна причина, почему сетевые карты с несколькими очередями требуют аккуратной настройки привязки IRQ. Вспомните, что на CPU, который обрабатывает прерывания от устройства, будет также выполняться и обработчик SoftIRQ. И в результате на том же CPU работают вышеприведённый цикл и выполняются вычисления бюджета.
Системы с несколькими сетевыми картами, каждая из которых поддерживает несколько очередей, могут оказаться в ситуации, когда на один CPU зарегистрировано несколько NAPI-структур. Обработка данных всех структур на одном CPU «оплачивается» из одного и того же бюджета.
Если вам не хватает CPU для распределения прерываний, то можно увеличить net_rx_action budget, чтобы каждый CPU обрабатывал больше пакетов. Увеличение бюджета повлечёт увеличение нагрузки на CPU (в особенности sitime или si в top или других программах), но должно снизить задержку, потому что данные будут обрабатываться быстрее.
Примечание: CPU будет ограничен по времени двумя jiffies, вне зависимости от присвоенного бюджета.
Языковое
Вместе с .NET 5 вышла и девятая версия C#. Официальную страничку с изменениями вы можете найти на сайте Microsoft, но давайте попробуем разобраться — что именно здесь стоит внимания?
Самое заметное изменение — это record-типы, позволяющие избавиться от бойлерплейта при написании DTO. Записи — это иммутабельные ссылочные типы с простым и коротким объявлением. В них по умолчанию определены методы Equals, HashCode, Copy, Clone, PrintMembers и ToString — разумеется, все они используют значения полей типа для выполнения операций. То есть Equals корректно сравнивает две записи по значениям, а не по ссылке.
Также записи поддерживают синтаксис копирования с изменением значений полей через with, например:
var person = new Person { FirstName = "Mads", LastName = "Nielsen" };
var otherPerson = person with { LastName = "Torgersen" };
Больше о применении записей вы можете почитать в блоге Владимира Хорикова и в публикации от Konrad Kokosa.
Другое важное изменение — это обновленный pattern matching. Теперь паттерны могут настраиваться по типам и операторам сравнения, причем несколько разных сравнений вы можете объединять через логические операторы. Например:
DeliveryTruck t when t.GrossWeightClass switch
{
< 3000 => 10.00m - 2.00m,
>= 3000 and <= 5000 => 10.00m,
> 5000 => 10.00m 5.00m
}
Остальные изменения не столь заметны — они касаются верхнеуровневых программ (возможность писать короткие программы без базового класса и функции main), упрощенного синтаксиса для new (без указания типа), init-only сеттеров и прочего.
Последние изменения в новом C#, которые хотелось бы упомянуть — это расширенная поддержка для source generators. Этот функционал позволяет генерировать код при компиляции проекта и зачастую очень удобен для авторов библиотек. В новом релизе работу с генераторами кода сделали чуть проще, расширив функционал partial классов (с них сняли некоторые из старых ограничений) и добавив инициализаторы модулей (методы, которые вызываются до первого доступа к любому полю/методу модуля).Хороший пример работы с генераторами кода вы можете найти в этой статье на Medium.
Отдельно стоит рассказать про F# 5. В новой версии языка добавилась масса классных возможностей для скриптов (например, директива для подключения nuget пакетов), slicing для более удобной работы с данными, а также улучшилась работа с quotation expressions и computation expressions.
Коротко — язык оброс разнообразным сахаром. Самое заметное изменение в C# 9 — это записи, но едва ли оно само по себе стоит обновления. С другой стороны, если вы будете обновлять версию дотнета по каким-то другим причинам, то у вас появится новый функционал, делающий язык чуть более мощным. Мелочь, а приятно.