Daemons são processos que não são executados diretamente sob o controle do usuário, mas servem em segundo plano. Normalmente, eles iniciam na inicialização do sistema e são executados continuamente até que o sistema seja desligado. A única diferença entre esses processos e os normais é que eles não enviam mensagens para o console ou tela de forma alguma.

Veja como você pode criar um daemon em uma máquina Linux.

Uma breve introdução sobre como os daemons são criados

Muitos daemons são executados no sistema e alguns exemplos familiares de daemons são os seguintes:

  • crond: Faz com que os comandos sejam executados no horário especificado
  • sshd: Permite o login no sistema a partir de máquinas remotas
  • httpd: Exibe páginas da web
  • nfsd: Permite o compartilhamento de arquivos pela rede

Além disso, os processos daemon geralmente são nomeados para terminar com a letra d, embora não seja obrigatório.

Para que um processo seja executado como um daemon, o seguinte caminho é seguido:

  • As operações iniciais, como ler arquivos de configuração ou obter os recursos necessários do sistema, devem ser executadas antes que o processo se torne um daemon. Desta forma, o sistema pode reportar os erros recebidos ao usuário e o processo será finalizado com um código de erro apropriado.
  • Um processo em execução em segundo plano é criado com init como seu processo pai. Para esta finalidade, um subprocesso é bifurcado do processo init primeiro e, em seguida, o processo superior é encerrado com exit.
  • Uma nova sessão deve ser aberta chamando a função setsid, e o processo deve ser desconectado do terminal.
  • Todos os descritores de arquivo abertos herdados do processo pai são fechados.
  • Entrada padrão, saída, e as mensagens de erro são redirecionadas para /dev/null.
  • O diretório de trabalho do processo deve ser alterado.

O que são sessões de daemon?

Depois de fazer login no sistema por meio de um terminal, os usuários podem executar muitos aplicativos por meio do programa shell. Esses processos devem fechar quando o usuário sair do sistema. O sistema operacional agrupa esses processos em grupos de sessões e de processos.

Cada sessão consiste em grupos de processos. Você pode descrever essa situação da seguinte forma:

O terminal onde os processos recebem suas entradas e enviam suas saídas é chamado de terminal de controle. Um terminal de controle está associado a apenas uma sessão por vez.

Uma sessão e os grupos de processos nela contidos possuem números de identificação (ID); esses números de identificação são os números de identificação do processo (PID) da sessão e dos líderes do grupo de processos. Um processo filho compartilha o mesmo grupo que seu processo pai. Quando vários processos são comunicação com o mecanismo de tubulação, o primeiro processo se torna o líder do grupo de processos.

Criando um processo daemon no Linux

Aqui você verá como criar uma função daemon. Para isso, você criará uma função chamada _daemon. Você pode começar nomeando o código do aplicativo que será executado como um daemon como teste.c, e o código que você criará a função daemon como daemon.c.

//test.c
#incluir <stdio.h>
int_daemon(int, int);
inta Principal()
{
getchar();
_daemon (0, 0);
getchar();
Retorna0;
}
//daemon.c
#incluir <sys/types.h>
#incluir <sys/stat.h>
#incluir <stdlib.h>
#incluir <stdio.h>
#incluir <fcntl.h>
#incluir <unistd.h>
#incluir <linux/fs.h>
#incluir <linux/limits.h>
int_daemon(int nochdir, int perto){
pid_t pid;
pid = garfo(); // Bifurca o processo pai
se (pid < 0) {
saída(EXIT_FAILURE);
}
se (pid > 0) {
saída(EXIT_SUCESSO);
}
Retorna0;
}

Para criar um daemon, você precisa de um processo em segundo plano cujo processo pai seja init. No código acima, _daemon cria um processo filho e, em seguida, mata o processo pai. Nesse caso, seu novo processo será um subprocesso de init e continuará sendo executado em segundo plano.

Agora compile o aplicativo com o seguinte comando e examine o status do processo antes e depois _deamon é chamado:

gcc-otesteteste.cdemônio.c

Execute o aplicativo e mude para um terminal diferente sem pressionar nenhuma outra tecla:

./teste

Você pode ver que os valores relacionados ao seu processo são os seguintes. Aqui, você terá que usar o comando ps para obter informações relacionadas ao processo. Neste caso, o _daemon função ainda não foi chamada.

ps -C teste -o "pid ppid pgid sid tty Estadocomando"
# Saída
PID PPID PGID SID TT STAT COMANDO
10296 5119 10296 5117 pts/2 S+ ./teste

Quando você olha para o ESTADO campo, você vê que seu processo está em execução, mas aguardando a ocorrência de um evento fora do cronograma que fará com que ele seja executado em primeiro plano.

Abreviação Significado
S Esperando adormecido para que um evento aconteça
T Aplicativo interrompido
s Líder da sessão
+ O aplicativo está sendo executado em primeiro plano

Você pode ver que o processo pai do seu aplicativo é o shell conforme o esperado.

ps-jp 5119 
# Saída
PID PGID SID TTY TEMPO CMD
5119 5119 5117 pts/2 00:00:02 zsh

Agora retorne ao terminal onde você está executando seu aplicativo e pressione Entrar para invocar o _daemon função. Em seguida, verifique novamente as informações do processo no outro terminal.

ps -C teste -o "pid ppid pgid sid tty Estadocomando"
# Saída
PID PPID PGID SID TT STAT COMANDO
22504 1 22481 5117 pts/2 S ./teste

Em primeiro lugar, você pode dizer que o novo subprocesso está sendo executado em segundo plano, pois você não vê o + personagem no ESTADO campo. Agora examine quem é o processo pai do processo usando o seguinte comando:

ps-jp 1 
​​​​​​​# Saída
PID PGID SID TTY TEMPO CMD
1 1 1? 00:00:01systemd

Agora você pode ver que o processo pai do seu processo é o systemd processo. É mencionado acima que para a próxima etapa, uma nova sessão deve ser aberta e o processo deve ser desconectado do terminal de controle. Para isso, você usa a função setsid. Adicione esta chamada ao seu _daemon função.

O trecho de código a ser adicionado é o seguinte:

if (setsid() == -1) 
Retorna-1;

Agora que você inspecionou o estado antes _daemon chamado, agora você pode remover o primeiro getchar função no teste.c código.

//test.c
#incluir <stdio.h>
int_daemon(int, int);
inta Principal()
{
_daemon (0, 0);
getchar();
Retorna0;
}

Após compilar e executar o aplicativo novamente, acesse o terminal onde você fez suas avaliações. O novo status do seu processo é o seguinte:

ps -C teste -o "pid ppid pgid sid tty Estadocomando"
​​​​​​​# Saída
PID PPID PGID SID TT STAT COMANDO
25494 1 25494 25494? Ss./teste

o ? assine o TT campo indica que seu processo não está mais conectado a um terminal. Observe que o PID, PGID, e SID os valores do seu processo são os mesmos. Seu processo agora é um líder de sessão.

Na próxima etapa, altere o diretório de trabalho para o diretório raiz de acordo com o valor do argumento que você passou. Você pode adicionar o seguinte trecho ao _daemon função para isso:

if (!nochdir) {
se (chdir("/") == -1)
Retorna-1;
}

Agora, de acordo com o argumento passado, todos os descritores de arquivo podem ser fechados. Adicione o seguinte código ao _daemon função:

#define NR_OPEN 1024
if (!noclose) {
para (i = 0; eu < NR_OPEN; e++)
fechar (i);
abrir("/dev/nulo", O_RDWR);
dup (0);
dup (0);
}

Depois que todos os descritores de arquivo forem fechados, novos arquivos abertos pelo daemon serão mostrados com os descritores 0, 1 e 2 respectivamente. Neste caso, por exemplo, o printf comandos no código serão direcionados para o segundo arquivo aberto. Para evitar isso, os três primeiros identificadores apontam para o /dev/null dispositivo.

Neste caso, o estado final do _daemon função será a seguinte:

#incluir <sys/types.h>
#incluir <sys/stat.h>
#incluir <stdio.h>
#incluir <stdlib.h>
#incluir <fcntl.h>
#incluir <errno.h>
#incluir <unistd.h>
#incluir <syslog.h>
#incluir <string.h>
int_daemon(vazio){
// PID: ID do processo
// SID: ID da sessão
pid_t pid, sid;
pid = garfo(); // Bifurca o processo pai
se (pid < 0) {
saída(EXIT_FAILURE);
}
se (pid > 0) {
saída(EXIT_SUCESSO);
}
// Criar uma SIDporcriança
sid = conjuntosid();
se (lado < 0) {
// FALHOU
saída(EXIT_FAILURE);
}
if ((chdir("/")) < 0) {
// FALHOU
saída(EXIT_FAILURE);
}
fechar (STDIN_FILENO);
fechar (STDOUT_FILENO);
fechar (STDERR_FILENO);
enquanto (1) {
// Algumas Tarefas
dormir (30);
}
saída(EXIT_SUCESSO);
}

Aqui está um exemplo de um snippet de código que executa o sshd aplicação como um demônio:

...
if (!(debug_flag || inetd_flag || no_daemon_flag)) {
int fd;
if (daemon (0, 0) < 0)
fatal("daemon() falhou: %.200s", strerror (errno));
/* Desconecte-se do tty de controle. */
fd = abrir (_PATH_TTY, O_RDWR | O_NOCTTY);
se (fd >= 0) {
(vazio) ioctl (fd, TIOCNOTTY, NULL);
fechar (fd);
}
}
...

Daemons são importantes para a programação do sistema Linux

Daemons são programas que executam várias ações de uma maneira predefinida em resposta a determinados eventos. Eles são executados silenciosamente em sua máquina Linux. Eles não estão sob o controle direto do usuário e cada serviço executado em segundo plano tem seu daemon.

É importante dominar daemons para aprender a estrutura do kernel do sistema operacional Linux e entender o funcionamento de várias arquiteturas de sistema.

O que é um demônio?

Leia a seguir

CompartilharTweetCompartilharE-mail

Tópicos relacionados

  • Linux
  • Kernel Linux
  • Programação
  • Programação em C

Sobre o autor

Fatih Küçükkarakurt (5 artigos publicados)

Um engenheiro e desenvolvedor de software que é fã de matemática e tecnologia. Ele sempre gostou de computadores, matemática e física. Ele desenvolveu projetos de mecanismos de jogos, bem como aprendizado de máquina, redes neurais artificiais e bibliotecas de álgebra linear. Além disso continua a trabalhar em aprendizado de máquina e matrizes lineares.

Mais de Fatih Küçükkarakurt

Assine a nossa newsletter

Junte-se à nossa newsletter para dicas de tecnologia, análises, e-books gratuitos e ofertas exclusivas!

Clique aqui para assinar