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.
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
:
daemon
.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.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.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./* 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; }