250 likes | 496 Views
Daemon Processes. Computer Network Programming. Motivation. You wrote a server and you want to have it running all the time so that clients can connect and use your service at any time. Examples: Web serves, telnet servers, ftp servers, domain name servers, etc.
E N D
Daemon Processes Computer Network Programming
Motivation • You wrote a server and you want to have it running all the time so that clients can connect and use your service at any time. • Examples: Web serves, telnet servers, ftp servers, domain name servers, etc. • You don’t want your server to be killed when you logout or when you press ^C. • You want your server to be running in the background silently without disturbing others and without getting disturbed by others. • You want to run it for a long-time: for days, months, years maybe. • You want it to be started automatically when the system boots up.
Daemon Processes • Solution: You need to run your server as a daemon! • A daemon is a process that runs in the background and is independent of control from all terminals. • A daemon process usually performs server tasks and administrative tasks • There are 20-50 daemon processes running in a Unix system: silently.
Some daemons running on a Unix system root 139 1 0 Mar 22 ? 0:07 /usr/sbin/inetd -s root 144 1 0 Mar 22 ? 0:01 /usr/lib/nfs/statd root 161 1 0 Mar 22 ? 1:49 /usr/lib/autofs/automountd root 146 1 0 Mar 22 ? 0:00 /usr/lib/nfs/lockd root 227 1 0 Mar 22 ? 0:07 /usr/lib/utmpd root 165 1 0 Mar 22 ? 0:22 /usr/sbin/syslogd -n -z 18 root 179 1 0 Mar 22 ? 0:02 /usr/sbin/cron root 303 1 0 Mar 22 ? 0:01 /usr/lib/snmp/snmpdx -y -c /etc/snmp/conf root 295 1 0 Mar 22 ? 0:03 /usr/lib/nfs/mountd root 297 1 0 Mar 22 ? 0:00 /usr/lib/nfs/nfsd -a 16 root 313 1 0 Mar 22 ? 0:00 /usr/lib/dmi/snmpXdmid -s aspendos root 16223 1 0 Mar 26 ? 1:00 /usr/lib/lpsched root 312 1 0 Mar 22 ? 0:00 /usr/lib/dmi/dmispd root 284 1 0 Mar 22 ? 0:08 /usr/dt/bin/dtlogin -daemon root 19274 139 0 Mar 27 ? 0:00 in.rlogind root 15160 1 0 Mar 26 ? 0:00 /aspendosh/apache/bin/httpd root 791 139 0 Mar 23 ? 0:18 /usr/dt/bin/rpc.ttdbserverd root 24477 139 0 14:10:32 ? 0:00 in.telnetd ………. truncated output
Why independence from all terminals • Assume you start your daemon from a terminal (xterm, dump terminal, etc). • You want to use the same terminal for other tasks. Hence you don’t want the daemon to print out messages to the screen while you are doing some other tasks • When the user presses interrupt keys (^C), you don’t want your daemon to be killed.
How to start a daemon • Start it from a system initialization script during system startup. • inetd, syslogd, sendmail, httpd are examples • inetd starts the daemon (service) • ftpd, telnetd, etc. are started from the inetd process. • cron daemon starts them at regular intervals • at command can be used to execute a server at a well-specified time in the future. • Can be started from user terminal: • to test the daemon • to restart a died daemon
syslogd daemon • Used to log messages (error messages, information messages, all kinds of messages) • Daemons usually don’t print messages on the screen. They send the messages to the syslogd and it logs everything or prints to console if necessary
Uses select() to multiplex input from multiple sources - input from UDP socket (port 514) - input from Unix domain socket (/var/run/log) - input from Kernel (/dev/klog device) - output to log file(s) - output to console - output to user - output to an other syslogd console Log file Daemon Daemon Udp Socket syslogd Unix Domain Socket Process Process Daemon /dev/klog Syslogs reads a configuration file /etc/syslog.conf to learn what to do with each kind of message kernel Messages
syslog() function • A daemon does not have a controlling terminal • (a keyboard/screen for example), hence it can not call printf.. • It calls syslog() function to output a error messages or log messages to the syslogd and syslogd stores the message or writes it to the console. Syslog() function sends the message to the syslogd. void syslog(int priority, const char* message, ….); • priority is combination oflevel and facilityflags. • message is a format string like printf(). • then some arguments may follow
Level denotes the severity of the message: crital, error, info, debug message etc. Facility identifies the type of the process sending the message ftp daemon, kernel, mail system, a user process, local use, etc. Example: syslog (LOG_INFO | LOG_LOCAL2, “rename error: %s %s”, file1, file2) syslogd uses the configuration file /etc/syslog.conf and level and facility parameters to decide what to do with each incoming message. /etc/syslogd.conf file content *.err;kern.notice;auth.notice /dev/console *.err;kern.debug;daemon.notice;mail.crit /var/adm/message
Use of syslog() function static void err_doit(int errnoflag, int level, const char *fmt, va_list ap) { int errno_save, n; char buf[MAXLINE]; errno_save = errno; vsprintf(buf, fmt, ap); n = strlen(buf); if (errnoflag) snprintf(buf+n, sizeof(buf)-n, ": %s", strerror(errno_save)); strcat(buf, "\n"); if (daemon_proc) { syslog (level, buf); /* send to syslogd daemon for logging */ } else { fflush(stdout); /* print out to the screen */ fputs(buf, stdout); fflush(stdout); } return; }
How can we daemonize a process #define MAXFD 64 extern int daemon_proc; /* defined in error.c */ void daemon_init(const char *pname, int facility) { int i; pid_t pid; if ( (pid = Fork()) != 0) exit(0); /* parent terminates */ /* 1st child continues */ setsid(); /* become session leader */ Signal(SIGHUP, SIG_IGN); if ( (pid = Fork()) != 0) exit(0); /* 1st child terminates */ /* 2nd child continues */ daemon_proc = 1; /* for our err_XXX() functions */ chdir("/"); /* change working directory */ umask(0); /* clear our file mode creation mask */ for (i = 0; i < MAXFD; i++) close(i); openlog(pname, LOG_PID, facility); }
A daemon process will never receive the following signals from the kernel: SIG_HUP, SIG_INT, SIH_WINCH. Usually SIG_HUP signal is given to the daemon by system administrators to make the daemon reread its confıguration file(s). Exampe: kill -HUP inetd
Daytime tcp server as a daemon int main(int argc, char **argv) { int listenfd, connfd; socklen_t addrlen, len; struct sockaddr *cliaddr; char buff[MAXLINE]; time_t ticks; daemon_init(argv[0], 0); if (argc == 2) listenfd = Tcp_listen(NULL, argv[1], &addrlen); else if (argc == 3) listenfd = Tcp_listen(argv[1], argv[2], &addrlen); else err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>"); cliaddr = Malloc(addrlen); for ( ; ; ) { len = addrlen; connfd = Accept(listenfd, cliaddr, &len); err_msg("connection from %s", Sock_ntop(cliaddr, len)); ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); Write(connfd, buff, strlen(buff)); Close(connfd); } }
inetd daemoninternet superserver There are a lot of internet servers that will be running on a typical Unix system - FTP, telnet, rlogin, TFTP, daytime, time, echo Servers In earlier systems, each service had a process (daemon) associated with. - each process does the same startup tasks creating sockets, binding listening…. - each process took an entry in the process table - these processes are asleep most of the time waiting for requests. After 4.3 BSD Unix system, a single server inetd daemon is used to wait for requests for all of these services and then create the corresponding server process on demand.
/etc/inetd.conf file ftp stream tcp nowait root /usr/sbin/in.ftpd in.ftpd telnet stream tcp nowait root /usr/sbin/in.telnetd in.telnetd name dgram udp wait root /usr/sbin/in.tnamed in.tnamed shell stream tcp nowait root /usr/sbin/in.rshd in.rshd login stream tcp nowait root /usr/sbin/in.rlogind in.rlogind tftp dgram udp wait root /usr/sbin/in.tftpd in.tftpd -s /tftpboot reads the configuration file upon startup inetd Has a listening socket for each TCP service or a UDP socket for each UDP service and uses select() fork() and exec() ftpd telnetd rlogind …….
inetd and its child services aspendos{korpe}:> ps -ef | grep 139 user ppid pidtty process root 139 1 0 Mar 22 ? 0:07 /usr/sbin/inetd -s korpe 23440 139 1 02:15:11 ? 0:00 in.ftpd root 23414 139 0 02:14:16 ? 0:00 in.ftpd root 19274 139 0 14:26:13 ? 0:00 in.rlogind root 23401 139 0 02:13:55 ? 0:00 in.telnetd root 15076 139 0 Mar 26 ? 0:00 in.rlogind root 21069 139 0 19:00:56 ? 0:00 in.telnetd root 23377 139 0 02:13:18 ? 0:00 in.telnetd root 22720 139 0 23:16:04 ? 0:00 in.telnetd We have a separate child server process for each client. The parent of these servers is inetd.
steps performed byinetd socket() For each service listed in the /etc/inetd.conf file bind() listen() (if TCP) select() accept() (if TCP) fork() close connected socket (if TCP) parent child close all descriptors other than socket Dup socket to descriptors 0, 1, 2 close socket setgid, setusid exec() server
Wait and Nowait • For services that uses TCP, when inetd creates a child process, it does not wait until the child terminates before accepting a new service request. • The child uses a different connected socket than the listening socket of the inetd. • For services that uses UDP, when inetd creates a child process, inetd waits until the child terminates before accepting a new service request. • The child uses the same UDP socket that the inetd was waiting on for requests.
Daytime Server as Daemon invoked by inetd int main(int argc, char **argv) { socklen_t len; struct sockaddr * cliaddr; char buff[MAXLINE]; time_t ticks; daemon_inetd(argv[0], 0); cliaddr = Malloc(MAXSOCKADDR); len = MAXSOCKADDR; Getpeername(0, cliaddr, &len); err_msg("connection from %s", Sock_ntop(cliaddr, len)); ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); Write(0, buff, strlen(buff)); Close(0); /* close TCP connection */ exit(0); } extern int daemon_proc; /* defined in error.c */ void daemon_inetd(const char *pname, int facility) { daemon_proc = 1; openlog(pname, LOG_PID, facility); } We are writing to descriptor 0 since it corresponds to the socket. (normally it corresponds to stdin = keyboard)