AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 787287
Accepted
abg1984
abg1984
Asked: 2024-11-27 18:20:20 +0800 CST2024-11-27 18:20:20 +0800 CST 2024-11-27 18:20:20 +0800 CST

Implementação de unregister_chrdev_region()

  • 772

Então, atualmente estou aprendendo a escrever módulos de kernel/drivers de dispositivo e estava analisando a implementação de unregister_chrdev_region:

https://elixir.bootlin.com/linux/v6.12/source/fs/char_dev.c#L311

/**
 * unregister_chrdev_region() - unregister a range of device numbers
 * @from: the first in the range of numbers to unregister
 * @count: the number of device numbers to unregister
 *
 * This function will unregister a range of @count device numbers,
 * starting with @from.  The caller should normally be the one who
 * allocated those numbers in the first place...
 */
void unregister_chrdev_region(dev_t from, unsigned count)
{
    dev_t to = from + count;
    dev_t n, next;

    for (n = from; n < to; n = next) {
        next = MKDEV(MAJOR(n)+1, 0);
        if (next > to)
            next = to;
        kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
    }
}

O que não entendo é a verificação nesta linha:

https://elixir.bootlin.com/linux/v6.12/source/fs/char_dev.c#L318

if (next > to) next = to;

O loop, como eu vejo, já quebra quando a variável do loop é igual ao limite superior to = from + count. Quando teríamos o caso de encontrarmos o condicional if (next > to)? Qual é o motivo dessa verificação condicional?

linux-kernel
  • 2 2 respostas
  • 18 Views

2 respostas

  • Voted
  1. Best Answer
    Stephen Kitt
    2024-11-27T18:40:43+08:002024-11-27T18:40:43+08:00

    unregister_chrdev_regioncancela o registro de uma série de dispositivos, mas esse cancelamento de registro deve ser tratado por major using __unregister_chrdev_region. O loop lida com isso:

    • na entrada, né o início do alcance do dispositivo para o principal atual
    • next = MKDEV(MAJOR(n)+1, 0);extrai o número principal do dispositivo ne o usa para calcular o início do próximo intervalo principal
    • se nextfor maior que to, o intervalo atual estará totalmente contido no principal atual e o cancelamento do registro precisará parar em toem vez denext

    Em todos os casos, __unregister_chrdev_regioné chamado para cancelar o registro do que resta no intervalo principal atual e nexté definido como o início do próximo intervalo principal ou o fim do intervalo geral para que a próxima iteração do loop manipule o próximo intervalo principal ou saia se tudo tiver sido manipulado.

    Vamos dar um exemplo: se você pedisse para cancelar o registro de 1024 dispositivos começando no principal 1 e no secundário 512:

    • na entrada da função, fromé 1536, counté 1024
    • toé calculado em 2560
    • na entrada do loop, né 1536
    • nexté calculado em 2048 (maior 2)
    • 2048 é menor que 2560, então __unregister_chrdev_regioné chamado para cancelar o registro de 512 dispositivos começando em 1536
    • na próxima iteração do loop, né 2048
    • nexté calculado como 3072 (maior 3)
    • 3072 é maior que 2560, então nexté definido como to, e __unregister_chrdev_regioné chamado para cancelar o registro de 512 dispositivos a partir de 2048
    • na próxima iteração do loop, né 2560 e o loop termina
    • 0
  2. Marcus Müller
    2024-11-27T18:40:51+08:002024-11-27T18:40:51+08:00

    Você está interpretando mal o que o loop faz! O loop não é

    //                        vvv
    for(int n = from; n < to; n++) {
      /* Do something treating n as a constant each iteration */
    }
    

    que corre exatamente to - from == countvezes.

    É, em vez disso,

    //                        vvvvvvvv
    for(int n = from; n < to; n = next) {
       next = something_that_might_or_might_not_change_each_iteration();
    }
    

    nesse caso,

    next=MKDEV(MAJOR(n)+1, 0);
    

    Se você procurar a definição de MKDEVeMAJOR , verá que isso se expande para

    next =  ((n >> 20) + 1) << 20 | 0; 
    

    o que equivale a "arredondar para o próximo múltiplo de 2 20 (mesmo que njá seja um múltiplo)".

    Então, é bem provável que já na primeira iteração seu nextseja maior que to!

    • 0

relate perguntas

  • Como posso fazer meu console framebuffer funcionar?

  • Bloqueando montagem syscall

  • Por que a versão 30 das ferramentas sem fio se tornou uma versão beta permanente?

  • tamanho da pilha do programa

  • Quais dongles WiFi 802.11ac (ou posteriores) funcionam com o kernel Linux 4.13

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve