Como o kernel do Linux sabe que colisões ocorreram no domínio de colisão Ethernet?

2

Digamos que eu tenha uma topologia de rede a seguir:

Alarguradebandatotalteórica(Tx+Rx)paratodososquatrohostsnototaléde100Mbps.Agora,seeuexecutar Iperf no modo UDP em todos os quatro hosts simultaneamente e forçar cada instância Iperf a colocar 50Mbps ( -b 50m in Cliente Iperf) do tráfego no fio, então o Iperf não coloca muito tráfego no fio. Isso ocorre porque as NICs recebem colisões e, portanto, o cliente Iperf recebe -1 como um valor de retorno para algumas de suas chamadas do sistema write() para o soquete UDP. Embora eu entenda como o kernel e o cliente Iperf se comunicam, não entendo muito bem como o NIC e o kernel se comunicam. Isso acontece com o driver da NIC ( tg3 para minha BCM5721 NIC)? Existe algum tipo de chamada de sistema que informa ao kernel que ocorreram colisões?

    
por Martin 08.08.2015 / 02:07

1 resposta

3

O kernel e o NIC comunicam da mesma forma que o kernel (especificamente, um driver de dispositivo, que faz parte do kernel) comunica-se com qualquer outro dispositivo (por exemplo, dispositivo de comunicação serial (como teclado, mouse ou RS232), disco (ou dispositivo de armazenamento em massa tipo disco), display, token de segurança, etc.) - eles falam diretamente um com o outro. Então, sim, isso acontece dentro do driver da NIC. Não, a comunicação do dispositivo do driver não passa por uma chamada do sistema.

Os drivers de dispositivos se comunicam com dispositivos, geralmente, por meio de dois métodos de acesso: E / S Mapeada na Memória (MMIO) e E / S Mapeada na Porta (PMIO). Estes são descritos e discutidos com alguma extensão em Super User nessas duas perguntas:

Veja também O que é um driver e como ele funciona? se você precisar da informação de fundo. BTW, cujo método de acesso é usado é determinado pela arquitetura do computador. Por exemplo, Wikipedia diz: “E / S mapeada de memória é preferida em arquiteturas baseadas em x86 …”

Voltando à sua pergunta específica, se assumirmos a E / S mapeada na memória, o driver poderia testar a colisão com o código C tão simples quanto

        if (nic->error_status & COLLISION)
        {
                // We get here if there was a collision.
                (code to handle collision)
                           ⋮
        }

(onde nic é um ponteiro para o endereço mapeado da NIC) e é uma questão trivial, então, o driver causar um erro para ser retornado ao processo do usuário da chamada do sistema write() .

Pergunta de acompanhamento:

Does the fact that drivers are part of the kernel mean that there is no driver ↔ kernel communication method?

Isso pode valer a pena ser perguntado como outra pergunta (ou pelo menos fazendo mais pesquisas, ou seja, pesquisas na web). Originalmente, o kernel do Unix era monolítico (veja também kernel monolítico ). A relação entre o kernel e os drivers era como a relação entre um corpo humano e suas mãos - as mãos são distintas, e nunca seria confundido com, digamos, cotovelos ou pulmões - mas eles são parte integrante do corpo.

Mesmo em máquinas que tinham quatro anéis de proteção , o Unix usava apenas dois - o núcleo estava no anel 0 e a terra do usuário era o anel 3. Existem outros sistemas operacionais onde os drivers de dispositivo são análogos ao garfo e garfo - um nível removido (por exemplo, os condutores estão em um dos anéis intermediários (1 e / ou 2)). Eu não acompanhei todos os desenvolvimentos em * nix / Linux (por exemplo, LKMs ) e alguns unices podem ter um maior grau de separação entre o kernel de base e os drivers do que outros. Por exemplo, veja

Como eu disse, este material está no limite da minha base de conhecimento; não me pergunte mais sobre o assunto acima.

Mas também, a questão é semanticamente ambígua. O corpo se comunica com as mãos? Sim, através do sistema nervoso (e, até certo ponto, do esqueleto). O “kernel” se comunica com drivers de dispositivos (que fazem parte do kernel)? Sim, no mesmo sentido que programas C (por exemplo, cat , cp , ls , sed , etc.) comunicar com a biblioteca C - através de chamadas de sub-rotina (e talvez o uso ocasional e criterioso de variáveis globais). Quando um processo do usuário chama uma chamada do sistema relacionada à E / S (por exemplo, open() , close() , read() , write() , ioctl() , poll() , select() , etc.), o código de manipulação de syscall de uso geral (no kernel) chama a rotina de driver de dispositivo apropriada (possivelmente com alguma lógica intermediária). O código relacionado ao sistema de arquivos também chama as rotinas de driver de disco apropriadas. E o kernel, pelo menos, facilita a invocação de manipuladores de interrupção específicos do dispositivo quando as interrupções são recebidas (implementações variam).

    
por 08.08.2015 / 07:46