Ensine-o passo a passo, implemente o modelo de estado do processo 5 em linguagem C

prefácio

As máquinas de estado são amplamente utilizadas no desenvolvimento de trabalho real. Quando entrei na empresa, quando fiz um fluxograma com base nos produtos da empresa, descobri que muitas vezes perdi um ou outro estado, o que levou a problemas no processo geral. Mais tarde Eu conhecia o estado.Para algo como uma máquina, descobri que esta imagem pode expressar claramente o fluxo de todo o estado.

Yikoujun fez muitos módulos de protocolo de rede, e o desenvolvimento de muitos protocolos deve usar máquinas de estado; uma máquina de estado robusta pode fazer com que seu programa não entre repentinamente em uma ramificação de programa imprevisível, não importa quais emergências ocorram.

Este artigo implementa uma máquina de estado simples do modelo de estado do processo 5 através da linguagem C, para que você possa se familiarizar com o charme da máquina de estado.

O que é uma máquina de estado?

definição

Máquina de estado é a abreviação de autômato de estado finito, que é um modelo matemático abstraído das regras de execução de coisas reais.

Vamos primeiro explicar o que é um "estado". As coisas reais têm estados diferentes, como um LED, etc., existem dois estados de ligado e desligado. O que costumamos chamar de máquina de estados é uma máquina de estados finita, ou seja, o número de estados das coisas que estão sendo descritas é limitado, por exemplo, o estado de uma luz de LED é dois ligado e desligado.

Uma máquina de estado, ou Máquina de Estado, não se refere a uma máquina real, mas a um modelo matemático. Para ser franco, geralmente se refere a um diagrama de transição de estado.

Exemplo

Tomando o diagrama de lâmpada da aula de física como exemplo, é uma pequena máquina de estado básica.

 O seguinte diagrama de máquina de estado pode ser desenhado

 

Aqui estão dois estados: ① a lâmpada está acesa, ② a lâmpada está desligada Se o interruptor estiver ligado, então o estado mudará para a lâmpada acesa. Se o interruptor for desligado enquanto a lâmpada estiver acesa, o estado mudará para lâmpada desligada.

O nome completo da máquina de estado é autômato de estado finito, e a palavra "automático" também contém significados importantes. Dada uma máquina de estado, dado seu estado atual e entrada, o estado de saída pode ser calculado claramente. Por exemplo, para uma lâmpada, dado o estado inicial em que a lâmpada está desligada e a entrada fornecida "ligar o interruptor", o próximo estado pode ser calculado.

Quatro conceitos

Os quatro conceitos de máquina de estado são dados abaixo.

  1. Estado, o estado. Uma máquina de estado deve conter pelo menos dois estados. Por exemplo, no exemplo da lâmpada acima, existem dois estados: a lâmpada está ligada e a lâmpada está desligada.

  2. Evento, o evento. Um evento é um gatilho ou uma senha para executar uma ação. Para uma lâmpada, "ligar o interruptor" é um evento.

  3. Ação, a ação. Ações a serem executadas após a ocorrência de um evento. Por exemplo, o evento é "ligar o interruptor" e a ação é "acende a luz". Ao programar, uma Ação geralmente corresponde a uma função.

  4. Transição, transformação. Ou seja, mudar de um estado para outro. Por exemplo, o "processo light-on" é uma transformação.

Aplicação da máquina de estado

A máquina de estado é uma abstração do mundo real, e é uma abstração matemática logicamente rigorosa, portanto é obviamente muito adequada para uso no campo digital. Ele pode ser aplicado em vários níveis, como design de hardware, design de compilador e programação para implementar várias lógicas de negócios específicas.

Modelo de Estado do Processo 5

O gerenciamento de processos é um dos cinco principais subsistemas do Linux. É muito importante e muito complicado de implementar. Vamos ver como o processo muda de estado.

A figura a seguir é o modelo de 5 estados do processo:

 Uma breve introdução a esta figura é a seguinte:

  1. Estado executável: Quando o processo está sendo executado pela CPU, ou está pronto para ser executado pelo escalonador a qualquer momento, diz-se que o processo está em estado de execução (running). Os processos podem ser executados no modo kernel ou no modo de usuário. Quando os recursos do sistema estão disponíveis, o processo é despertado e entra no estado pronto para execução, que é chamado de estado pronto.

  2. Estado de sono leve (interruptível): O processo está dormindo (bloqueado), aguardando a chegada de recursos para acordar, ou pode acordar por meio de outros sinais de processo ou interrupções de relógio e entrar na fila de execução.

  3. Estado de sono profundo (ininterrupto): É basicamente semelhante ao sono leve, mas uma coisa é que não pode ser despertado por outros sinais de processo ou interrupções do relógio. A transição para um estado executável pronto só é possível quando explicitamente acordado usando a função wake_up().

  4. Estado suspenso: O processo entra no estado suspenso quando recebe o sinal SIGSTOP, SIGTSTP, SIGTTIN ou SIGTTOU. O sinal SIGCONT pode ser enviado a ele para fazer a transição do processo para o estado executável.

  5. Estado de zumbi: Quando um processo parou de ser executado, mas seu processo pai não perguntou seu status e o PCB não foi liberado, o processo é considerado em estado de zumbi.

O estado do processo é comutado de acordo com este diagrama de estado.

O fluxo de estados é um pouco complicado, pois nosso objetivo é implementar uma máquina de estados simples, então vamos simplificar a máquina de estados da seguinte forma:

 Para implementar uma máquina de estado, primeiro converta a máquina de estado na seguinte tabela de transição de estado.

 

A breve descrição é a seguinte: Supondo que o processo atual esteja no estado running, somente após ocorrer o evento de agendamento, o processo migrará para o estado owencpu. Caso ocorram outros eventos neste estado, como wake e wait_event Não causa transições de estado.

Como mostrado na FIG:

  1. Cada coluna representa um estado e cada linha corresponde a um evento.

  2. Esta tabela é o diagrama central para implementar a máquina de estado. Compare detalhadamente a relação entre esta tabela e o diagrama de transição de estado.

  3. Na cena real, a mudança de processo será muito mais complicada do que esta imagem. Felizmente, muitos grandes deuses nos ajudaram a resolver esses problemas complexos. Só precisamos nos apoiar nos ombros de gigantes.

concluir

De acordo com a tabela de transição de estado, os estados da máquina de estado são definidos da seguinte forma:

typedef enum {
  sta_origin=0,
  sta_running,
  sta_owencpu,
  sta_sleep_int,
  sta_sleep_unint
}State;

Os eventos ocorridos são os seguintes:

typedef enum{
  evt_fork=0,
  evt_sched,
  evt_wait,
  evt_wait_unint,
  evt_wake_up,
  evt_wake, 
}EventID;

Seja um estado ou um evento, ele pode ser ajustado de acordo com a situação real.

Defina uma estrutura para representar as informações de transição de estado atual:

typedef struct {
  State curState;//当前状态
  EventID eventId;//事件ID
  State nextState;//下个状态
  CallBack action;//回调函数,事件发生后,调用对应的回调函数
}StateTransform ; 

Função de retorno de chamada de evento: Em aplicações práticas, diferentes eventos precisam ser executados com ações diferentes, portanto, funções diferentes precisam ser definidas. Por conveniência, todos os eventos neste exemplo usam a mesma função de retorno de chamada. Função: Imprime o status do processo antes e depois da ocorrência do evento, caso o status mude, chame a função callback correspondente.

void action_callback(void *arg)
{
 StateTransform *statTran = (StateTransform *)arg;
 
 if(statename[statTran->curState] == statename[statTran->nextState])
 {
  printf("invalid event,state not change\n");
 }else{
  printf("call back state from %s --> %s\n",
   statename[statTran->curState],
   statename[statTran->nextState]);
 }
}

Defina uma matriz de tabelas de migração para cada estado:

/*origin*/
StateTransform stateTran_0[]={
 {sta_origin,evt_fork,        sta_running,action_callback},
 {sta_origin,evt_sched,       sta_origin,NULL},
 {sta_origin,evt_wait,        sta_origin,NULL},
 {sta_origin,evt_wait_unint,  sta_origin,NULL},
 {sta_origin,evt_wake_up,     sta_origin,NULL},
 {sta_origin,evt_wake,        sta_origin,NULL},
}; 

/*running*/
StateTransform stateTran_1[]={
 {sta_running,evt_fork,        sta_running,NULL},
 {sta_running,evt_sched,       sta_owencpu,action_callback},
 {sta_running,evt_wait,        sta_running,NULL},
 {sta_running,evt_wait_unint,  sta_running,NULL},
 {sta_running,evt_wake_up,     sta_running,NULL},
 {sta_running,evt_wake,        sta_running,NULL},
}; 
/*owencpu*/
StateTransform stateTran_2[]={
 {sta_owencpu,evt_fork,        sta_owencpu,NULL},
 {sta_owencpu,evt_sched,       sta_owencpu,NULL},
 {sta_owencpu,evt_wait,        sta_sleep_int,action_callback},
 {sta_owencpu,evt_wait_unint,  sta_sleep_unint,action_callback},
 {sta_owencpu,evt_wake_up,     sta_owencpu,NULL},
 {sta_owencpu,evt_wake,        sta_owencpu,NULL},
}; 

/*sleep_int*/
StateTransform stateTran_3[]={
 {sta_sleep_int,evt_fork,        sta_sleep_int,NULL},
 {sta_sleep_int,evt_sched,       sta_sleep_int,NULL},
 {sta_sleep_int,evt_wait,        sta_sleep_int,NULL},
 {sta_sleep_int,evt_wait_unint,  sta_sleep_int,NULL},
 {sta_sleep_int,evt_wake_up,     sta_sleep_int,NULL},
 {sta_sleep_int,evt_wake,        sta_running,action_callback},
}; 
/*sleep_unint*/
StateTransform stateTran_4[]={
 {sta_sleep_unint,evt_fork,        sta_sleep_unint,NULL},
 {sta_sleep_unint,evt_sched,       sta_sleep_unint,NULL},
 {sta_sleep_unint,evt_wait,        sta_sleep_unint,NULL},
 {sta_sleep_unint,evt_wait_unint,  sta_sleep_unint,NULL},
 {sta_sleep_unint,evt_wake_up,     sta_running,action_callback},
 {sta_sleep_unint,evt_wake,        sta_sleep_unint,NULL},
}; 

Implemente a função de geração de eventos:

void event_happen(unsigned int event)
功能:
 根据发生的event以及当前的进程state,找到对应的StateTransform 结构体,并调用do_action()
void do_action(StateTransform *statTran)
功能:
 根据结构体变量StateTransform,实现状态迁移,并调用对应的回调函数。
#define STATETRANS(n)  (stateTran_##n)
/*change state & call callback()*/
void do_action(StateTransform *statTran)
{
 if(NULL == statTran)
 {
  perror("statTran is NULL\n");
  return;
 }
 //状态迁移
 globalState = statTran->nextState;
 if(statTran->action != NULL)
 {//调用回调函数
  statTran->action((void*)statTran);
 }else{
  printf("invalid event,state not change\n");
 }
}
void event_happen(unsigned int event)
{
 switch(globalState)
 {
  case sta_origin:
   do_action(&STATETRANS(0)[event]);
   break;
  case sta_running:
   do_action(&STATETRANS(1)[event]);
   break;
  case sta_owencpu:
   do_action(&STATETRANS(2)[event]); 
   break;
  case sta_sleep_int:
   do_action(&STATETRANS(3)[event]); 
   break;
  case sta_sleep_unint:
   do_action(&STATETRANS(4)[event]); 
   break;
  default:
   printf("state is invalid\n");
   break;
 }
}

Programa de teste: Função:

  1. O estado inicial da máquina de estado de inicialização é sta_origin;

  2. Crie um thread filho e exiba o status atual do processo a cada segundo;

  3. A sequência de eventos é: evt_fork-->evt_sched-->evt_sched-->evt_wait-->evt_wake.

Os leitores podem seguir suas próprias necessidades, modificar a sequência de eventos e observar as mudanças no estado.

main.c

/*显示当前状态*/
void *show_stat(void *arg)
{
 int len;
 char buf[64]={0};
 
 while(1)
 {
  sleep(1);
  printf("cur stat:%s\n",statename[globalState]);
 } 
}
void main(void)
{
 init_machine();
 //创建子线程,子线程主要用于显示当前状态
 pthread_create(&pid, NULL,show_stat, NULL);

 sleep(5);
 event_happen(evt_fork);

 sleep(5);
 event_happen(evt_sched);
 sleep(5);
 event_happen(evt_sched);
 sleep(5);
 event_happen(evt_wait);
 sleep(5);
 event_happen(evt_wake);
 
}

resultado da operação:

Pode-se observar pelos resultados que:

evt_fork-->evt_sched-->evt_sched-->evt_wait-->evt_wake

A sequência de transição de estado correspondente à sequência de eventos é:

origem-->correndo-->owencpu-->owencpu-->sleep_int-->correndo

Acho que você gosta

Origin blog.csdn.net/yx5666/article/details/127411032
Recomendado
Clasificación