Spin locks, semáforos, mutexes, conclusões no Linux

       Raça e simultaneidade são relativamente fáceis de ocorrer no Linux. Operações atômicas só podem ser executadas em números inteiros. Portanto, mutexes e bloqueios de rotação são freqüentemente usados ​​para proteger recursos críticos para resolver problemas de raça e simultaneidade.

Uso de mutex e spinlock:

       No contexto do processo, um mutex pode ser usado por um longo tempo de espera, porque pode dormir, e um bloqueio de rotação pode ser usado por um curto tempo de espera para reduzir o tempo de troca de contexto. Spin locks podem ser usados ​​em contextos de interrupção, mas mutexes não podem ser usados ​​porque podem dormir. No entanto, antes que o contexto de interrupção adquira o bloqueio de rotação, a interrupção local deve ser desativada para evitar o aninhamento de interrupção. O código com spinlocks não pode dormir e não pode ser usado recursivamente, caso contrário, causará um impasse.

Quantidade de sinal:

O semáforo é o meio mais típico utilizado pelo sistema operacional para exclusão mútua e sincronização, e seu valor pode ser 0, 1 ou n. A operação P e a operação V podem ser executadas, e também são operações atômicas, que não serão interrompidas durante a execução.

P(s): Decresça 1 do valor de s, se s >= 0, o processo continua a executar, caso contrário, coloque o processo em estado de espera, entre em suspensão e entre na fila de espera. Ou seja, a operação para baixo

V(s): Some 1 ao valor de s, se s > 0, acorda o processo esperando o semáforo na fila. Ou seja, a operação UP.

  • struct semáforo sem; a definição de semáforo
  • void sema_init(struct semaphore *sem, int val): Inicializa e define o valor do semáforo sem para val.
  • void down (struct semaphore *sem ); o semáforo é decrementado em 1, ele irá dormir e não pode ser usado no contexto de interrupção.
  • int down_interruptibleistruet semaphore * sem); é consistente com a função down, mas o processo de entrada no estado de suspensão pode ser interrompido pelo sinal, e o sinal também fará com que a função retorne. Neste momento, o valor de retorno da função não é 0.
  • int down_trylock (struct semáforo* sem); Esta função tenta obter o semáforo sem. Se puder ser obtido imediatamente, obterá o semáforo e retornará 0, caso contrário, retornará um valor diferente de zero. Não faz com que o chamador durma e pode ser usado no contexto de interrupção.
  • vaid up (struct semáforo * sem ) Libere o semáforo sem e acorde o garçom.

Quando usado como exclusão mútua, processo 1: P(s)--->seção crítica--->V(s). Mas o kernel do Linux prefere o mutex como meio de exclusão mútua.

Quando usado como uma sincronização: ---> Processo 1 executa para baixo (p) e espera ----> Processo 2: para cima (v) -----> Processo 1 executa:

processo 1 processo 2
para baixo (p) o código
espere para cima(v)
o código

bloqueio de rotação:

        O bloqueio de rotação é um meio típico de exclusão mútua de recursos críticos. Para obter um bloqueio de rotação, uma operação atômica será executada primeiro em uma determinada CPU. Esta operação é para testar e definir uma determinada variável de memória. O resultado do teste indica que o bloqueio está livre. O programa obtém o bloqueio de rotação e continua para executar recursos críticos, como O resultado do teste indica que está ocupado, e o programa irá rodar em círculos, continuamente obtendo recursivamente se o bloqueio está livre, até que o bloqueio esteja livre, e então continuar a executar os recursos críticos.

  • spinlock_t lock; //Define o bloqueio de rotação
  • spin_lock_init (lock) //Inicializa o bloqueio de rotação
  • spin_lock (lock) //Obtém o bloqueio de rotação e retorna imediatamente, caso contrário, ele girará até ser liberado e retornar
  • spin_unlock (lock) // libera o bloqueio de rotação

Mutex:

A exclusão mútua de recursos críticos é um método comum de exclusão mútua no kernel do Linux. É o mesmo que a exclusão mútua do semáforo e irá dormir após a exclusão mútua. O uso é consistente com a exclusão mútua do semáforo e é usado no contexto do processo.

  • struct mutex my_mute //definição de mutex
  • mutex_init{&my_mutex.); //Inicialização
  • void mutex_lock(struct mutex *lock); //Pega o mutex
  • void mutex_unlock(struct mutex*lock); //libera o mutex

Quantidade concluída:

O papel da quantidade de conclusão pode ser usado para sincronização. Um processo espera que outro processo conclua uma tarefa antes de continuar a executar:

  • conclusão da estrutura my_completion; // definição do valor da conclusão
  • init_completion ( &my_completion); // Inicializa a quantidade de conclusão, o valor inicial é 0
  • void wait_for_completion (struct completado *c); //aguarde a conclusão para ser ativado
  • void complete (struct completação *e); //É hora de acordar
  processo 1 processo 2
o código wait_for_completion
completo  ....espere
continuar a executar

おすすめ

転載: blog.csdn.net/weixin_42432281/article/details/126286520