Вобщем так: стоит задача написать небольшой демон, работающий с сетью.
Я делаю так:
1) Готовлю сокет, вызываю к нему Listen
2) Создаю потоки с помощью pthread_create
3) В новый потоках вызывается accept
4) Отключаю вызывающий поток от консоли с помощью daemon
Вопрос в слудующем: чем занять вызывающий поток, т.к. иначе он вываливается и останавливаются все остальные потоки?
И еще в top я вижу только одну запись, почему? Скажем записей httpd я вижу куду больше. При этом хочу заметить, что pthread_create ошибок не возвращает, соккет начинает принимать соединения (проверенно). pthread_detach ситуацию не решил.
Как в этом случае поступить? Можно, конечно, вызывающий (первый) поток тоже отправить на accept. Но что лучше?
Здравствуйте, Программер, Вы писали:
П>Вобщем так: стоит задача написать небольшой демон, работающий с сетью. П>Я делаю так: П>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 socketwhile ( 1 ) {
if ( fd = accept(???) )
pthread_create(the_handler ....);
}
return 0;
}
Здравствуйте, Программер, Вы писали: П>Вобщем так: стоит задача написать небольшой демон, работающий с сетью.
Рекомендую найти в гугле фак эхи fido7.ru.unix.prog (точнее, приложение к нему) "Как писать сервера".
Прямо на groups.google.com набираешь
как писать сервера group:fido7.ru.unix.prog
Там же есть и "Signals FAQ", который также пригодится, особенно если ты связался с pthreads и демонами
Здравствуйте, Программер, Вы писали:
П>И еще в top я вижу только одну запись, почему? Скажем записей httpd я вижу куду больше. При этом хочу заметить, что pthread_create ошибок не возвращает, соккет начинает принимать соединения (проверенно). pthread_detach ситуацию не решил.
Если система достаточно современная, и на ней используются ntpl треды, то pthread_create не создает процессов, поэтому и в top их не видно. httpd возможно форкается. При чем здесь pthread_detach?
Никогда не делайте ничего правильно с первого раза, иначе никто потом не оценит, как это было сложно.
П>Вопрос в слудующем: чем занять вызывающий поток, т.к. иначе он вываливается и останавливаются все остальные потоки?
Пример создания демона:
/*
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); // Вот пример, чем может заниматься вызывающий поток.
}