Professional Documents
Culture Documents
Management
UNIT II
Socket Options
File Control
I/O Control
Signal Driven I/O
Server Example
#define MYPORT 3490 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(void) {
int sockfd, new_fd; // listen on sockfd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int sin_size;
close(new_fd);
}
return 0;
}
#include <netinet/in.h>
Client Example
#include <sys/socket.h>
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
buf[numbytes] = '\0';
printf("Received: %s",buf);
close(sockfd);
return 0;
}
Signals
• Introduced in UNIX systems to simplify IPC.
• Signal is a software interrupt
• Used by the kernel to notify processes of system
events or can be used for inter proccess
communication.
• A signal is a short message sent to a process, or
group of processes, containing the number
identifying the signal.
– No data is delivered with traditional signals.
– POSIX.4 defines i/f for queueing & ordering
RT signals arguments.
Signal Transmission
• Signal sending:
– Kernel updates descriptor of destination process.
• Signal receiving:
– Kernel forces target process to “handle” signal.
• Pending signals are sent but not yet received.
– Up to one pending signal per type for each process,
except for POSIX.4 signals.
– Subsequent signals are discarded.
– Signals can be blocked, i.e., prevented from being
received.
Signal-Related Data Structures
• sigset_t stores array of signals sent to a process.
• The process descriptor (struct task_struct in
<linux/sched.h>) has several fields for tracking sent,
blocked and pending signals.
Signal handling system call :
struct sigaction {
void (*sa_handler)();/* handler address, or
SIG_IGN(ignore),
or SIG_DFL(default) */
sigset_t sa_mask; /* blocked signal list */
int sa_flags; /* options e.g., SA_RESTART */
}
Signal Disposition
Disposition : Action associated with signals
• Ignore the signal (most signals can simply be ignored,
except SIGKILL and SIGSTOP)
• Handle the signal disposition via a signal handler routine.
This allows us to gracefully shutdown a program when
the user presses Ctrl-C (SIGINT).
• Block the signal. In this case, the OS queues signals for
possible later delivery
• Let the default apply SIG_DFL (usually process
termination)
• Signals can be ignored SIG_IGN
Original Signal Handling (Version 7)
• Two includes: <sys/types.h> and <signal.h>
• handler can either be:
– a function (that takes a single int which is the
signal)
– the constant SIG_IGN
– the constant SIG_DFL
• signal will return SIG_ERR in case of error
Signal Handling System Calls
• int sigaction(int sig, const
struct sigaction *act, struct
sigaction *oact);
– Replaces the old signal() function.
– Used to bind a handler to a signal.
– For RT signals, the handler’s prototype is of
form:
• void (*sa_sigaction)(int,
siginfo_t *, void *);
Common Signals
• SIGHUP (1):sent to a process when its controlling
terminal has disconnected
• SIGINT (2) : Ctrl-C (or DELETE key)
• SIGQUIT (3):Ctrl-\ (default produces core)
• SIGSEGV (11):Segmentation fault
• SIGKILL (4):Illegal instruction (default core)
• SIGUSR[1,2]:User-defined signals (10,12)
• kill –l will list all signals
• SIGFPE (8):Floating Point Exception (divide by 0;
integer overflow; floating-point underflow)
Alarming Signals
• SIGALRM can be used as a kind of “alarm clock”
for a process
• By setting a disposition for SIGALRM, a process
can set an alarm to go off in x seconds with the
call:
– unsigned int alarm(unsigned int numseconds)
• Alarms can be interrupted by other signals
• Examples: mysleep.c, impatient.c
• SIGCHLD signals – Sent by kernel when a process terminates
to the parent of the child
• When Child is in zombie state it maintains information about
the child termination status, process ID… to the parent to be
fetched later.
• wait - wait for a child process to stop or terminate. Returns
process ID and status of terminated child
• #include <sys/wait.h>
pid_t wait(int *stat_loc);
- waits untill first child terminates
• pid_t waitpid(pid_t pid, int *stat_loc, int options);
- specifies process ID we want to wait for WNOHANG option
tells waitpid not to block if there exist running children that have
not yet terminated
-Difference between wait() and waitpid(): It is used since unix
signals are not queued. Can be used when the same client has
multiple (n) connections with the concurrent server and when
the child terminates n FIN signals sent to child process which
responds by sending n SIGCHLD to parent.As unix signals are
not queued the parent leaves zombie child if wait is used.
Hence waitpid must be used within loop
I/O Blocking
socket();
bind() ;
listen();
while
accept();
recv() ;
send() ;
• Simple server has blocking problem
– Suppose 5 connections accepted.
– Suppose next accept() blocks.
– Other connections cannot send and receive.
– Cannot get keyboard input either.
select() :I/O Multiplexing
• waits on multiple file descriptors and timeout
• returns when any file descriptor
– is ready to be read or
– written or
– indicate an error, or
– timeout exceeded
• advantages
– simple
– application does not consume CPU cycles while
waiting
• disadvantages
– does not scale to large number of file descriptors
Example:
Server Programming
• byte ordering
• separating records in streams
• use of select()
• misinterpreting the project specification
• not knowing all available system calls
There are more System Calls
• #include <arpa/inet.h>
• src
– (Input) The pointer to the null-terminated character string that contains the text
presentation form of an IPv4 / IPV6 address.
dst
– (Output) The pointer to a buffer into which the function stores the numeric
address. The calling application must ensure that the buffer referred to by dst is
large enough to hold the numeric address (4 bytes for AF_INET or 16 bytes for
AF_INET6).
size
• (Input) The size of the buffer pointed at by dst.
• sock_ntop
- takes a pointer to a socket address structure, looks
inside the structure, and calls the appropriate function to
return the presentation format of the address.
• #include "unp.h“
int getsockopt(
int sockfd,
int level, /* SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP etc */
int optname, /* option name */
void *optval, /* option value */
socklen_t *optlen); /* data length of option*/
int setsockopt(
int sockfd,
int level,
int optname,
const void *optval,
socklen_t optlen);
Two types of socket options
• Flag options
– Enable or disable a feature
– Optval points to an integer which can be zero or non-zero
• Value options
– Pass a value to/from the OS
– Optval points to some structure
Level of an Option
• SO_KEEPALIVE
– Regularly probes if connection is alive
• SO_LINGER
– Linger till all data is sent before returning from close() on a
TCP connection.
• SO_RCVBUF/ SO_SNDBUF
– Size of receive/send buffers on socket.
• SO_RCVTIMEO/SO_SNDTIMEO
– Place timeout on receive/send operation.
Some more socket options
• IP_TOS
– Set type of service field in IP datagram
• IP_TTL
– Set time-to-live field in IP datagram
• IP_ADD_MEMBERSHIP / IP_DROP_MEMBERSHIP
– Join/Drop a multicast group
• TCP_KEEPALIVE
– Probe timer for TCP connection probing
• TCP_MAXSEG / TCP_MAXRT
– TCP maximum segment size, maximum retransmit time
System call
recvfrom() No datagram ready
EWOULDBLOCK
Return ok
Process datagram Copy complete
Signal driven I/O
Application Operating system
Deliver SIGIO
Signal Handler datagram ready
System call
recvfrom() Copy datagram
Return ok
Process datagram Copy complete
fcntl()
flags |= O_NONBLOCK;
– FIONREAD
• Return number of bytes in socket buffer
– SIOCGIFCONF
• Get list of all interfaces
– SIOCGIFBRDADDR/ SIOCSIFBRDADDR
• Get/set broadcast address
– SIOCGARP/SIOCSARP/SIOCDARP
• Get/modify/delete ARP cache entry.
– SIOCADDRT/SIOCDELRT
• Add/delete routes
Signal-driven I/O
Signal driven I/O
Application Operating system
Deliver SIGIO
Signal Handler datagram ready
System call
recvfrom() Copy datagram
Return ok
Process datagram Copy complete
Conditions that generate SIGIO
• UDP
– Datagram arrival
– Socket errors
Datagram queue
SIGIO
Handler
User Space
while(1) {
/* Block SIGIO temporarily */
Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
/* Unblock SIGIO */
Sigprocmask(SIG_SETMASK, &oldmask, NULL);
Do something else…
}
I/O Models
I/O Multiplexing
Chapter 6 (UNP Book)
I/O Models
1. Blocking I/O
2. Non-blocking I/O
3. I/O multiplexing – select()
4. Signal driven I/O
5. Asynchronous I/O
Two steps in data reception
Return ok
Read datagram Copy complete
Non-Blocking I/O (polling)
Application Operating system
System call
recvfrom() No datagram ready
EWOULDBLOCK
Time System call
recvfrom() No datagram ready
EWOULDBLOCK
Return ok
Read datagram Copy complete
I/O Multiplexing
Concurrent Server
select() listenfd
Remote Clients C1 C2 F3 F4 P5
Or files
Or pipes
I/O Multiplexing
Application Operating system
Time
Process blocks Wait for data
on any fd
Return readable
datagram ready
recvfrom() System call Copy datagram
Return ok
Read datagram Copy complete
Signal driven I/O
Application Operating system
Concurrent Server
select() listenfd
Clients C1 C2 C3 C4 C5
select() call
• Types of event
– ready for read
– ready for write
– Exception condition
select() call
int select(
int maxfdp1, /* max. fd + 1 */
fd_set *readfds, /* read ready? */
fd_set *writefds, /* write ready? */
fd_set *exceptfds, /* exceptions? */
struct timeval *timeout);
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
}
struct fd_set
• Set of descriptors that we want to wait
on for events.
• Manipulation macros
– void FD_ZERO(fd_set *fds)
– void FD_SET (int fd, fd_set *fds)
– void FD_CLR (int fd, fd_set *fds)
– int FD_ISSET(int fd, fd_set *fds)
Non-forking Concurrent
Server
fdset rdset, wrset;
int listenfd, connfd1, connfd2;
int maxfdp1;
………
Connection establishment etc.
………
/* initialize */
FD_ZERO(&rdset);
FD_ZERO(&wrset);
for( ;; ) {
FD_SET(connfd1, &rdset);
FD_SET(connfd2, &wrset);
FD_SET(listenfd, &rdset);
• Return Value
• Returns the number of elements in the ufds array that have had event
occur on them; this can be zero if the timeout occurred. Also returns
-1 on error (and errno will be set accordingly.)
Shutdown()
• Close – Decrements descriptors reference count
and closes socket when count reaches 0
• Close terminates both direction of data transfer
• Shutdown does half close- other end can still send
data after one end of the connection closes.