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