Por que a API do módulo Linux não é compatível com versões anteriores?
Por que a API do módulo Linux não é compatível com versões anteriores? Estou frustrado por encontrar drivers atualizados depois de atualizar o kernel do Linux.
Eu tenho um adaptador sem fio que precisa de um driver proprietário, mas o fabricante descontinuou este dispositivo há cerca de 7 anos. Como o código é muito antigo e foi escrito para Linux 2.6.0.0, ele não compila com os kernels Linux mais recentes. Eu usei muitas distribuições Linux, mas o mesmo problema está em toda parte. Embora exista um driver de código aberto distribuído com o kernel do Linux, ele não funciona. Algumas pessoas estão tentando modificar o antigo código proprietário para torná-lo compatível com os kernels Linux mais recentes, mas quando um novo kernel Linux é lançado, leva meses para tornar o código compatível com ele. Nesse período, outra nova versão é lançada. Por esse motivo, não posso atualizar para um novo kernel do Linux; às vezes nem consigo atualizar minha distribuição.
Respostas
Greg Kroah-Hartman escreveu sobre este tópico aqui:https://www.kernel.org/doc/html/v4.10/process/stable-api-nonsense.html
Além de alguns detalhes técnicos sobre a compilação do código C, ele destaca alguns problemas básicos de engenharia de software que tomam sua decisão.
Linux Kernel é sempre um trabalho em andamento. Isso acontece por muitos motivos:
- Novas exigências surgem. As pessoas querem que seu software faça mais, é por isso que a maioria de nós atualiza, queremos os melhores e mais recentes recursos. Isso pode exigir retrabalho no software existente.
- São encontrados erros que precisam ser corrigidos, às vezes os erros estão no próprio design e não podem ser corrigidos sem um retrabalho significativo
- Novas ideias e expressões no mundo do software acontecem e as pessoas encontram maneiras muito mais fáceis/elegantes/eficientes de fazer as coisas.
Isso é verdade para a maioria dos softwares , e qualquer software que não seja mantido terá uma morte lenta e dolorosa . O que você está perguntando é por que esse código antigo não mantido ainda funciona?
Por que as interfaces antigas não são mantidas?
Garantir a compatibilidade com versões anteriores exigiria que as interfaces antigas (geralmente "quebradas" e inseguras) fossem mantidas. Claro que é teoricamente possível fazer isso, exceto que acarreta um custo significativo .
Greg Kroah-Hartman escreve
Se o Linux tivesse que garantir a preservação de uma interface de fonte estável, uma nova interface teria sido criada e a mais antiga e quebrada teria que ser mantida ao longo do tempo, levando a um trabalho extra para os [desenvolvedores]. Como todos os Linux [desenvolvedores] fazem seu trabalho em seu próprio tempo, pedir aos programadores que façam trabalho extra sem ganho, de graça, não é uma possibilidade.
Mesmo que o Linux seja de código aberto, ainda há apenas um tempo limitado do desenvolvedor para mantê-lo. Portanto, a mão de obra ainda pode ser discutida em termos de "custo". Os desenvolvedores devem escolher como gastam seu tempo:
- Gaste muito tempo mantendo interfaces antigas/quebradas/lentas/inseguras. Às vezes, isso pode ser o dobro ou o triplo do tempo necessário para escrever a interface na primeira instância.
- Jogue fora as interfaces antigas e espere que outros mantenedores de software [façam seu trabalho e] mantenham seu próprio software.
Em suma, as interfaces de binning são realmente econômicas (para os desenvolvedores do kernel) . Se você quer saber por que os desenvolvedores não gastam meses e anos de suas vidas evitando que você pague US $ 10 por um novo adaptador wifi ... esse é o motivo. Lembre-se de que é uma economia de tempo/custo para os desenvolvedores do kernel, não necessariamente econômica para você ou para os fabricantes.
Embora eu tenha contribuído com alguns patches (muito pequenos) para o kernel do Linux, não me considero um desenvolvedor do kernel. No entanto, aqui está o que eu sei:
Um driver escrito para a versão 2.6.0.0 do kernel é anterior à eliminação do Big Kernel Lock (BKL) que ocorreu na versão 2.6.39 do kernel.
O BKL foi criado quando o Linux ainda era um sistema operacional de processador único (single-core, single-thread). Assim que o suporte SMP foi adicionado, os desenvolvedores reconheceram que o BKL se tornaria um grande gargalo em algum momento, mas desde que houvesse apenas alguns núcleos/threads no sistema no total, era um tanto tolerável. Mas primeiro se tornou um problema real para as pessoas que usam o Linux em supercomputadores e, assim, o trabalho começou a substituir tudo o que precisava do BKL por mecanismos de bloqueio mais refinados ou, sempre que possível, por métodos sem bloqueio.
Em computadores modernos, que podem ter números de núcleos de dois dígitos em desktops comuns e laptops de alta potência, sem falar em servidores, uma API de módulo de kernel compatível com versões anteriores 2.6.0 também precisaria implementar BKL.
Se um módulo legado disser "Eu quero pegar o BKL", o restante do kernel não tem ideia do que o módulo está planejando fazer com ele e, portanto, o mecanismo de compatibilidade com versões anteriores teria que pegar todos os bloqueios que substituíram o BKL apenas para cobrir todas as possibilidades. Isso seria um grande sucesso de desempenho. E os novos métodos sem trava também precisariam verificar o bloqueio herdado - o que anula o ponto de ser sem trava em primeiro lugar. Portanto, a própria existência do mecanismo de compatibilidade com versões anteriores degradaria o desempenho do sistema, mesmo que nenhum módulo legado fosse realmente carregado.
Mais recentemente, os patches de segurança Spectre/Meltdown fizeram grandes mudanças no que precisa acontecer quando o limite do kernel/userspace está sendo ultrapassado. Quaisquer módulos compilados antes da implementação das correções Spectre/Meltdown podem não ser confiáveis com kernels pós-Specre/Meltdown.
Há apenas duas semanas, eu estava solucionando problemas em um servidor antigo que precisava de um ciclo de energia manual quando as atualizações de segurança eram aplicadas pela automação. Isso já havia acontecido várias vezes antes e era reproduzível. Descobri que ele tinha uma versão muito antiga do megasr
driver de armazenamento proprietário de antes dos patches Spectre/Meltdown, que não estava incluído nas atualizações automáticas. Depois de atualizar o driver para a versão atual, o problema desapareceu. A propósito, isso foi em um sistema RHEL 6.10 simples.
Também vi servidores travando ao carregar drivers proprietários de monitoramento de hardware pré-Spectre/Meltdown com um kernel pós-Spectre/Meltdown. Com base nessa experiência, estou totalmente convencido de que as correções do Spectre/Meltdown precisam ser tratadas como um divisor de águas: o kernel e os módulos precisam ser versões anteriores ou posteriores às correções; misturar e combinar só vai levar ao sofrimento e despertar à meia-noite para o administrador do sistema de plantão.
E como o Spectre era um problema de nível de design da CPU , é "um presente que continua dando": algumas pessoas encontrarão novas maneiras de explorar as fraquezas e, em seguida, os desenvolvedores do kernel precisarão descobrir maneiras de bloquear as explorações.
Esses são apenas dois dos grandes problemas que uma API de módulo de kernel legado compatível com 2.6.0.0 precisaria resolver. Tenho certeza de que existem muitos outros.
E depois há o lado mais filosófico. Pense nisso: o que torna o Linux possível?
Uma grande parte disso são especificações de hardware abertas . Se as especificações de hardware estiverem abertas, qualquer pessoa pode participar. Como o código-fonte do sistema operacional é aberto, qualquer um pode contribuir, para benefício de todos. E você não pode manter as especificações de programação de hardware como seu segredo comercial se o código do driver for de código aberto.
Os desenvolvedores do kernel do Linux tendem a acreditar no modelo de código aberto. É por isso que eles fizeram suas escolhas de design e desenvolvimento para que a maneira preferida de o fabricante de hardware participar seja abrir o código do driver, integrá-lo à distribuição principal do código-fonte do kernel e, então (e somente então ) você obtenha o benefício de toda a comunidade de desenvolvedores do kernel para mantê-lo.
Isso fornece algum incentivo aos designers e fabricantes de hardware para tornar isso possível. Se você tem algo que deseja manter em segredo, faça o esforço de encapsulá-lo em um ASIC ou talvez em um firmware assinado, se necessário. (Se você fizer o último, conceda a outros a permissão para redistribuir o pacote de firmware.)
Mas como o kernel é de código aberto, os desenvolvedores do kernel não podem exatamente impedir que outros mantenham drivers proprietários separadamente. Mas eles também não têm incentivo para se preocupar com eles.
Na verdade, o incômodo extra causado por drivers binários proprietários na depuração do kernel é um incentivo para o desenvolvedor do kernel não se preocupar com o desenvolvimento do driver proprietário: "Eles tornam meu trabalho mais difícil, por que devo fazer algo em particular para facilitar o trabalho deles?"
Portanto, os desenvolvedores do kernel geralmente fazem o que é mais vantajoso para eles como um grupo/comunidade. Se isso incluir alguma alteração na API do módulo, que assim seja. Os drivers de terceiros nem entram na equação.