Демоны
От: Программер  
Дата: 22.11.04 16:51
Оценка:
Вобщем так: стоит задача написать небольшой демон, работающий с сетью.
Я делаю так:
1) Готовлю сокет, вызываю к нему Listen
2) Создаю потоки с помощью pthread_create
3) В новый потоках вызывается accept
4) Отключаю вызывающий поток от консоли с помощью daemon

Вопрос в слудующем: чем занять вызывающий поток, т.к. иначе он вываливается и останавливаются все остальные потоки?
И еще в top я вижу только одну запись, почему? Скажем записей httpd я вижу куду больше. При этом хочу заметить, что pthread_create ошибок не возвращает, соккет начинает принимать соединения (проверенно). pthread_detach ситуацию не решил.

Как в этом случае поступить? Можно, конечно, вызывающий (первый) поток тоже отправить на accept. Но что лучше?
Re: Демоны
От: Garrrrr  
Дата: 22.11.04 17:00
Оценка: 2 (1)
Здравствуйте, Программер, Вы писали:

П>Вобщем так: стоит задача написать небольшой демон, работающий с сетью.

П>Я делаю так:
П>1) Готовлю сокет, вызываю к нему Listen
П>2) Создаю потоки с помощью pthread_create
П>3) В новый потоках вызывается accept
П>4) Отключаю вызывающий поток от консоли с помощью daemon

П>Вопрос в слудующем: чем занять вызывающий поток, т.к. иначе он вываливается и останавливаются все остальные потоки?

П>И еще в top я вижу только одну запись, почему? Скажем записей httpd я вижу куду больше. При этом хочу заметить, что pthread_create ошибок не возвращает, соккет начинает принимать соединения (проверенно). pthread_detach ситуацию не решил.

П>Как в этом случае поступить? Можно, конечно, вызывающий (первый) поток тоже отправить на accept. Но что лучше?

Вообще обычно 1 (первый, главный) поток занимается accept() и уже после успешного возврата создаются потоки
для обработки соединения, т е получается что то вроде
void* the_handler(void *arg)
{
  int *fd = *(int*)arg;
  // processing the connection
}

int main(int, char**)
{
  // creating & preparing socket
  while ( 1 ) {
    if ( fd = accept(???) )
      pthread_create(the_handler ....);
  }
  return 0;
}
Re[2]: Демоны
От: Программер  
Дата: 22.11.04 17:05
Оценка:
Здравствуйте, Garrrrr, Вы писали:

G>Вообще обычно 1 (первый, главный) поток занимается accept() и уже после успешного возврата создаются потоки


Cпасибо!
Re: Демоны
От: Eugene Kilachkoff Россия  
Дата: 22.11.04 18:33
Оценка: 2 (1)
Здравствуйте, Программер, Вы писали:
П>Вобщем так: стоит задача написать небольшой демон, работающий с сетью.
Рекомендую найти в гугле фак эхи fido7.ru.unix.prog (точнее, приложение к нему) "Как писать сервера".
Прямо на groups.google.com набираешь

как писать сервера group:fido7.ru.unix.prog

Там же есть и "Signals FAQ", который также пригодится, особенно если ты связался с pthreads и демонами
... << RSDN@Home 1.1.3 stable >>
Re: Демоны
От: White Eagle Россия  
Дата: 23.11.04 07:28
Оценка: 1 (1)
Здравствуйте, Программер, Вы писали:

П>И еще в top я вижу только одну запись, почему? Скажем записей httpd я вижу куду больше. При этом хочу заметить, что pthread_create ошибок не возвращает, соккет начинает принимать соединения (проверенно). pthread_detach ситуацию не решил.


Если система достаточно современная, и на ней используются ntpl треды, то pthread_create не создает процессов, поэтому и в top их не видно. httpd возможно форкается. При чем здесь pthread_detach?
Никогда не делайте ничего правильно с первого раза, иначе никто потом не оценит, как это было сложно.
Re: Демоны
От: fefelov Россия  
Дата: 24.11.04 08:53
Оценка:
П>Вопрос в слудующем: чем занять вызывающий поток, т.к. иначе он вываливается и останавливаются все остальные потоки?

Пример создания демона:
/*
  Description: Daemonization routine.
*/
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "error.h"
#include "daemon.h"

/* daemon ***********************************************************
*/
int
daemon(const char* rootDir, const char* pidFile)
{
  int  rc;
  int  maxfd;
  int  fd;
  char s[32];

  /* fork() so the parent can exit, this returns control to the command
     line or shell invoking our program. This step is required so that
     the new process is guaranteed not to be a process group leader. The
     next step, setsid(), fails if we're a process group leader.
  */
  rc = fork();
  if (rc < 0)
    stopOnError("daemon(): unable to fork()");
  if (rc > 0)
    exit(EXIT_SUCCESS); /* End parent process. */

  /* setsid() to become a process group and session group leader. Since
     a controlling terminal is associated with a session, and this new
     session has not yet acquired a controlling terminal our process now
     has no controlling terminal, which is a good thing for daemons.
  */
  rc = setsid();
  if (rc == -1)
    stopOnError("daemon(): unable to setsid()");

  /* fork() again so the parent (the session group leader) can exit. This
     means that we, as a non-session group leader, can never regain a
     controlling terminal.
  */
  rc = fork();
  if (rc < 0)
    stopOnError("daemon(): unable to fork()");
  if (rc > 0)
    exit(EXIT_SUCCESS); /* End parent process. */

  /* chdir("/") to ensure that our process doesn't keep any directory
     in use. Failure to do this could make it so that an administrator
     couldn't unmount a filesystem, because it was our current directory.
  */
  if (rootDir != NULL)
  {
    rc = chdir(rootDir);
    if (rc == -1)
      stopOnError("daemon(): unable to chdir()");
  }

  /*  We close all open file descriptors that may have been inherited
     from the parent process. This is to reduce the resources we use.
  */
  maxfd = sysconf(_SC_OPEN_MAX);
  for (fd = maxfd - 1; fd >= 0; fd--)
    close(fd); /* Ignore errors. */

  /* Establish new open descriptors for stdin, stdout, and stderr. Even if
     we don't plan to use them, it is still a good idea to have them open.
  */
  fd = open("/dev/null", O_RDWR); /* stdin - file handle 0. */
  dup(fd);                        /* stdout - file handle 1. */
  dup(fd);                        /* stderr - file handle 2. */

  /* Write pid-file.
  */
  if (pidFile != NULL)
  {
    sprintf(s, "%u\n", getpid());
    fd = open(pidFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
    if (fd == -1)
      stopOnError("daemon(): unable to create pid-file");
    if (write(fd, s, strlen(s)) == -1)
      stopOnError("daemon(): unable to write pid-file");
    close(fd);
  }

  return 0;
}

Пример запуска демона:
int
main(void)
{
  daemon("/tmp", "/var/run/my.pid");
  while(1) sleep(1); // Вот пример, чем может заниматься вызывающий поток.
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.