300 likes | 433 Views
Overview. Last Lecture Broadcast and multicast This Lecture Daemon processes and advanced I/O functions Source: Chapters 13&14 of Stevens’ book Next Lecture Unix domain protocols and non-blocking I/O Source: Chapters 15&16 of Stevens’ book. daemon.
E N D
Overview • Last Lecture • Broadcast and multicast • This Lecture • Daemon processes and advanced I/O functions • Source: Chapters 13&14 of Stevens’ book • Next Lecture • Unix domain protocols and non-blocking I/O • Source: Chapters 15&16 of Stevens’ book
daemon • A daemon is a process that runs in the background and is independent of control from all terminals • Reasons for daemons’ independence of terminals • Prevent daemons’ error message from appearing on a user’s terminal • Signals generated from terminal keys must not affect any daemons that were started from that terminal earlier • Ways to start a daemon • Started by the system initialization scripts • Started by inetd superserver • Performed by cron daemon on a regular basis • Started from user terminals (foreground or background)
syslogd daemon • How it works? • Read the configuration file /etc/syslog.conf • A Unix domain socket is created and bound to the pathname /var/run/log • A UDP socket is created and bound to port 514 • The pathname /dev/klog is opened to read kernel error messages • Runs in an infinite loop that calls select, waiting for any one of the above descriptors to be readable, reads the log message, and does what the configuration file says to do with that message. • If the daemon receives the SIGHUP signal, it rereads the configuration file
syslog function • How to send log messages? • create a Unix domain datagram socket and send our messages to the pathname the daemon has bound, or send them to port 514 by a UDP socket • syslog function • An easy interface to the syslogd daemon • void syslog(int priority, const char *message, …); • priority is a combination of a level and a facility shown later • message is like a format string to printf, with the addition of a %m specification, which is replaced with the error message corresponding to the current value of errno.
level • Log messages have a level between 0 and 7 • If no level is specified, LOG_NOTICE is the default
facility • Identify the type of process sending the message • If no facility is specified, LOG_USER is the default
Example for syslog • The following call could be issued by a mail daemon when a call to open unexpectedly fails: • syslog(LOG_INFO|LOG_MAIL, “open(%s ): %m”, file); • When an application calls syslog for the first time, it creates a Unix domain datagram socket and then calls connect to the well-known pathname of the socket created by the syslogd daemon. This socket remains open until the process terminates. • Alternatively, the process can call openlog and closelog • void openlog(const char *ident, int options, int facility); • ident is a string that will be inserted in front of each log message • options is formed as the logical OR of one or more of the constants in Figure 12.3 • facility specifies a default facility • void closelog(void);
daemon_init function • Control flow of daemon_init (refer to lib/daemon_init.c) • fork: change the process into a child process • setsid: create a new session and the process becomes the session leader and group leader • Ignore SIGHUP and fork again, so that the daemon cannot automatically acquire a controlling terminal should it open a terminal device in the future. We must ignore SIGHUP because when the session leader terminates, all processes in the session are sent the SIGHUP signal • Set flag for error functions (err_XXX) so that they send error messages to syslogd. We cannot use printf to print any error message from a daemon (because of no controlling terminal) • Change working directory and clear file mode creation mask • Close any open descriptors • openlog for errors
Daemon invoked by inetd • Control flow (refer to inetd/daytimetcpsrv3.c) • Set daemon flag so that err_XXX can print error messages to syslogd • openlog • Use getpeername to find out the peer address • Receive requests from the client by reading from the descriptor 0 • Send response to the client • Close connection.
tcpd • Control flow • Check the client IP address using getpeername • Check the service (port number) using getsockname • Compare the above with the corresponding entries in hosts.allow and hosts.deny files and then decide if the connection should be closed or not • If the connection is allowed, call exec to start the server (using argv)
Socket timeouts • Three ways to place a timeout on an I/O operation involving a socket • Call alarm, which generates the SIGALRM signal when the specified time has expired (refer to lib/connect_timeo.c and advio/dgclitimeo3.c) • Block waiting for I/O in select, which has a time limit as an argument (refer to lib/readable_timeo.c) • Use the newer SO_RCVTIMEO and SO_SNDTIMEO socket options (refer to advio/dgclitimeo2.c) • The important point for the programmer is to find out how to test the timeout condition.
recv and send • Prototype • ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); • ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags); • Both return: number of bytes read or written if OK, -1 on error • The first three arguments are the same as the first three arguments to read and write • flags is either 0, or is formed by logically OR’ing one or more of the constants shown in Figure 13.6
readv and writev • Prototype • ssize_t readv(int filedes, const struct iovec *iov, int iovcnt); • Called scatterread since the input data is scattered into multiple application buffers • ssize_t writev(int filedes, const struct iovec *iov, int iovcnt); • Called gatherwrite since multiple buffers are gathered for a single output operation. • Both return: number of bytes read or written if OK, -1 on error • struct iovec { void *iov_base; size_t iov_len;}; • iovcnt is the number of elements in the array of iovec structures
recvmsg and sendmsg • Prototype • ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); • ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags); • Both return: number of bytes read or written if OK, -1 on error • struct msghdr { void *msg_name; socklen_t msg_namelen; struct iovec *msg_iov; size_t msg_iovlen; void *msg_control; socklen_t msg_controllen; int msg_flags;} • msg_name and msg_namelen are used for unconnected UDP sockets to store a socket address and its length • msg_control and msg_controllen are used for optional ancillary data • msg_flags is used only by recvmsg. When recvmsg is called, the flags is copied into the msg_flags member and this value is used by the kernel to drive its receiving processing. This value is then updated based on the result of recvmsg • msg_flags is ignored by sendmsg since this function uses its argument flags
Ancillary data • struct cmsghdr {socklen_t cmsg_len; int cmsg_level; int cmsg_type; /* followed by char array */ }
Miscellaneous • Ways to find out how much data is queued • Use MSG_PEEK flag (MSG_DONTWAIT for nonblocking) • Use the FIONREAD command of ioctl • Handle sockets with standard I/O library • Use fdopen to convert a socket (descriptor) into a FILE pointer • Standard I/O uses three types of buffering • Fully buffered: I/O takes place only when the buffer is full, or the process calls fflush or exit • Line buffered: I/O takes place only when a new line is encountered, or the process calls fflush or exit • Unbuffered: I/O takes place each time a standard I/O output function is called • Most Unix implements standard I/O based on the following rules • Standard error is always unbuffered; standard input and output, and other streams are fully buffered, unless they refer to a terminal device, in which case they are line buffered.