Unit 6
-
Upload
siddr -
Category
Technology
-
view
745 -
download
0
Transcript of Unit 6
UNIT -6 SIGNALS AND DAEMON PROCESSES
Prepared By,
Darshan.K.R
Lecturer,SJBIT
Kengeri,Bangalore
Stack
Heap
Uninitialized data (bss)
Initialized data
Text
Command line args and environment variables
Initialized to zero by exec
Read from program by exec
Variable Standards- POSIX.1
Standards- XPG3
Implementation: SVR4
Implementation-4.3+BSD
Description
HOME Home directory
LANG Name of locale
LC_ALL Name of locale
LC_COLLATE Name of locale for collation
LC_CTYPE Name of locale for character classification
LC_MONETARY Name of locale for monetary editing
LC_NUMERIC Name of locale for numeric editing
LC_TIME Name of locale for date/time formatting
LOGNAME Login name
NLSPATH Sequence of templates for message catalogs
PATH List of path prefixes to search for executable files
TERM Terminal type
TZ Time zone information
Function Std- ANSI C Std: POSIX.1 Std: XPG3 Impl: SVR4 Impl: 4.3BSD
getenv
putenv (maybe)
setenv
unsetenv
clearenv (maybe)
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit (int resource, struct rlimit *rlptr);
int setrlimit (int resource, const struct rlimit *rlptr);
struct rlimit{
rlim_t rlim_cur; /*soft limit: current limit */
rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */
};
getrlimit and setrlimit functions
Rules
1. A soft limit can be changed by any process to a value less than or equal to its hard limit
2. Any process can lower its hard limit to a value greater than or equal to its soft limit. This lowering of the hard limit is irreversible for normal users
3. Only a superuser process can raise a hard limit.
Infinite limit is RLIM_INFINTY
RLIMIT_CORE The maximum size in bytes of a core file
RLIMIT_CPU The maximum amount of CPU time in seconds (SIGXCPU)
RLIMIT_DATA The maximum size in bytes of the data segment
RLIMIT_FSIZE The maximum size in bytes of a file that may be created (SIGFSZ)
RLIMIT_MEMLOCK Locked-in memory address space
RLIMIT_NOFILE The maximum number of open files per process
RLIMIT_NPROC The maximum number of child processes per user id
RLIMIT_OFILE Same as RLIMIT_NOFILE
RLIMIT_RSS Maximum resident set size in bytes
RLIMIT_STACK The maximum size in bytes of the stack
RLIMIT_VMEM The maximum size in bytes of the mapped address space
#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#include "ourhdr.h"#define doit(name) prlimits(#name, name) static void prlimits(char *, int);
int main (void) {
doit(RLIMIT_CORE); doit(RLIMIT_CPU); doit(RLIMIT_DATA); doit(RLIMIT_FSIZE);
#ifdef RLIMIT MEMLOCKdoit(RLIMIT_MEMLOCK);
#endif#ifdef RLIMIT_NOFILE /* SVR4 name */
doit(RLIMIT_NOFILE);#endif#ifdef RLIMIT_OFILE /* 4.3+BSD name */
doit(RLIMIT_OFILE);#endif#ifdef RLIMIT_NPROC
doit(RLIMIT_NPROC);#endif#ifdef RLIMIT_RSS
doit(RLIMIT RSS);#endif
doit(RLIMIT_STACK);#ifdef RLIMIT_VMEM
doit(RLIMIT_VMEM);#endifexit(0);
}
static voidpr_limits (char *name, int resource){
struct rlimit limit ;
if (getrlimit(resource, &limit) < 0)err_sys("getrlimit error for %S", name);
printf ("%-14s ", name); if (limit.rlim_cur == RLIM_INFINITY)
printf(" (infinite) ");else
printf("%10ld ", limit.rlim_cur);if (limit.rlim_max == RLIM_INFINITY)
printf(" (infinite)\n");else
printf("%10ld\n", limit.rlim_max);}
Output – SVR4
RLIMIT_CORE 1048576 1048576
RLIMIT_CPU (infinite) (infinite)
RLIMIT_DATA 16777216 16777216
RLIMIT_FSIZE 2097152 2097152
RLIMIT_NOFILE 64 1024
RLIMIT_STACK 16777216 16777216
RLIMIT_VMEM 16777216 16777216
UNIX Kernel Support for Processes
• UNIX System V
• UNIX process consists of
1. Text segment
2. Data segment
3. Stack segment
• Segment is an area of memory that is managed by the system as a unit.
• Process Table
• Keeps track of all active processes.
1. System Processes
2. User Processes
• Contains pointers to segments and the U-area of a process.
• U-area is an extension of a Process table entry and contains other process-specific data
1. File descriptor table
2. current root
3. working directory inode numbers
4. Set of system imposed process resource limits
File descriptor table current directory root
….
Text
Data
Stack
Process U-area
A Process
Process Table
Per-process region table
A UNIX process data structureKernel region Table
UNIX Kernel Support for Processes
• Very first process – 0 – created by the system boot code.
• All other processes – created via the fork system call.
• When a process is created by fork, it contains duplicated copies of the text, data and stack segments of the parent.
• It also has a File descriptor table such that both share the same file pointer.
Process Table
Data Structure of Parent and child after forkKernel region Table
Text
Data
Stack
Stack
Data
File desc table
File desc table
File Table
Parent
Child
UNIX Kernel Support for Processes
Attributes inherited from its parent or set by the kernel.
1. Real User Identification ID (rUID)
2. Real group Identification number (rGID)
3. An effective user identification number (eUID)
4. An effective group Identification number (eGID)
5. Saved set-UID and set-GID
6. Process group identification number.
7. Supplementary group identification numbers
8. Current directory
9. Root directory
10. Signal Handling
11. Signal mask
12. Umask
13. Nice value
14. Controlling terminal
UNIX Kernel Support for Processes
Attributes different between the parent and the child process
• Process Identification number (PID)
• Parent process identification number (PPID)
• Pending signals
• Alarm clock time
• File locks
• wait, waitpid sytem calls – suspend till child finishes
• Signal or sigaction function to detect or ignore the child process termination.
• _exit system call
• exec system call – like changing jobs.
• fork and exec are used to spawn a sub process to execute a different program.
• Multiple processes can execute multiple programs concurrently
• Child executes in its own address space
UNIX Kernel Support for Processes
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int * statloc)
pid_t waitpid(pid_t pid, int * statloc, int options)
• Child process - Zombie process
• Parent process – init process
• Waitpid:
• If pid == -1
• If pid > 0
• If pid == 0
• If pid < -1
int main (void){
pid_t pid;if ( (pid = fork() <0)
err_sys(“fork error");else if (pid == 0) /* first child */{
if ( (pid = fork () < 0)err_sys("fork error");
else if (pid > 0)exit (0); /* parent from second fork == first child */
/* We're the second child; our parent becomes init as soon as our real parent calls exit () in the statement above. Here's where we'd continue executing, knowing thatwhen we're done, init will reap our status. */
sleep(2);printf (" second child, parent pid = %d\n It, getppid () ) ;exit(0);
}if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
err_sys("waitpid error");
/* We're the parent (the original process); we continue executing, knowing that we're not the parent of the second child. */exit (0) ;
}
Wait3 and Wait4 functions
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage);
Function Pid Options Rusage POSIX.1 SVR4 4.3+BSD
wait
waitpid
wait3
wait 4
Race Conditions
• When multiple processes are trying to do something with shared data and final outcome depends on the order in which the processes are run.
• If a parent wants to wait for the child to terminate – call wait function
• If a child wants to wait for the parent to terminate –
while (getppid() != 1)
sleep(1)
#include "ourhdr.h"
TELL_WAIT () ; /* set things up for TELL xxx & WAIT xxx */
if ( (pid = fork () < 0)
err_sys("fork error");
else if (pid == 0) { /* child */
/* child does whatever is necessary... */
TELL_PARENT(getppid()); /* tell parent we're done */
WAIT_PARENT () ; /* and wait for parent */
/* and the child continues on its way... */
exit(0);
}
/* parent does whatever is necessary... */
TELL_CHILD (pid) ; /* tell child we're done */
WAIT_CHILD () ; /* and wait for child */
/* and the parent continues on its way... */
exit (0) ;
#include <sys/types. h> #include "ourhdr.h"static void charatatime (char *);
int main (void) {pid_t pid;if ( (pid = fork () < 0)
err_sys ("fork error");else if (pid == 0) {
charatatime ("output from child\n");) else {
charatatime(."output from parent\n"); ) exit(0) ;
}static void charatatime (char *str) {
char *ptr;int c;setbuf (stdout, NULL); /* set unbuffred */for (ptr = str; c = *ptr++; )
putc(c, stdout);}
Output $ a.out
output from child
output from parent
$ a.out
oouuttppuutt ffrroomm cphairledn
t
$ a.out
oouuttppuutt ffrroomm pcahrielndt
$ a.out
ooutput from parent
utput from child
int main (void){
pid_t pid;+ TELL_WAIT () ;+ if ( (pid = fork() < 0)
err_sys("fork error");else if (pid == 0) {
+ WAIT_PARENT(); /* parent goes first */charatatime("output from child\n");
} else {charatatime("output from parent\n");
+ TELL_CHILD(pid);}exit (0) ;
}static void charatatime(char *str) {
char *ptr;int c;
setbuf(stdout, NULL); /* set unbuffered */for (ptr = str; c = *ptr++;)
putc(c, stdout);}
#include <unistd. h>
int execl (const char *pathname, const char *arg0, ... / * (char *) 0 * / );
int execv (const char *pathname, char *const argv[ ] ) ;
int execle (const char *pathname, const char *arg0, .../* (char *) 0, char *const envp[ ] */ );
int execve (const char *pathname, char *const argv[ ], char *const envp[ ] ) ;
int execlp(const char *filename, const char *argO, ... /* (char *) 0 */ );
int execvp (const char *filename, char *const argv [ ] ) ;
All six return: -1 on error, no return on success
exec Functions• Process is completely replaced.
• Process ID does not change
• Replaces the current program with a new program from the disk.
Differences
Function pathname filename arg list
argv[ ] environ emp[ ]
execl
execlp
execle
execv
execvp
execve
(Letter in name) P L V e
Limit on the total size of the argument list : ARG_MAX
4096 on a POSIX.1 system.
Eg: grep _POSIX_SOURCE /usr/include/*/*.h
Inherits
• Process ID and parent process ID
• real user Id and real group Id
• supplementary group Ids
• process group ID
• Session ID
• controlling terminal
• time left until alarm clock.
• current working directory
• root directory
• file mode creation mask
• file locks
• process signal mask.
• pending signals
• resource limits
• tms_utime, tms_stime, tms_cutime, tms_ustime
Relationship
execlp execl execle
execvp execv execve
(system call)
build argv
try each
PATH prefix
use
environ
build argv build argv
char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL };int main (void) {
pid_t pid;if ( (pid = fork () < 0)
err_sys (" fork error");else if (pid == 0){
/* specify pathname, specify environment */if (execle (" /home/stevens/bin/echoall",
"echoall", "myarg1", "MY ARG2", (char *) 0,env_init < 0)
err_sys("execle error");}if (waitpid(pid, NULL, 0) < 0)
err_sys ("wait error");if ( (pid = fork () < 0)
err_sys ("fork error");else if (pid == 0) {
/* specify filename, inherit environment */if (execlp("echoall“,"echoall", "only 1 arg", (char *) 0) < 0)
err_sys("execlp error");}exit (0) ;
}
#include "ourhdr.h"
int main(int argc, char *argv[]) {
int i;
char **ptr; extern char **environ;
for (i = 0; i < argc; i++) /* echo all command-line args */
printf("argv[%d]: %s\n", i, argv[i]);
for (ptr = environ; *ptr != 0; ptr++)
printf("%s\n", *ptr);
/* and all env strings *f
exit (0) ;
}
$ a.out
argv[0]: echoall
argv[l]: myarg1
argv[2]: MY ARG2
USER=unknown
PATH=/tmp
$ argv[0]: echoall
argv[1]: only 1 arg
USER=stevens
HOME=/home/stevens
LOGNAME=stevens
31 more lines…….
EDITOR=/usr/ucb/vi
int system(const char *cmdstring) { pid_t pid; int status;
if (cmdstring == NULL) return(1); /* always a command processor with UNIX */
if ((pid = fork()) < 0) { status = -1; /* probably out of processes */ } else if (pid == 0) { /* child */ execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); _exit(127); /* execl error */ } else { /* parent */ while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { status = -1; /* error other than EINTR from waitpid() */ break; } } }
return(status);}
Exit Code Number
Meaning Example Comments
1 catchall for general errors let "var1 = 1/0"
miscellaneous errors, such as "divide by zero"
2 misuse of shell builtins, according to Bash documentation
Seldom seen, usually defaults to exit code 1
126 command invoked cannot execute
permission problem or command is not an executable
127 "command not found" possible problem with $PATH or a typo
128 invalid argument to exit exit 3.14159
exit takes only integer args in the range 0 - 255
128+n fatal error signal "n" kill -9 $PPIDof script
$? returns 137 (128 + 9)
130 script terminated by Control-C Control-C is fatal error signal 2, (130 = 128 + 2, see above)
255 exit status out of range exit -1 exit takes only integer args in the range 0 - 255
Process Times
#include <sys/times.h>clock_t times (struct tms *buf);
Struct tms{clock_t tms_utime; /*user CPU time */clock_t tms_stimel; /*system CPU time */clock_t tms_cutime ; /*user CPU time, terminated children */clock_t tms_cstime; /* system CPU time, terminated children */
};
Main program
#include <sys/times.h> #include "ourhdr.h"
static void pr_times(clock_t, struct tms *, struct tms *); static void do_cmd(char *);
int main(int argc, char *argv[]){
int i;for (i = 1; i < argc; i++)
do_cmd(argv[i]); /* once for each command-line arg */exit(0);
}
Function to execute the command static void do_cmd(char *cmd) /* execute and time the "cmd" */{
struct tms tmsstart, tmsend;clock_t start, end; int status;
fprintf(stderr, "\ncommand: %s\n", cmd);if ( (start = times (&tmsstart)) == -1) /* starting values */
err_sys("times error");
if ( (status = system(cmd)) < 0) /*execute command */err_sys ("systemO error");
if ( (end = times(&tmsend)) == -1) /* ending values */err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
pr_exit(status);}
Function to calculate and print the timestatic void pr_times (clock_t real, struct tms *tmsstart, struct tms *tmsend) {
static long clktck = 0;if (clktck == 0) /* fetch clock ticks per second first time ,/if ( (clktck = sysconf(_SC_CLK_TCK)) < 0)
err_sys("sysconf error"); fprintf(stderr, " real: %7.2f\n", real/ (double) clktck); fprintf(stderr, " user: %7.2f\n",
(tmsend->tms_utime - tmsstart->tms_utime)/(double) clktck);fprintf(stderr,"sys: %7.2f\n",
(tmsend->tms_stime - tmsstart->tms_stime)/(double) clktck);fprintf(stderr, " child user: %7.2f\n",
(tmsend->tms_cutime - tmsstart->tms_cutime)/(double) clktck);fprintf(stderr, " child sys: %7.2f\n",
(tmsend->tms_cstime - tmsstart->tms_cstime) /(double) clktck);}
Output
$ a.out "sleep 5" "date"command: sleep 5
real: 5.25user: O. 00sys: 0.00child user: 0.02child sys: 0.13
normal termination, exit status = a
command: dateSun Aug 18 09:25:38 MST 1991real: 0.27user: 0.00sys: O. 00child user: 0.05child sys: 0.10
normal termination, exit status = a
Interpreter files
Files that begin with#! pathname [optional-argument]
Eg: #! /bin/sh
The actual file that gets execed is the file specified by the pathname.
Pathname is usually absolute pathname.
Some systems have a limit of 32 characters for the first line.
Differentiate between interpreter file: a text file that begins with a #!
interpreter: specified by pathname
#include <sys/types.h>#include <sys/wait.h>#include "ourhdr.h"
int main (void){
pid_t pid;if ( (pid = fork 0 ) < 0)
err_sys("fork error");else if (pid == 0) { /* child */
if (execl("/home/stevens/bin/testinterp","testinterp", "myarg1", "MY ARG2",(char *) 0) < 0)
err_sys("execl error");if (waitpid(pid, NULL, 0) < 0)
err_sys("waitpid error");exit(0);
}
$ cat /home/stevens/bin/testinterp#!/home/stevens/bin/echoarg foo
$ a.outargv[0] : /home/stevens/bin/echoargargv[1] : fooargv[2] : /home/stevens/bin/testinterpargv[3] : myarglargv[4] : MY ARG2
Example
awk –f myfile
Interpreter file, awkexample:#! /bin/awk –fBEGIN (
for (i = 0; i < ARGC; i++)printf "ARGV[%d] = %s\n", i, ARGV[i]exit
}
$ awkexample file1 FILENAME2 f3ARGV[0] = /bin/awk ARGV[1] = file1ARGV[2] = FILENAME2 ARGV[3] = f3
When /bin/awk is executed, its command-line arguments are/bin/awk -f /usr/local/bin/awkexample file1 FILENAME2 f3
Are interpreter files required?1. They hide the fact that certain programs are scripts in some other language.
Eg: awkexample optional-argumentsInstead of
awk –f awkexample optional-arguments
2. They provide an efficiency gain.awk ‘BEGIN {
for (i = 0; i < ARGC; i++)printf "ARGV[%d] = %s\n", i, ARGV[i]exit
}’ $*
3. They let us write shell scripts using shells other than /bin/sh.Eg: #! /bin/csh
Process Accounting
When enabled, kernel writes an accounting record each time a process terminates.
32 bytes of binary data.
typedef u short comp_t; /* 3-bit base 8 exponent; 13-bit fraction */
struct acct{
char ac_flag; /* flag */
char ac_stat; /* termination status (signal & core flag only) */
/*(not provided by BSD systems) */
uid t ac_uid; /* real user ID */
gid_t ac_gid; /* real group 1D */
dev t ac_tty; /* controlling terminal */
time t ac_btime; /* starting calendar time */
comp_t ac_utime; /* user CPU time (clock ticks) */
comp_t ac_stime; /* system CPU time (clock ticks) */
comp_t ac_etime; /* elapsed time (clock ti.cks) */
comp_t ac_mem; /* average memory usage */
comp_t ac_io; /* bytes transferred (by read and write) */
comp_t ac_rw; /* blocks read or written */
char ac_comm[8];/* command name: [8] for SVR4, [10] for 4.3+BSQ */
};
Accounting Record
ac_Flag
AFORK – process is the result of fork, but never called exec
ASU – Process used super user privileges ACOMPAT – process used compatibility
mode ACORE – process dumped core AXSIG – process was killed by a signal
int main (void){
pid_t pid;if ( (pid = fork ()) < 0)
err_sys("fork error");else if (pid != 0) { /* parent */
sleep(2);exit(2); /* terminate with exit status 2 */
}/* first. child */
if ( (pid = fork()) < 0)err_sys("fork error");
else if (pid != 0) {
sleep(4);abort (); /* terminate with core dump */
}/* second child */
if ( (pid = fork()) < 0)err_sys("fork error");
else if (pid != 0) {execl (" /usr/bin/dd", "dd", "if=/boot", "of=/dev/null",NULL)exit(7); /* shouldn't get here */
/* third child */if ( (pid = fork ()) < 0)
err_sys("fork error");else if (pid != 0) {
sleep(8);exit(0); /* normal exit */
}/* fourth child */
sleep(6);kill(getpid(), SIGKILL); /* terminate with signal, no core dump */exit(6); /* shouldn't get here */
}
Procedure
1. Become a superuser and enable accounting, with the accton command.
2. Run the program
3. Become a superuser and turn accounting off.
4. Run the program to print the selected fields from the accounting file.
Output
accton e = 7, chars = 64, stat = 0: Sdd e = 37, chars = 221888, stat = 0: second
childa.out e = 128, chars = 0, stat = 0: parenta.out e = 274, chars = 0, stat = 134: F D X first childa.out e = 360, chars = 0, stat = 9: F X fourth
childa.out e = 484, chars = 0, stat = 0: F third child
Process Relationships
Terminal Logins Network Logins Process Groups Sessions Controlling Terminal tcgetpgrp and tcsetpgrp functions
Terminal Login
init
init
getty
Login
Terminal device driver
User at a terminal
fork
exec
exec
fd 0, 1, 2
RS-232 connection
Reads /etc/ttys;
Forks once per terminal
Create empty environment
Each child execs getty
Reads user name
Initial environment set
Validate password
Changes to home directory
Permissions set
• execle(“usr/bin/login”, “login, “-p”. username, (char *) 0, envp)
• execl (“/bin/sh”, “-sh”, (char *) 0);
Network Login
init
inetd
inetd
telnetd
Login shell
Pseudo-terminal device driver
User at a terminal
TCP connection request
From TELNET client
fork
exec
fd 0, 1, 2
Executes /etc/rc
When connection request arrives
Network connection through telnetd server and telnet client
telnet hostname
Process Groups
Collection of one or more processes Unique process group ID.
#include <sys/types.h>#include <unistd.h>pid_t getpgrp(void);
Process group leader has process group ID equal to process ID. Process group lifetime.
#include <sys/types.h>#include <unistd.h>Int setpgid(pid_t pid, pid_t pgid);
A process can set only the pgid of itself or its children. If pid is 0, Process Id of caller is used. If pgid is 0, pid is the pgid.
Sessions
Login shell proc1 proc2 proc3 proc4
proc5Process group Process group
Process group
session
proc1 | proc2 &
Proc3 | proc4 | proc5
• Session is a collection of one or more process groups
Sessions
• Session is a collection of one or more process groups
#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
• The process becomes the session leader of this session. The process is the only process in this new session.
• The process becomes the process group leader of a new process group. The new process group ID is the process ID of the calling process.
• The process has no controlling terminal. If the process had a controlling terminal before calling setsid, that association is broken.
Controlling Terminal
A session can have a single controlling terminal.
The session leader that establishes the connection to the controlling terminal is called the controlling process.
Process groups can be background process groups and foreground process groups.
If a session has a controlling terminal, then it has a single foreground process group, and all other process groups in the session are background process groups.
Terminal’s interrupt signal or quit signal are sent to foreground process group.
Modem disconnect is detected by the terminal interface, the hang-up signal is sent to the controlling process.
Controlling Terminal
Login shell proc1 proc2 proc3 proc4
proc5Background Process group session leader = controlling prcess
Background Process group
Foreground Process group
Controlling terminal
Terminal input and terminal generated signalsModem disconnect
(hangup signal)
tcgetpgrp and tcsetpgrp functions
#include <sys/types.h>
#include <unistd.h>
pid_t tcgetpgrp(int filedes);
int tcsetpgrp(int filedes, pid_t pgrpid);