Title: System Calls: processes
1System Calls processes
2Running another program
- int system (const char string)
- Runs the command passed to it, and waits for it
to complete. - Invoke program using shell
- include ltstdlib.hgt
- include ltstdio.hgt
- int main()
-
- printf (running ps with system()\n)
- system(ps ax)
- printf (done\n)
- exit(0)
3exec family of system call
- Replace current process with a new program
- include ltunistd.hgt
- extern char environ
- int execl(const char path, const char arg, ...,
(char )0) - int execlp(const char file, const char arg,
..., (char )0) - int execle(const char path, const char arg,
..., (char )0, - char const envp)
- int execv(const char path, char const argv)
- int execvp(const char file, char const argv)
- int execve(const char filename, char const
argv, - char const envp)
4Example of usage
- include ltunistd.hgt
- include ltstdio.hgt
- include ltstdlib.hgt
- Int main()
-
- printf (Running ps with execlp\n)
- execlp(ps,ps,ax,0)
- printf (Done.\n)
- exit(0)
execlp search for program called ps (searching
for program using PATH), execute program in
place of calling process, with ps as first
argument, ax as second argument, i.e., ps
ax. When ps finishes, the process ends.
Not executed, unless there is an error, e.g.
program cannot be found or not executable.
5About exec family
- Search for program
- i.e., based on the paths specified in PATH
environment variable - Does not support shell meta characters, such as
, gt, lt, quotes - system() calls support all of these, as it
invokes shell to run the given command - sprintf (commandline,ls wc)
- execlp(/bin/sh,sh,-c,commandline, (char
)0)
6Code Example
- Usage waitfile filename command
- Periodically checks the file named. If the file
is unchanged since last time, the command is
executed. If no command is specified, the file is
copied to the standard output. - include ltstdio.hgt
- include ltsys/types.hgt
- include ltsys/stat.hgt
- char progname
- main(int argc, char argv)
-
- int fd
- struct stat stbuf
- time_t old_time 0
7- progname argv0
- if (argc lt 2)
- error("Usage s filename cmd",
progname) - if ((fd open(argv1, 0)) -1)
- error("can't open s", argv1)
- fstat(fd, stbuf)
- while (stbuf.st_mtime ! old_time)
- old_time stbuf.st_mtime
- sleep(60)
- fstat(fd, stbuf)
-
8- if (argc 2) / copy file /
- execlp("cat", "cat", argv1,
(char ) 0) - error("can't execute cat s",
argv1) - else / run
process / - execvp(argv2, argv2)
- error("can't execute s",
argv2) -
- exit(0)
-
9Control of processes
- exec family of library functions overlay the new
program on the current one running by the process - How to regain control after running a program?
- fork() to generate a child process to run the
program - In parent process, wait() child to terminate
10fork()
- include ltsys/types.hgt
- include ltunistd.hgt
- pid_t fork(void)
- creates a new process by duplicating calling
process. New process, i.e., the child, is an
exact duplicate of calling process, i.e.,
the parent, except - Child process has a new PID, its parent process
ID is the PID of current process - Timers, asynchronous I/O,
- For calling process, return value of fork is the
child PID for child process, return value is 0.
11Example of using fork()
-
- int main() pid_t pid char message int n
- printf("fork program starting\n") pid
fork() switch(pid) case -1 exit(1)
case 0 message "this is the child
process" n 3 break
default message "this is the
parent process" n 6 break
 for( n gt 0 n--) puts(message)
sleep(1) Â exit(0)
zhang_at_storm Demo ./a.out fork program
startingnthis is the child process fork program
startingnthis is the parent process this is the
child process this is the parent process this is
the child process this is the parent process this
is the parent process this is the parent
process this is the parent process
12Difference between parent child
- Different pids
- In parent, fork( ) returns pid of the child
process if a child process is created - In child, fork( ) always returns 0
- separate copies of all data including variables
with their current values and stack - separate program counter (PC) indicating where to
execute next - originally both have same value but they are
thereafter separate - after fork, two processes do not share variables
13Zombie/defunct Process
- When child process terminates, its association
with its parent survives until parent terminates
normally or calls wait() - Child process remain in system, as its exit code
needs to be stored in case parent calls wait()
later - After a parent process fork()s a child process,
it must wait() (or waitpid()) for that child
process to exit. This allows all remnants of the
child to vanish.
14wait() system call
- include ltsys/types.hgt
- include ltsys/wait.hgt
- pid_t wait(int status)
- pid_t waitpid(pid_t pid, int status, int
options) - int waitid(idtype_t idtype, id_t id, siginfo_t
infop, int options) - wait for state changes in a child of calling
process, and obtain info. about the child, for
example, child terminated child was stopped by
a signal or child was resumed by a signal.
15Checking exiting status of child
- pid_t wait(int status)
- If status is not NULL, wait() and waitpid() store
status info. - One can inspect the status with following macros
(which take - an integer itself as an argument)
- WIFEXITED(status)
- returns true if the child
terminated normally. - WEXITSTATUS(status)
- returns exit status of the child.
- WIFSIGNALED(status)
- returns true if child process was
terminated by a signal. - .
16Synchronous and asynchronous process execution
- In some cases, e.g. if child process is a server
or "daemon", parent process would not wait for
child to finish. - In other cases, e.g. running an interactive
command, parent process normally wait for child
to exit before continuing. - If you run a command with an ampersand as it's
last argument, e.g. sleep 60 , parent shell
doesn't wait for the child process to finish.
17forkbomb
- int main(int argc, char argv)
-
- pid_t childpid
- int count
- if (argc ! 2)
-
- cerr ltlt "Usage forkbomb ltintgt"
ltlt endl - exit(1)
-
- count atoi(argv1)
-
18forkbomb(2)
- if (count gt 4)
-
- cerr ltlt "Integer parameter has
been reduced to 4" ltlt endl - count 4
-
- for (int i 1 i lt count i)
- childpid fork()
-
- cout ltlt "---- Terminating process " ltlt
getpid() - ltlt endl
- return 0
-
19File descriptors
- Child process inherit all files descriptors of
parent process - Including 0, 1, 2
- If parent process redirects standard input or
output, so does the child process - Sometimes one wants to reconnect standard
input/output to the terminal, /dev/tty
20Redirect standard input/output
- int fd
- fdopen(file,0)
- close(0)
- dup(fd)
- close (fd)
- scanf ("s",buf)
- printf ("Read s\n",buf)
dup(fd) duplicates fd on the lowest numbered
unallocated file descriptor, returning a new
descriptor referring to same file
21Another way to redirect stdin/stdout
- include ltstdio.hgt
- include ltstdlib.hgt
- include ltunistd.hgt
- int main(int argc, char argv)
- char filename
- if (argc!2)
- fprintf (stderr,usage useupper file\n)
- exit(1)
-
- filenameargv1
22freopen
- If (!freopen(filename,r,stdin))
- fprintf(stderr,could not redirect stdin from
file s\n,filename) - exit(2)
-
- execl(./upper,upper,0)
- perror(could not exec ./upper)
- exit(3)
freopen(const char path, const char mode, FILE
stream) opens file specified by path, associates
the stream pointed to by stream with it. original
stream pointed to by stream is closed.
23Reconnect standard input/output to terminal
- system(char s) / run command line s /
-
- int status, pid, w, tty
- int (istat)(), (qstat)()
- extern char progname
- fflush(stdout)
- tty open("/dev/tty", O_RDWR)
- if (tty -1)
- fprintf(stderr, "s can't open
/dev/tty\n", progname) - return -1
-
24Reconnect standard input/output to terminal
- if ((pid fork()) 0)
- close(0) dup(tty)
- close(1) dup(tty)
- close(2) dup(tty)
- close(tty)
- execlp("sh", "sh", "-c", s, (char
) 0) - exit(127)
-
25Reconnect standard input/output to terminal
- close(tty)
- istat signal(SIGINT, SIG_IGN)
- qstat signal(SIGQUIT, SIG_IGN)
- while ((w wait(status)) ! pid w !
-1) -
- if (w -1)
- status -1
- signal(SIGINT, istat)
- signal(SIGQUIT, qstat)
- return status
-
26Exercise how would you implement time ?
- time options command arguments...
- Runs specified command, writes timing statistics
about this program run to standard error - elapsed real time between invocation and
termination, - user CPU time (sum of tms_utime and tms_cutime
values in a struct tms as returned by times(2)) - system CPU time (sum of tms_stime and
tms_cstime values in a struct tms as returned by
times(2)). - zhang_at_storm time who wc -l
- 7
- real 0m0.002s
- user 0m0.000s
- sys 0m0.002s
27Time related functions
- include ltsys/time.hgt
- int gettimeofday(struct timeval tv,
struct timezone tz) - get the time as well as a timezone. tv,
pointer to timeval gives number of seconds and
microseconds since the Epoch (000000 UTC,
January 1,1970) - struct timeval
- time_t tv_sec / seconds
/ - suseconds_t tv_usec /
microseconds / -
-
28Measure Elapsed Time
- struct timeval tv1,tv2
- struct timezone tz
- if (gettimeofday (tv1,tz)!0)
- printf ("failed to
gettimeofday\n") - return
-
- // do the work
- if (gettimeofday (tv2,tz)!0)
- printf ("failed to
gettimeofday\n") - return
-
- printf ("elapsed time is d us\n",
- (tv2.tv_sec-tv1.tv_sec)(tv2.tv_usec-tv1
.tv_usec)1000000)
29Useful system calls
- times() get process times
- include ltsys/times.hgt
- clock_t times(struct tms buf)
- stores current process times in struct tms that
buf points to. - struct tms
- clock_t tms_utime / user time
/ - clock_t tms_stime / system
time / - clock_t tms_cutime / user time
of children / - clock_t tms_cstime / system
time of children / -
-
30Exercise Simple Shell
- How to implement output redirection specified
with gtgt, i.e., append standard output to a file ? - myshell
- zhang ls gtgt tmp.txt
- Create a child process to run the command ls
- In child process, redirect standard output to
given file and set file position to end of file - In parent, wait for child process to terminate
31Append to file
- include ltstdio.hgt
- int fseek(FILE stream, long offset, int
whence) - Set file position indicator to given position
- offset is given relative to whence
- whence SEEK_SET, SEEK_CUR, or SEEK_END
- sets file position to the end of file
- feek(file,0L, SEEK_END)
32Next class
- Signals
- Pipes
- Overview on multi-threaded programming