Я нашел его после прочтения этого ответа суперпользователя , отмечая этот комментарий
Но не для PID (-p), потому что он печатает только конкретный процесс, а для сеанса (-g)
и экспериментального
ps f -g
результата
$ ./script.sh $$
PID TTY STAT TIME COMMAND
14492 pts/24 Ss 0:00 -bash
9906 pts/24 S+ 0:00 \_ bash ./script.sh 14492
9907 pts/24 R+ 0:00 \_ ps f -g14492
Я сам отвечу на свой вопрос, так как сам читал исходный код и занимался исследовательской работой. Если бы я сам не провел некоторую исследовательскую работу, мне очень помогли бы ответы Frostschutz и Sourcejedi — они кажутся правильными, насколько я знаю (, хотя и не так подробно, но они дают вам отправной точкой, чтобы провести остальную часть исследования самостоятельно ).
Немного теории :Существует два вида дисциплин организации очередей :классовые и бесклассовые.
Классовые дисциплины (как говорится в ответе sourcejedi )гибкие. Они позволяют вам присоединять к ним дочерние классовые qdisc и могут совместно использовать полосу пропускания с другими классами, когда это возможно.Листовые классы имеют бесклассовый qdisc (elementary/fundamental qdisc ), прикрепленный к ним (, также называемый элементарным qdisc ). Очереди, управляемые этими элементарными qdisc, — это место, где пакеты помещаются в очередь и удаляются из очереди. Пакеты удаляются из очереди и помещаются в очередь из этих классов с помощью алгоритма, соответствующего классу. Примерами классовых qdisc являются :HTB и CBQ.
Бесклассовые qdisc — это фундаментальные или элементарные qdisc, которые являются жесткими в том смысле, что к ним не могут быть прикреплены дочерние qdisc, а также они не могут совместно использовать полосу пропускания. Говоря наивным языком, они предоставлены сами себе. Эти qdisc владеют очередью, из которой они ставят в очередь и удаляют пакеты в соответствии с алгоритмом, соответствующим qdisc. Примеры бесклассового qdisc :pfifo, bfifo, pfifo _fast (по умолчанию, используемые в Linux tc ), tbf, sfq и некоторые другие.
В примере дерева в вопросе каждый из листовых классов htb 1 :1, 1 :2 и 1 :3 имеет прикрепленный к нему элементарный qdisc, который по умолчанию является pfifo (не pfifo _быстро ). Элементарный qdisc, прикрепленный к листу, можно изменить с помощью пользовательской утилиты tc
следующим образом:
tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5
tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10
Более подробную информацию об этом можно найти в руководстве по организации очередей HTB Linux . Поэтому дерево на самом деле выглядит так:
1: root qdisc (class htb)
(100)
/ | \
/ | \
/ | \
1:1 1:2 1:3 parent qdiscs (class htb)
(30) (10) (60)
|| || || -----> pfifo qdiscs (queue length: txqueuelen (default, can be changed by tc utitlity))
Обратите внимание, что параметр txqueuelen является параметром, -специфичным для интерфейса. Это означает, что параметр является свойством интерфейса и может быть изменен с помощью iproute2
или ifconfig
. По умолчанию его значение равно 1000. Вот пример того, как изменить его на 200 черезiproute2
:
ip link set eth0 txqueuelen 200
Когда конечный узел создается (в контексте HTB qdisc ), pfifo qdisc по умолчанию присоединяется к листовому классу. Этот pfifo инициализируется с ограничением очереди txqueuelen интерфейса. Это можно найти в функции htb_change_class()
в сч _htb.c ,строка 1395:
/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
* so that can't be used inside of sch_tree_lock
* -- thanks to Karlis Peisenieks
*/
new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
classid, NULL);
Длину очереди по умолчанию для очереди pfifo см. в sch _fifo.c , строка 61 :
.u32 limit = qdisc_dev(sch)->tx_queue_len;
Ядро напрямую взаимодействует с корневым qdisc (, может быть классовым или бесклассовым ), когда оно хочет поставить пакет в очередь или удалить из очереди. Если корневой qdisc является классовым и имеет потомков, то он сначала классифицирует пакет (и решает, какому потомку отправить пакет ). Исходный код ядра, где это делается:sch _htb.c , строка 209:
static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
int *qerr)
Читая комментарии, можно легко сделать вывод, что эта функция возвращает одно из следующих:
NULL, если пакет нужно отбросить
-1, если пакет должен быть поставлен в очередь в прямую _очередь
листовой узел (который содержит элементарный qdisc, где фактически заканчиваются пакеты )Эта функция проходит через все внутренние узлы (Классы )дерева пока он не вернет конечный узел, где пакет должен быть поставлен в очередь.
При исключении из очереди каждый из классов следует алгоритму, связанному с их qdisc, чтобы решить, из какого из дочерних элементов исключить из очереди, и дочерние элементы делают то же самое, пока пакет не будет удален из очереди из элементарного qdisc, присоединенного к листовому классу. Это также гарантирует, что скорость дочернего класса не больше, чем у его родителя. (Так как родитель будет решать, пройдет пакет или нет ). Я не изучал источник удаления из очереди в htb, поэтому не могу предоставить его источник.
Прямая очередь:Это специальная внутренняя очередь fifo, поддерживаемая qdisc HTB, из которой пакеты удаляются из очереди с аппаратной скоростью. Длина его очереди равна txqueuelen. Пакет попадает в прямую очередь, если HTB не может отнести его к одному из дочерних qdisc, а значение по умолчанию не указано.
Итак, ответы на мои собственные вопросы:
Да,поскольку они являются листовыми узлами, по умолчанию они являются очередями pfifo с длиной очереди txqueuelen интерфейса, которая по умолчанию равна 1000 и может быть изменена.
Дисциплина обслуживания очередей подобна алгоритму вместе с очередью, объединенными в единый пакет! Если вы спросите меня, организация очереди является свойством как типа очереди, так и планировщика пакетов (, здесь планировщик пакетов означает алгоритм, который ставит пакет в очередь и удаляет из очереди ). Например, очередь может иметь тип pfifo или bfifo. Алгоритм, используемый для постановки в очередь и удаления из очереди, одинаков, но длина очереди измеряется в байтах для байта fifo (bfifo ). Пакеты сбрасываются в bfifo, когда достигается лимит байтов. Предел байтов по умолчанию рассчитывается как mtu*txqueuelen
. Например, когда пакет ставится в очередь, длина пакета добавляется к текущей длине очереди. Точно так же, когда пакет исключен из очереди, длина пакета вычитается из длины очереди.
Ответ выше.
Некоторые источники, к которым можно обратиться:
Отказ от ответственности:У меня много вопросов, а я не использовал HTB уже лет десять? Так что с уверенностью ответить не могу. Но так как вы пока не получили ни одного ответа, возможно, это все же поможет.
Are there internal queues maintained for each of the parent htb classes (1:1, 1:2 and 1:3)?
Это конечные классы, и каждый из них представлен структурой очереди qdisc, поэтому я предполагаю, что это считается внутренними очередями. Не уверен насчет длины очереди -извините.
struct htb_class_leaf {
int deficit[TC_HTB_MAXDEPTH];
struct Qdisc *q;
} leaf;
структура Qdisc определена в include/net/sch _generic.h
What exactly is meant by Queueing Discipline (QDisc)?
Это зависит от контекста, но в основном это API ядра, в котором пакеты ставятся в очередь и удаляются из очереди; таким образом, QDisc получает некоторый контроль над порядком (или временем, когда )входящие пакеты должны снова отправляться (или вообще отбрасываться, даже ). Вот как QDisc, такие как HTB, SFQ или PRIO, затем формируют трафик различными способами, например, расставляют приоритеты или накладывают ограничения на пропускную способность.
Generally, queueing discipline ("qdisc") is a black box,
which is able to enqueue packets and to dequeue them (when
device is ready to send something) in order and at times
determined by algorithm hidden in it.
И HTB — лишь один из нескольких таких алгоритмов.
What is a direct_queue?
Не является частью API, но обрабатывается внутри... так что вы можете считать это частью алгоритма HTB.
Если вы намеренно относите пакеты к X:0
или если класс по умолчанию не существует, HTB решил поместить их в отдельную очередь, и при исключении из очереди он попытается отправить эти пакеты первыми.
* [...] If we end up with classid MAJOR:0 we enqueue the skb into special
* internal fifo (direct). These packets then go directly thru. If we still
* have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful
* then finish and return direct queue.
... и здесь он сначала удаляет из очереди прямые пакеты .
Обычно это результат неправильной конфигурации (отправки пакетов несуществующему классу ), но разработчики HTB решили, что в этом случае весь трафик должен быть пропущен, а не отброшен весь трафик (слишком разрушительно ).
Некоторые быстрые поиски на основе смутных воспоминаний:
HTB является гибким. По умолчанию я думаю, что вы получаете FIFO для каждого листового класса, возможно, он использует конфигурацию по умолчанию для FIFO. Однако вы также можете, например. используйте PFIFO или FQ _CODEL для конечного класса. См., например. «необязательно прикрепите дисциплины очередей к листовым классам» здесь:http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm
Думаю, вы их увидите, если побежите tc qdisc show
.
«Эта «прямая» очередь используется только в том случае, если один из ваших фильтров явно нацелен на «0» classid htb qdisc»https://lists.bufferbloat.net/pipermail/cerowrt-devel/2013-June/006507.html. Прямая очередь не формируется. Судя по всему, длину прямой очереди теперь можно контролировать, хотя я не знаю, как (и поддерживает ли это )tc.https://patchwork.ozlabs.org/patch/225546/
Я бы не сказал, что есть отдельный "планировщик пакетов". Планировщик пакетов представляет собой QDisc (, хотяman tc-tbf
описывает себя как «никогда не планирующий трафик»; это означает, что он никогда не -приказывает ему ).