Successfully reported this slideshow.
Your SlideShare is downloading. ×

PHP e seus demônios

Ad

PHP e seus demônios
CRIANDO	
  DAEMONS	
  EM	
  PHP

Ad

PALESTRANTE

2

Ad

Henrique	
  Moody
• Desenvolvedor	
  web	
  com	
  foco	
  em	
  PHP	
  desde	
  
2007	
  
• Usuário	
  assíduo	
  de	
  L...

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Upcoming SlideShare
O esquecido do PHP
O esquecido do PHP
Loading in …3
×

Check these out next

1 of 63 Ad
1 of 63 Ad

More Related Content

PHP e seus demônios

  1. 1. PHP e seus demônios CRIANDO  DAEMONS  EM  PHP
  2. 2. PALESTRANTE 2
  3. 3. Henrique  Moody • Desenvolvedor  web  com  foco  em  PHP  desde   2007   • Usuário  assíduo  de  Linux  desde  2008   • Zend  Certified  Engineer  5.3  desde  2011   • Contribui  com  vários  projetos  Open  Source     • Líder  Técnico   • Desenvolvedor  PHP  Senior 3
  4. 4. PALESTRA 4
  5. 5. PHP  e  seus  demônios • • • • • • Forks   Sinais   Daemons   Spawn   Zombies   IPC 5
  6. 6. FORKS 6
  7. 7. • Em  sistemas  operacionais  Unix-­‐like  fork  é  uma   operação  em  que  um  processo  cria  uma  cópia  de   si  mesmo   • Fork  é  uma  forma  de  um  processo  executar   outro  ou  outros  processos  a  partir  de  si  mesmo   • Quando  a  cópia  do  processo  é  criada  essa  cópia   é  chamada  de  processo  filho  tornando  o   processo  original  o  processo  pai   • No  PHP  é  necessária  a  extensão  PCNTL   habilitada  e  extremamente  recomendável  a   extensão  POSIX  também  habilitada 7
  8. 8. PCNTL  (Process  Control) • Deve  ser  habilitada  no  momento  da  compilação   do  PHP  (——enable-pcntl)   • Suportada  apenas  para  sistemas  Unix-­‐like   • Não  funciona  em  web  servers   • Cria  e  gerencia  processos  e  sinais 8
  9. 9. POSIX  (Portable  Operating  System   Interface) • Habilitada  por  padrão  na  compilação  do  PHP   • Suportada  apenas  para  sistemas  Unix-­‐like   • Fornece  uma  API  padrão  para  desenvolvimento   em  sistemas  Unix-­‐like   • Gerencia  processos,  sessões,  grupos,  usuários  e   arquivos  de  sistemas  Unix-­‐like 9
  10. 10. Funcionamento • A  função  pcntl_fork()  criará  o  fork  e  retornará  um  valor   diferente  para  cada  processo  (pai  e  filho)   • Caso  pcntl_fork()  retorne  -1  ocorreu  um  erro  no  fork   • Caso  pcntl_fork()  retorne  0  houve  sucesso  no  fork.  O   processo  atual  é  o  filho   • Caso  pcntl_fork()  retorne  um  número  maior  do  que  0   houve  sucesso  no  fork.  O  processo  atual  é  o  pai  e  o  retorno   de  pcntl_fork()  é  o  PID  do  filho   • Nada  impede  um  processo  filho  criar  forks  de  si  mesmo   • Todas  as  variáveis  inicializadas  no  processo  pai  estarão   disponíveis  para  os  filhos 10
  11. 11. Forks/pcntl.php <?php $pid = pcntl_fork(); if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL; ! } elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL; ! } else { // Sou o processo filho, em background mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); } 11
  12. 12. Forks/pcntl+posix.php <?php $pid = pcntl_fork(); if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL; ! } elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL; ! } else { // Sou o processo filho, em background if (0 !== posix_getuid()) { error_log('É necessário ser root para alterar informações do processo'); exit(2); } ! ! ! if (! posix_setuid(1000)) { error_log('Não foi possível definir o usuário do processo como 1000'); exit(3); } if (! posix_setgid(1000)) { error_log('Não foi possível definir o grupo do processo como 1000'); exit(4); } mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); } 12
  13. 13. SINAIS 13
  14. 14. • Em  sistemas  Unix-­‐like,  um  sinal  é  uma   notificação  de  software  a  um  processo  da   ocorrência  de  um  evento   • Um  sinal  é  gerado  pelo  SO  quando  o  evento  que   causa  o  sinal  acontece   • Existem  vários  sinais  que  podem  ser  enviados   para  um  processo,  alguns  deles  podem  ser   manipulados  pela  aplicação  já  outros  apenas   pelo  próprio  SO   • Podemos  enviar  através  da  função  posix_kill()   • Podemos  definir  um  callback  para  manipular   sinais  através  da  função  pcntl_signal() 14
  15. 15. Lista  de  constantes  de  sinais  do  PHP • SIGABRT • SIGIOT • SIGTTIN • SIGALRM • SIGKILL • SIGTTOU • SIGBABY • SIGPIPE • SIGURG • SIGBUS • SIGPROF • SIGUSR1 • SIGCHLD • SIGQUIT • SIGUSR2 • SIGCONT • SIGSEGV • SIGVTALRM • SIGFPE • SIGSTOP • SIGWINCH • SIGHUP • SIGSYS • SIGXCPU • SIGILL • SIGTERM • SIGXFSZ • SIGINT • SIGTRAP • SIGIO • SIGTSTP 15
  16. 16. Mais  comuns • SIGHUP:  enviado  quando  o  sessão  (terminal)  do  processo  é  fechada   • • • • • • • Pode  ser  interceptado   SIGINT:  enviado  quando  um  se  pretende  interromper  o  processo   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-C,  e  em  alguns  sistemas  com  delete  ou  break   SIGTSTP:  enviado  quando  se  pretende  pausar  o  processo   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-Z SIGCONT:  enviado  quando  se  pretende  despausar  o  processo  após  SIGTSTP   • Pode  ser  interceptado   SIGTERM:  enviado  quando  se  pretende  terminar  o  processo  (amigavelmente).   • Pode  ser  interceptado   SIGQUIT:  enviado  quando  se  pretende  encerrar  o  processo  e  obter  um  dump  de  memória.   • Pode  ser  interceptado   • Pode  ser  enviado  via  teclado,  com  Control-   SIGKILL:  enviado  quando  se  pretende  encerrar  imediatamente  o  processo   • Não  ser  interceptado 16
  17. 17. Sinais/envio.php <?php ! // Envia um 0 (verifica se o PID é válido ou não) posix_kill($pid, 0); ! // Envia um SIGUSR1 (User-defined signal 1) posix_kill($pid, SIGUSR1); ! // Envia um SIGSTOP (pausa a execução do processo) posix_kill($pid, SIGSTOP); ! // Envia um SIGCONT (continua a execução do processo) posix_kill($pid, SIGCONT); ! // Envia um SIGKILL (mata instantâneamente o processo) posix_kill($pid, SIGKILL); 17
  18. 18. Sinais/manipulacao.php <?php ! declare(ticks = 1); function signalHandler($signal) { switch ($signal) { case SIGQUIT; error_log('Me fecharam com o teclado (Control-)'); exit(1); case SIGINT: error_log('Me interromperam com o teclado (Control-C)'); exit(1); case SIGHUP: error_log('Fecharam meu terminal'); exit(1); case SIGTERM: error_log('Me pediram para me matar'); exit(0); } } ! pcntl_signal(SIGQUIT, 'signalHandler'); pcntl_signal(SIGINT, 'signalHandler'); pcntl_signal(SIGHUP, 'signalHandler'); pcntl_signal(SIGTERM, 'signalHandler'); pcntl_signal(SIGTSTP, 'signalHandler'); pcntl_signal(SIGTSTP, SIG_IGN); // SIG_IGN faz com que SIGTSTP seja ignorado pcntl_signal(SIGCONT, SIG_IGN); // SIG_IGN faz com que SIGCONT seja ignorado ! echo 'PID: ' . getmypid() . PHP_EOL; while (true) { echo date('Y-m-d H:i:s') . PHP_EOL; sleep(1); } 18
  19. 19. DAEMONS 19
  20. 20. • Acrônimo  de  Disk  And  Execution  MONitor  (Monitor   de  Execução  e  de  Disco)   • Em  Unix  e  outros  sistemas  operacionais  multi-­‐ tarefas  é  um  programa  de  computador  que  roda  de   forma  independente  em  background,  ao  invés  de   ser  controlado  diretamente  por  um  usuário   • Em  um  ambiente  Unix,  o  processo  pai  de  um   daemon  é  normalmente  (mas  nem  sempre)  o   processo  init  (PID=1)   • Alguns  exemplos  de  daemons  são:  MySQL  Server,   Apache  Server,  Nginx  Server,  Cron   • Muitas  vezes,  um  programa  se  torna  um  daemon   através  de  forking 20
  21. 21. CRIANDO  UM  DAEMON 21
  22. 22. Passo  a  passo 1. Fork  off  and  die   2. Máscara  de  criação  dos  arquivos   3. Entradas  e  saídas   4. Logging   5. Desligar  sessão  (SID)   6. Working  directory   7. Locking 22
  23. 23. Fork  off  and  die • Você  apenas  criará  o  fork  e  encerrará   imediatamente  o  processo  pai   • O  processo  filho  será  o  daemon,  executando  em   background 23
  24. 24. Daemons/fork.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 24
  25. 25. Máscara  de  criação  dos  arquivos • Para  garantir  que  você  possa  ler  e  escrever   arquivos  restaure  o  umask  para  o  padrão  do   sistema,  com  umask(0) 25
  26. 26. Daemons/fork+umask.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 26
  27. 27. Entradas  e  saídas • O  daemon  não  possui  interação  com  o  usuário,   portanto  você  não  deve  permitir  que  os  métodos   de  entrada  e  saída  (STDIN,  STDOUT  e  STDERR)   sejam  utilizados   • Você  pode  fechar  STDIN,  STDOUT  e  STDERR,  mas   caso  você  esteja  utilizando  essas  constantes  com   certeza  você  terá  problemas   • Você  também  pode  utilizar  as  funções  ob_*  para   evitar  outputs 27
  28. 28. Daemons/fork+umask+file_descriptors.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2); } 28
  29. 29. Logging • Visto  que  não  interação  entre  o  daemon  e  o  usuário,   logs  são  uma  ótima  forma  de  obter  feedback  de  um   daemon   • Você  pode  fazer  logs  em:   ‣ Arquivos   ‣ Bancos  de  dados  relacionais   ‣ Bancos  de  dados  não-­‐relacionais   ‣ Message  Queue   ‣ Syslog   ‣… 29
  30. 30. Daemons/fork+umask+file_descriptors+logging.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); while (true) { syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); continue; } syslog(LOG_ERR, 'Falha ao enviar email'); sleep(2); } closelog(); 30
  31. 31. Desligar  sessão  (SID) • Mesmo  que  o  processo  filho  seja  executado  em   background,  não  dependendo  do  processo  pai,  eles  estão   na  mesma  sessão   • Quando  a  sessão  terminar  (o  terminal  fechado,  por   exemplo),  o  sistema  matará  o  processo  filho   • A  função  posix_setsid()  cria  uma  nova  sessão  para  o   processo  filho,  desvinculando-­‐o  do  processo  pai  e  sua   sessão   • O  processo  filho  passa  a  ter  o  init  (processo  inicial  que   carrega  todos  os  outros  processos  do  sistema)  como   processo  pai 31
  32. 32. Daemons/fork+umask+file_descriptors+logging+detach_sid.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); ! if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2); } ! while (true) { /** Payload **/ } closelog(); 32
  33. 33. Working  directory • O  filho  herda  o  working  directory  do  pai   • Este  working  directory  pode  ser  um  volume   montado  que  pode  ser  desmontado  em  algum   momento   • Para  desmontar  um  volume  o  sistema  irá  matar   qualquer  processo  que  ainda  está  usando  o   diretório 33
  34. 34. Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir.php <?php $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2); ! } elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! umask(0); ! fclose(STDIN); fclose(STDOUT); fclose(STDERR); ! $fd0 = fopen('/dev/null', 'r'); $fd1 = fopen('/tmp/psd.log', 'a'); $fd2 = fopen('php://stdout', 'a'); ! openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0); ! if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2); } ! chdir(__DIR__); ! while (true) { /** Payload **/ } closelog(); 34
  35. 35. pidfile • Contém  o  PID  do  daemon   • Impede  que  o  daemon  seja  executado  mais  de   uma  vez 35
  36. 36. Generated  by  https://www.lucidchart.com 36
  37. 37. Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir+pidfile.php <?php ! $pidfile = '/var/run/psd/daemon.pid'; if (file_exists($pidfile)) { $daemonPid = (int) file_get_contents($pidfile); if (true === posix_kill($daemonPid, 0)) { echo 'Daemon já em execução (PID ' . $daemonPid . ').' . PHP_EOL; exit(2); } unlink($pidfile); } ! $pidfileHandler ! = fopen($pidfile, 'w+'); if (! flock($pidfileHandler, LOCK_EX | LOCK_NB)) { echo 'Falha ao bloquear acesso externo ao pidfile' . PHP_EOL; exit(3); } ! $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(4); ! } elseif ($pid > 0) { if (! fwrite($pidfileHandler, $pid)) { echo 'Falha ao escrever PID no pidfile' . PHP_EOL; exit(5); } ! echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit(); } ! register_shutdown_function('unlink', ! $pidfile); // Corpo do daemon 37
  38. 38. SPAWN 38
  39. 39. • Muito  utilizado  no  processamento  de  filas   quando  você  precisa  de  processos  concorrentes   • Um  processo  pode  criar  outros  processos  e   delegar  tarefas  para  cada  um  deles   • Esse  recurso  muitas  vezes  é  confundido  com   multi-­‐threading,  mas  não  é  isso.  O  PHP  não   possui  suporte  a  este  recurso  mas  existe  uma   extensão  PECL  para  isso   • Geralmente  os  processos  pai  são  daemons   sendo  seus  filhos  workers   • Você  não  pode  alterar  o  SID  dos  filhos  pois  você   precisa  deles  na  mesma  sessão  do  processo  pai 39
  40. 40. Spawn/exemplo.php <?php $pid = pcntl...// Fluxo normal do daemon ! $childrenLimit = 10; $childrenPids = array(); while (true) { if (count($childrenPids) >= $childrenLimit) { $firstChildPid = array_shift($childrenPids); pcntl_waitpid($firstChildPid, $status); } ! ! ! ! $childPid = pcntl_fork(); if ($childPid == -1) { syslog(LOG_ERR, 'Falha ao criar filho'); continue; } if ($childPid > 0) { $childrenPids[] = $childPid; continue; } syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); exit(0); } syslog(LOG_ERR, 'Falha ao enviar email'); exit(3); } closelog(); 40
  41. 41. ZOMBIES 41
  42. 42. • Um  processo  zombie  é  um  processo  que  já  foi   completamente  executado  mas  ainda  se  encontra  na  tabela   de  processos  do  SO,  permitindo  que  o  processo  que  o  criou   leia  o  seu  valor  de  saída   • Quando  um  processo  termina,  a  memória  a  ele  associada  é   libertada,  no  entanto  a  informação  sobre  esse  processo   continua  disponível,  embora  ele  já  não  exista   • Normalmente  os  processos  zombie  não  duram  muito  tempo   já  que  o  sinal  SIGCHLD  é  emitido  quando  ele  entra  nesse   estado,  possibilitando  ao  processo  pai  saber  quando  isso   acontece  para  ler  as  informações  necessárias   • Se  o  processo  pai  explicitamente  ignora  o  SIGCHLD  definindo   seu  manipulador  como  SIG_IGN  todos  as  informações  de   término  dos  processos  filhos  serão  descartadas  e  os   processos  zombies  continuarão  na  tabela 42
  43. 43. Zombies/reaper.php <?php ! function reaper($signal) { if ($signal != SIGCHLD) { return; } ! while (pcntl_waitpid(-1, $status, WNOHANG | WUNTRACED) > 0) { usleep(1000); } } ! pcntl_signal(SIGCHLD, 'reaper'); 43
  44. 44. Inter-­‐Process  Communication IPC 44
  45. 45. • Cada  processo  possui  um  contexto  de  execução  próprio.  Um   processo  não  tem  conhecimento  do  contexto  de  outro   processo  sendo  assim  os  processos  não  conseguem  transferir   informação  entre  si   • Inter-­‐Process  Communication  (IPC),  é  o  grupo  de  mecanismos   que  permite  aos  processos  transferirem  informação  entre  si   • Usando  IPC  um  processo  pai  consegue  obter  informações   precisar  de  seus  filhos   • Para  IPC  podemos  utilizar:   ‣ Arquivos   ‣ Filas  de  mensagens   ‣ Memória  Compartilhada   ‣ Sinais   ‣ Par  de  Sockets   ‣… 45
  46. 46. Arquivos • Você  pode  escrever  dados  em  um  processo  e  ler   em  outro  processo,  desde  que  ambos  tenham   permissão  de  leitura   • Nome  do  arquivo  deve  ser  único 46
  47. 47. IPC/file.php <?php ! $filename = '/tmp/' . getmypid() . '.ipc'; if (! is_file($filename)) { touch($filename); } ! $dataWritten = 'PHP e seus Demônios'; if (false === file_put_contents($filename, $dataWritten)) { echo 'Falha ao gravar dados no arquivo' . PHP_EOL; exit(2); } ! $dataGiven = file_get_contents($filename); if (false === $dataGiven) { echo 'Falha ao ler dados no arquivo' . PHP_EOL; exit(3); } ! echo 'Dado lido no arquivo: ' . $dataGiven . PHP_EOL; ! if (! unlink($filename)) { echo 'Falha ao tentar remover o arquivo' . PHP_EOL; exit(3); } 47
  48. 48. Memória  compartilhada • É  um  fácil  caminho  para  usar  funções  que  permitem  o  PHP  ler,   escrever,  criar  e  deletar  segmentos  de  memória  compartilhada  UNIX   • O  PHP  possui  duas  API’s,  as  funções  shmop_*  e  shm_*:     • Para  habilitar  as  funções    shmop_*    é  preciso  compilar  o  PHP  com  a   opção  --enable-shmop  do  configure   • Para  habilitar  as  funções    shm_*    é  preciso  compilar  o  PHP  com  a   opção  --enable-sysvshm  do  configure   • Funciona  basicamente  com  uma  chave,  por  ela  você  pode  ler  e   escrever  dados  na  memória   • Utilize  o  comando  ipcs  para  monitorar  os  seguimentos  criados  e   ipcrm shm ID  para  remover  seguimentos  (você  também  pode  usar   ipcmk  para  criar  seguimentos) 48
  49. 49. IPC/shmop.php <?php ! $key = getmypid(); $flag = 'c'; $permission = 0644; $memorySize = 1024; ! $shmId = shmop_open($key, $flag, $permission, $memorySize); if (! $shmId) { echo 'Não foi possível criar o segmento de memória' . PHP_EOL; exit(1); } ! $stringWritten = 'PHP e seus demônios'; $shmBytesWritten = shmop_write($shmId, $stringWritten, 0); if ($shmBytesWritten != strlen($stringWritten)) { echo 'Não foi possível gravar o dado e com seu tamanho correto' . PHP_EOL; exit(2); } ! $stringRead = shmop_read($shmId, 0, $memorySize); if (! $stringRead) { echo 'Não foi possível ler o dado na memória compartilhada' . PHP_EOL; exit(2); } ! echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL; ! if (! shmop_delete($shmId)) { echo 'Não foi possível marcar o bloco de memória compartilhada para remoção'; } ! shmop_close($shmId); 49
  50. 50. IPC/shm.php <?php ! $key = getmypid(); $permission = 0644; $memorySize = 1024; ! $shmId = shm_attach($key, $memorySize, $permission); if (! $shmId) { echo 'Falha ao criar o segmento de memória' . PHP_EOL; exit(1); } ! $stringWritten = 'PHP e seus demônios'; if (! shm_put_var($shmId, 1, $stringWritten)) { echo 'Falha ao gravar o dado na memória compartilhada' . PHP_EOL; exit(2); } ! if (! shm_has_var($shmId, 1)) { echo 'Nenhum dado na chave 1 foi encontrado na memória' . PHP_EOL; exit(2); } ! $stringRead = shm_get_var($shmId, 1); if (! $stringRead) { echo 'Falha ao ler o dado da chave 1 na memória compartilhada' . PHP_EOL; exit(2); } ! echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL; ! if (! shm_remove($shmId)) { echo 'Falha ao remover do bloco de memória compartilhada'; } ! if (! shm_detach($shmId)) { echo 'Falha ao se desconectar do bloco de memória compartilhada'; } 50
  51. 51. Filas  de  mensagens • O  PHP  possui  suporte  a  filas  de  mensagens  do     • Para  habilitar  as  funções    msg_*    é  preciso   compilar  o  PHP  com  a  opção  --enable-sysvmsg   do  configure   • Utilize  o  comando  ipcs  para  monitorar  os   seguimentos  criados  e  ipcrm msg ID  para   remover  seguimentos  (você  também  pode  usar   ipcmk  para  criar  seguimentos) 51
  52. 52. IPC/msg.php <?php ! $key = getmypid(); $messageQueueId = msg_get_queue($key); ! $messageSent = 'PHP e seus demônios'; $messageWasSent = msg_send($messageQueueId, 2, $messageSent); if (! $messageWasSent) { echo 'Falha ao enviar mensagem' . PHP_EOL; exit(2); } ! if (! msg_receive($messageQueueId, 2, $msgType, 1024, $messageReceived, true, 0, $error)) { echo 'Falha ao ler mensagem' . $error . PHP_EOL; exit(3); } echo 'Mensagem recebida: ' . $messageReceived . PHP_EOL; ! if (! msg_remove_queue($messageQueueId)) { echo 'Falha ao remover fila de mensagens'. PHP_EOL; exit(3); } 52
  53. 53. Par  de  sockets • Dois  sockets  conectados  armazenados  em  um   array   • Conexão  de  duas  vias,  as  mensagens  são   entregues  no  mesmo  instante 53
  54. 54. IPC/msg.php <?php ! $sockets = array(); ! if (false === socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { echo 'Falha ao criar par de sockets: ' . socket_strerror(socket_last_error()) . PHP_EOL; } ! $pid = pcntl_fork(); if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; } elseif ($pid > 0) { ! ! ! socket_close($sockets[0]); $messageWritten = 'Mensagem enviada pelo processo pai'; if (false === socket_write($sockets[1], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); } $messageGiven = socket_read($sockets[1], 1024, PHP_BINARY_READ); echo 'Mensagem no processo pai: ' . "t" . $messageGiven . PHP_EOL; socket_close($sockets[1]); ! } else { ! ! ! socket_close($sockets[1]); $messageWritten = 'Mensagem enviada pelo processo filho'; if (false === socket_write($sockets[0], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); } $messageGiven = socket_read($sockets[0], 1024, PHP_BINARY_READ); echo 'Mensagem no processo filho: ' . "t" . $messageGiven . PHP_EOL; socket_close($sockets[0]); } 54
  55. 55. Outras  formas • • • • • • • • APC   Memcached   MongoDB   MySQL   RabbitMQ   Redis   SQLite   … 55
  56. 56. PERFORMANCE 56
  57. 57. • Não  existe  garbage  collection,  o  processo   principal  não  morre   • Utilize  as  funções  gc_enable()  e   gc_collect_cycles()   • O  PHP  possui  um  cache  padrão  de  arquivos   abertos  (em  memória)  isso  pode  prejudicar  a   performance  do  daemon,  utilize   clearstatcache()  para  remover  esse  cache   • Utilizar  IPC  sem  limpar  os  dados  corretamente   pode  ocasionar  uma  série  de  problemas 57
  58. 58. BIBLIOTECAS 58
  59. 59. • AraraProcess  (https://github.com/Arara/ Proccess)   • PHP-­‐Daemon  (https://github.com/shaneharter/ PHP-­‐Daemon)   • System_Daemon  (http://pear.php.net/package/ System_Daemon)   • ZendX_Console_Process_Unix  (http:// framework.zend.com/manual/1.12/en/ zendx.console.process.unix.html) 59
  60. 60. PERGUNTAS 60
  61. 61. CONCLUSÃO 61
  62. 62. Links • @henriquemoody  na  maioria  das  redes  sociais   (about.me,  BitBucket,  Coderbits,  GitHub,  SlideShare,   Twitter…)   • Código  da  palestra:  https://github.com/henriquemoody/ php-­‐e-­‐seus-­‐demonios/tree/1.0.0   • Ícones:  http://www.visualpharm.com   • Formatação  de  código:  https://sublime.wbond.net/ packages/Highlight 62
  63. 63. Referências • • • • • • • • • • • • • • • http://en.wikipedia.org/wiki/Cron   http://en.wikipedia.org/wiki/Daemon_(computing)   http://en.wikipedia.org/wiki/Init   http://en.wikipedia.org/wiki/POSIX   http://man7.org/linux/man-­‐pages/man7/signal.7.html   http://php.net/ChangeLog-­‐4.php   http://php.net/cli   http://php.net/ncurses   http://php.net/newt   http://php.net/pcntl   http://php.net/posix   http://php.net/readline   http://pt.wikipedia.org/wiki/Daemon_(computação)   http://www.slideshare.net/jkeppens/php-­‐in-­‐the-­‐dark   http://www.win.tue.nl/~aeb/linux/lk/lk-­‐10.html 63

×