Ferramentas do usuário

Ferramentas do site


daemon

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.


daemon [2023/09/12 16:14] (atual) – criada - edição externa 127.0.0.1
Linha 1: Linha 1:
 +====== Daemons (serviços) ======
 +
 +
 +===== Conceito de daemon =====
 +Em várias situações precisa-se que um processo fique em execução continuamente (//eternamente//) em uma máquina. A estes processos dá-se o nome de **''daemons''** ou **''serviços''**. 
 +
 +Geralmente são programas que são iniciados assim que o sistema operacional é inicializado. Coloca-se a chamada dos ''daemons'' nos arquivos de configuração para que os mesmos sejam ativados automaticamente durante o processo de boot do sistema. Um ''daemon'' só deve ser cancelado quando o sistema operacional está encerrando o seu processamento. ''Daemons'' são processos que rodam em //background// e não devem ter um terminal associado à eles. 
 +
 +
 +===== Regras de codificação =====
 +
 +Para se codificar um daemon deve-se realizar uma série de tarefas e chamadas de funções para que o processo se comporte como um ''daemon'':
 +
 +   * A primeira coisa a fazer no processo é chamar a função [[fork]] para duplicar o processo atual e terminar o processo pai. Assim, o término do processo pai libera o shell, pois o mesmo acha que o comando terminou. O processo filho herda o Process Group ID do pai mas cria um novo Process ID, garantindo que este processo não será um processo líder de grupo.  
 +  * Deve-se chamar a função [[setsid]] para criar uma nova sessão. Com a criação de uma nova sessão, o processo filho torna-se o líder da sessão, torna-se o líder do grupo de processos e não irá possuir um terminal de controle.
 +  * Em sistemas baseados no Unix //System V//, deve-se realizar o [[fork]] novamente, pois algum evento futuro poderá ligar um terminal ao processo ''daemon''.
 +  * Deve-se trocar o diretório atual para o diretório raiz ou para um diretório específico. Este diretório preferencialmente não deve ser um diretório montado depois do processo de boot. 
 +  * Deve-se mudar a máscara de criação do processo para **''0''** usando a função [[umask]]. Isto possibilita o processo ''daemon'' criar arquivos com a permissão desejada. Caso não se chame esta função, pode ser que o processo ''daemon'' herde alguma máscara que esteja desabilitando alguma permissão necessária para o funcionamento do daemon.
 +  * Todos os descritores de arquivos que não serão utilizados pelo processo ''daemon'' devem ser fechados. Isto previne que o ''daemon'' segure algum descritor herdado aberto. Geralmente o ''daemon'' fecha todos os descritores antes de abrir qualquer arquivo, garantindo assim que somente os arquivos necessários ficarão abertos durante o tempo de vida do daemon.
 +  * Deve-se associar a ''entrada padrão'', ''saída padrão'' e ''saída de erro padrão'' para ''/dev/null''. Assim, caso algum evento ocorra, o sistema operacional irá descartar.
 +  * Caso durante a vida do processo daemon ele precise ler algum arquivo de configuração ou mudar sua configuração interna, deve-se instalar um [[sinal|signal handler]] para o [[sinal|sinal SIGHUP]], pois como o processo está desconectado de qualquer terminal ele naturalmente nunca receberá este sinal do sistema operacional.
 +
 +===== Funções =====
 +  * [[setsid]]
 +  * [[syslog]]
 + 
 +
 +===== Exemplo completo =====
 +
 +<code c>
 +/* daemon.c */
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <signal.h>
 +#include <syslog.h>
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +
 +
 +int daemon_init (void)
 +{
 +   pid_t iPid;
 +   long iMaxFd;
 +   int i, fd0, fd1, fd2;
 +   struct sigaction sa;
 +
 +   /* 1. passo - duplicar o processo usando o fork */
 +   if((iPid = fork()) < 0)
 +   {
 +      perror("fork:");
 +      exit(1);
 +   }
 +
 +   if(iPid != 0) /* finaliza o pai */
 +   {
 +      exit(0);
 +   }
 +
 +   /* 2. passo - chamar a função setsid para criar uma nova sessão de processo, 
 +     ficando o processo filho como líder da sessão e sem um terminal de controle
 +     associado ao processo */
 +   setsid();
 +
 +
 +   /* 3. passo - é necessário realizar 2 forks para evitar
 +     que o shell ligue um terminal ao processo. Também é
 +     necessário ignorar o sinal de término do pai */
 +
 +   sa.sa_handler = SIG_IGN;
 +   sigemptyset(&sa.sa_mask);
 +   sa.sa_flags = 0;
 +   if(sigaction(SIGHUP, &sa, NULL) < 0)
 +   {
 +      perror("sigaction:");
 +      exit(1);
 +   }
 + 
 +   if((iPid = fork()) < 0)
 +   {
 +      perror("fork:");
 +      exit(1);
 +   }
 +
 +   if(iPid != 0) /* finaliza o pai */
 +   {
 +      exit(0);
 +   }
 +
 +   /* 4. passo - troca-se o diretório atual para a raiz do sistema ou para um diretorio do 
 +      próprio daemon */
 +   chdir("/");
 +
 +   /* 5. passo - inicializa a máscara padrão de criação de arquivos */
 +   umask(0);
 +
 +   /* 6. passo - fechando todos os descritores de arquivos existentes no
 +      sistema. Utiliza-se a informação de número máximo de descritores configurado 
 +      no sistema e obtido com a função sysconf. */
 +   iMaxFd = sysconf (_SC_OPEN_MAX);
 +   for (i=0; i < iMaxFd; i++)
 +   {
 +      close (i);
 +   }
 +
 +   /* 7. passo - abrindo arquivos de entrada padrao, saida padrao e saida de erro para /dev/null */
 +   fd0 = open("/dev/null", O_RDWR);
 +   fd1 = dup(0);
 +   fd2 = dup(0);
 +
 +   /* abrindo a log */
 +   openlog("daemon_init", LOG_CONS, LOG_DAEMON);
 +
 +   if( fd0 != 0 || fd1 != 1 || fd2 != 2 )
 +   {
 +      syslog(LOG_ERR, "não foi aberto um dos arquivos %d %d %d", fd0, fd1, fd2);
 +   }
 +
 +
 +   return 0;
 +}
 +
 +int main(void)
 +{
 +   int i;
 +   daemon_init(); /* chama o daemon */
 +
 +   for(i=0;i<20;i++)
 +   {
 +      syslog(LOG_NOTICE, "faltam %d segundos para terminar o daemon", 20-i);
 +      sleep(1);
 +   }
 +
 +   return 0;
 +}
 +</code>
  
daemon.txt · Última modificação: 2023/09/12 16:14 por 127.0.0.1