Unix Programming - Module 5
Unix Programming - Module 5
Module 5:
(a). What are signals? Mention different source of signals? Write program
to setup signal handlers for SIGINT and SIGALRM.
Ans: Signals are software interrupts. Signals provide a way of handling
asynchronous events: a user at a terminal typing the interrupt key to stop a
program or the next program in a pipeline terminating prematurely.
When a signal is sent to a process, it is pending on the process to handle it. The process
can react to pending signals in one of three ways:
➢ Accept the default action of the signal, which for most signals will terminate
the process.
➢ Ignore the signal. The signal will be discarded and it has no affect whatsoever
on the recipient process.
➢ Invoke a user-defined function. The function is known as a signal handler
routine and the signal is said to be caught when this function is called.
DAEMON CHARACTERISTICS
The characteristics of daemons are:
▪ Daemons run in background.
▪ Daemons have super-user privilege.
▪ Daemons don’t have controlling terminal.
CODING RULES
▪ Call umask to set the file mode creation mask to 0. The file mode creation
mask that's inherited could be set to deny certain permissions. If the
daemon process is going to create files, it may want to set specific
permissions.
▪ Call fork and have the parent exit. This does several things. First, if the
daemon was started as a simple shell command, having the parent
terminate makes the shell think that the command is done. Second, the
child inherits the process group ID of the parent but gets a new process ID,
so we're guaranteed that the child is not a process group leader.
▪ Call setsid to create a new session. The process (a) becomes a session
leader of a new session, (b) becomes the process group leader of a new
process group, and (c) has no controlling terminal.
▪ Change the current working directory to the root directory. The current
working directory inherited from the parent could be on a mounted file
system. Since daemons normally exist until the system is rebooted, if the
daemon stays on a mounted file system, that file system cannot be
unmounted.
▪ Unneeded file descriptors should be closed. This prevents the daemon
from holding open any descriptors that it may have inherited from its
parent.
▪ Some daemons open file descriptors 0, 1, and 2 to /dev/null so that any
library routines that try to read from standard input or write to
standard output or standard error will have no effect. Since the daemon
is not associated with a terminal device, there is nowhere for output to be
displayed; nor is there anywhere to receive input from an interactive user.
Even if the daemon was started from an interactive session, the daemon
runs in the background, and the login session can terminate without
affecting the daemon. If other users log in on the same terminal device, we
wouldn't want output from the daemon showing up on the terminal, and
the users wouldn't expect their input to be read by the daemon.
(c). What is signal mask of a process? WAP to check whether the SIGINT
signal present in signal mask.
Ans: SIGNAL MASK:
• A process initially inherits the parent’s signal mask when it is created, but any
pending signals for the parent process are not passed on.
• A process may query or set its signal mask via the sigprocmask API:
#include <signal.h>
The following program illustrates the uses of sigsetjmp and siglongjmp APIs.
#include<iostream.h>
#include<stdio.h>
#include<unistd.h>
#include<signal
.h>
#include<setjmp
.h> sigjmp_buf
env;
void
callme(int
sig_num)
{ cout<< “catch signal:”
<<sig_num <<endl;
siglongjmp(env,2);
}
Int
main(
)
{
sigset_t sigmask;
struct sigaction
action,old_action;
sigemptyset(&sigmask);
if(sigaddset(&sigmask,SIGTERM)==-1) ||
sigprocmask(SIG_SETMASK,&sigmask,0)==-1)
perror(“set signal mask”);
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask,SIGSEG
V);
action.sa_handler=(void(*)())cal
lme; action.sa_flags=0;
if(sigaction(SIGINT,&action,&old_action)
==-1) perror(“sigaction”);
if(sigsetjmp(env,1)!=0)
{ cerr<<”return from
signal interruption”;
return 0;
} else cerr<<”return from first
time sigsetjmp is called”;
pause();
}
Ans: KILL
A process can send a signal to a related process via the kill API. This is a simple means of
interprocess communication or control. The function prototype of the API is:
#include<signal.h>
int kill(pid_t pid, int signal_num);
Returns: 0 on success, -1 on failure.
The signal_num argument is the integer value of a signal to be sent to one or more processes
designated by pid. The possible values of pid and its use by the kill API are:
pid > 0 The signal is sent to the process whose process ID is pid.
pid == 0 The signal is sent to all processes whose process group ID equals the process group
ID of the sender and for which the sender has permission to send the signal.
pid < 0 The signal is sent to all processes whose process group ID equals the absolute value
of pid and for which the sender has permission to send the signal.
pid == 1 The signal is sent to all processes on the system for which the sender has
permission to send the signal.
The following program illustrates the implementation of the UNIX kill command using the
kill API:
#include<iostream.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<signal.h>
int main(int argc,char** argv)
{ int pid, sig =
SIGTERM;
if(argc==3)
{
if(sscanf(argv[1],
”%d”,&sig)!=1)
{ cerr<<”invalid number:” << argv[1] <<
endl; return -1;
}
argv++,argc--;
}
while(
--
argc>0
)
ALARM
The alarm API can be called by a process to request the kernel to send the SIGALRM signal
after a certain number of real clock seconds. The function prototype of the API is:
#include<signal.h>
Unsigned int alarm(unsigned int time_interval);
Returns: 0 or number of seconds until previously set alarm The alarm API can be used to
implement the sleep API:
#include<signal.h>
#include<stdio.h>
#include<unistd.h> void
wakeup( ) { ; } unsigned int
sleep (unsigned int timer )
{
Struct sigaction action;
action.sa_handler=wakeup;
action.sa_flags=0;
sigemptyset(&action.sa_mask
);
if(sigaction(SIGALARM,&acti
on,0)==-1)
{
perror(“si
gaction”);
return -1;
}
(void)
alarm
(timer);
(void)
pause( );
return 0;
}
(f). What is error logging? With a neat block schematic discuss the error
login facility in BSD.
Ans: ERROR LOGGING
One problem a daemon has is how to handle error messages. It can't simply write
to standard error, since it shouldn't have a controlling terminal. We don't want all
the daemons writing to the console device, since on many workstations, the
console device runs a windowing system. A central daemon error-logging facility is
required.
Fig 12.1 The BSD syslog facility
Ans: SIGNAL:
The function prototype of the signal API is:
#include <signal.h>
The following example attempts to catch the SIGTERM signal, ignores the SIGINT signal, and
accepts the default action of the SIGSEGV signal. The pause API suspends the calling process
until it is interrupted by a signal and the corresponding signal handler does a return:
The SIG_IGN specifies a signal is to be ignored, which means that if the signal is generated to
the process, it will be discarded without any interruption of the process.
SIGNAL MASK:
• A process initially inherits the parent’s signal mask when it is created, but any pending
signals for the parent process are not passed on.
• A process may query or set its signal mask via the sigprocmask API:
#include <signal.h> int sigprocmask(int cmd, const sigset_t *new_mask,
sigset_t *old_mask);
Returns: 0 if OK, 1 on error
• The new_mask argument defines a set of signals to be set or reset in a calling process
signal mask, and the cmd argument specifies how the new_mask value is to be used by
the API. The possible values of cmd and the corresponding use of the new_mask value
are:
• the actual argument to new_mask argument is a NULL pointer, the cmd argument will
be ignored, and the current process signal mask will not be altered.
• If the actual argument to old_mask is a NULL pointer, no previous signal mask will be
returned.