Chapter 13 Systems Programming. Systems Programming. Error Handling. Error Handling. Example: File I/O. Example: File I/O

Similar documents
UNIX System Calls. Sys Calls versus Library Func

Hyo-bong Son Computer Systems Laboratory Sungkyunkwan University

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

CSC 271 Software I: Utilities and Internals

I/O OPERATIONS. UNIX Programming 2014 Fall by Euiseong Seo

I/O OPERATIONS. UNIX Programming 2014 Fall by Euiseong Seo

CSE 333 SECTION 3. POSIX I/O Functions

Lecture 21 Systems Programming in C

System Calls and I/O Appendix. Copyright : University of Illinois CS 241 Staff 1

System Calls. Library Functions Vs. System Calls. Library Functions Vs. System Calls

Chp1 Introduction. Introduction. Objective. Logging In. Shell. Briefly describe services provided by various versions of the UNIX operating system.

Operating System Labs. Yuanbin Wu

Preview. System Call. System Call. System Call. System Call. Library Functions 9/20/2018. System Call

CS 201. Files and I/O. Gerson Robboy Portland State University

CSE 333 SECTION 3. POSIX I/O Functions

CS240: Programming in C

Lecture files in /home/hwang/cs375/lecture05 on csserver.

Interacting with Unix

CSC209F Midterm (L0101) Fall 1999 University of Toronto Department of Computer Science

Operating Systems. Processes

Operating System Labs. Yuanbin Wu

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

OPERATING SYSTEMS: Lesson 2: Operating System Services

Outline. OS Interface to Devices. System Input/Output. CSCI 4061 Introduction to Operating Systems. System I/O and Files. Instructor: Abhishek Chandra

Lecture 3. Introduction to Unix Systems Programming: Unix File I/O System Calls

File I/0. Advanced Programming in the UNIX Environment

Systems Programming. COSC Software Tools. Systems Programming. High-Level vs. Low-Level. High-Level vs. Low-Level.

Examination C++ Programming

Last Week: ! Efficiency read/write. ! The File. ! File pointer. ! File control/access. This Week: ! How to program with directories

CS , Spring Sample Exam 3

UNIX System Programming

Important Dates. October 27 th Homework 2 Due. October 29 th Midterm

CSC209H Lecture 6. Dan Zingaro. February 11, 2015

PRACTICAL NO : 1. AIM: To study various file management system calls in UNIX.

Parents and Children

Process Creation in UNIX

CS240: Programming in C

Operating Systems. Lecture 06. System Calls (Exec, Open, Read, Write) Inter-process Communication in Unix/Linux (PIPE), Use of PIPE on command line

CMSC 216 Introduction to Computer Systems Lecture 17 Process Control and System-Level I/O

Operating System Labs. Yuanbin Wu

All the scoring jobs will be done by script

Contents. NOTICE & Programming Assignment #1. QnA about last exercise. File IO exercise

which maintain a name to inode mapping which is convenient for people to use. All le objects are

Operating Systems CMPSCI 377 Spring Mark Corner University of Massachusetts Amherst

All the scoring jobs will be done by script

Advanced Unix/Linux System Program. Instructor: William W.Y. Hsu

Unix File and I/O. Outline. Storing Information. File Systems. (USP Chapters 4 and 5) Instructor: Dr. Tongping Liu

System Programming. Process Control II

System Programming. Process Control III

System- Level I/O. Andrew Case. Slides adapted from Jinyang Li, Randy Bryant and Dave O Hallaron

Operating systems. Lecture 7

Recitation 8: Tshlab + VM

File I/O. Dong-kun Shin Embedded Software Laboratory Sungkyunkwan University Embedded Software Lab.

Windows architecture. user. mode. Env. subsystems. Executive. Device drivers Kernel. kernel. mode HAL. Hardware. Process B. Process C.

Overview. Unix System Programming. Outline. Directory Implementation. Directory Implementation. Directory Structure. Directories & Continuation

UNIVERSITY OF ENGINEERING AND TECHNOLOGY, TAXILA FACULTY OF TELECOMMUNICATION AND INFORMATION ENGINEERING SOFTWARE ENGINEERING DEPARTMENT

Lecture 8: Unix Pipes and Signals (Feb 10, 2005) Yap

CMPS 105 Systems Programming. Prof. Darrell Long E2.371

File I/O. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Lecture 23: System-Level I/O

structs as arguments

CS 33. Files Part 2. CS33 Intro to Computer Systems XXI 1 Copyright 2018 Thomas W. Doeppner. All rights reserved.

Files and Directories Filesystems from a user s perspective

CSC 1600 Unix Processes. Goals of This Lecture

CSCI-E28 Lecture 3 Outline. Directories, File Attributes, Bits, File Operations. Write our own versions of Unix programs

Lesson 2. process id = 1000 text data i = 5 pid = 1200

CSC209 Fall Karen Reid 1

File Systems. q Files and directories q Sharing and protection q File & directory implementation

Fall 2015 COMP Operating Systems. Lab #3

Process Management! Goals of this Lecture!

Unix-Linux 2. Unix is supposed to leave room in the process table for a superuser process that could be used to kill errant processes.

CS 471 Operating Systems. Yue Cheng. George Mason University Fall 2017

Fall 2017 :: CSE 306. File Systems Basics. Nima Honarmand

Naked C Lecture 6. File Operations and System Calls

Operating System Labs. Yuanbin Wu

CS240: Programming in C

CSci 4061 Introduction to Operating Systems. File Systems: Basics

CSI 402 Lecture 11 (Unix Discussion on Files continued) 11 1 / 19

File Descriptors and Piping

Contents. Programming Assignment 0 review & NOTICE. File IO & File IO exercise. What will be next project?

The course that gives CMU its Zip! I/O Nov 15, 2001

File and Directories. Advanced Programming in the UNIX Environment

Processes often need to communicate. CSCB09: Software Tools and Systems Programming. Solution: Pipes. Recall: I/O mechanisms in C

Chapter 4 - Files and Directories. Information about files and directories Management of files and directories

System Programming. Introduction to Unix

Files and Directories

System Calls and I/O. CS 241 January 27, Copyright : University of Illinois CS 241 Staff 1

Introduction. Files. 3. UNIX provides a simple and consistent interface to operating system services and to devices. Directories

Outline. File Systems. File System Structure. CSCI 4061 Introduction to Operating Systems

Preview. Process Control. What is process? Process identifier The fork() System Call File Sharing Race Condition. COSC350 System Software, Fall

Preview. Review. System Data Files (Password File) System Data Files (Password File) System Data Files (Password File)

CMPSC 311- Introduction to Systems Programming Module: Input/Output

Maria Hybinette, UGA. ! One easy way to communicate is to use files. ! File descriptors. 3 Maria Hybinette, UGA. ! Simple example: who sort

CPSC 341 OS & Networks. Processes. Dr. Yingwu Zhu

UNIX System Programming. Overview. 1. A UNIX System. 2. Processes (review) 2.1. Context. Pipes/FIFOs

Chapter 10. The UNIX System Interface

File I/O - Filesystems from a user s perspective

What Is Operating System? Operating Systems, System Calls, and Buffered I/O. Academic Computers in 1983 and Operating System

Input and Output System Calls

CSCI 4500/8506 Operating Systems Some UNIX System Calls, Library, and PThreads Functions

Transcription:

Chapter 13 Systems Programming Graham Glass and King Ables, UNIX for Programmers and Users, Third Edition, Pearson Prentice Hall, 2003. Original Notes by Raj Sunderraman Converted to presentation and updated by Michael Weeks Systems Programming UNIX System calls: C functions that provide access to the file system, processes, and error handling. System Calls grouped into 3 main categories: File Management (Fig. 13.1) Process Management (Fig. 13.2) Error Handling (Fig. 13.3) 2008-12-1 cs3320 1 2008-12-1 cs3320 2 Error Handling Most system calls are capable of failing in some way. Example: open a file may fail because file does not exist! System call returns a value of -1 when it fails. This value does not tell much about the cause of the failure. Error Handling global variable errno holds the numeric code of the last system-call error function perror() describes the system-call error void perror(char* str) /* standard C function in stdio.h */ Displays str followed by : followed by a description of the last system call error. Error 0 is displayed if no error See example showerrno.c 2008-12-1 cs3320 3 2008-12-1 cs3320 4 Example: File I/O #include <fcntl.h> #include <errno.h> main () { int fd; /* Open a non-existent file to cause an error */ fd = open ("nonexist.txt", O_RDONLY); if (fd == -1) /* fd == -1 =, an error occurred */ { printf ("errno = %d\n", errno); perror ("main"); /* Force a different error */ fd = open ("/", O_WRONLY); if (fd == -1) { printf ("errno = %d\n", errno); perror ("main"); Example: File I/O /* Execute a successful system call */ fd = open ("nonexist.txt", O_RDONLY O_CREAT, 0644); /* Display after successful call */ printf ("errno = %d\n", errno); /* will display previous error num (21) */ perror ("main"); errno = 0; /* Manually reset error variable */ perror ("main"); $ showerror errno = 21 main: Is a directory errno = 29 main: Illegal seek main: Success 2008-12-1 cs3320 5 2008-12-1 cs3320 6

File Management System Calls: open, fcntl, read, write, lseek, unlink, close Typical sequence: open Each read() and write() invokes a system call! Close All data are processed as a series of bytes (no format) 2008-12-1 cs3320 7 2008-12-1 cs3320 8 2008-12-1 cs3320 9 2008-12-1 cs3320 10 UNIX File 2008-12-1 cs3320 11 2008-12-1 cs3320 12

vmunix File I/O File A sequence of bytes Directory A file that includes info on how to find other files. dev console lp0 bin csh / lib libc.a usr include etc passwd File I/O Path name Absolute path name Start at the root / of the file system /user/john/filea Relative path name Start at the current directory which is an attribute of the process accessing the path name../dira/fileb Links Symbolic Link 4.3BSD A file containing the path name of another file can across file-system boundaries. Hard Link. or.. 2008-12-1 cs3320 13 2008-12-1 cs3320 14 File I/O File Descriptor Non-negative integer returned by open() or creat(): 0.. OPEN_MAX Virtually un-bounded for SVR4 & 4.3+BSD Each descriptor has its own private set of properties file pointer (stores offset within file; changes on read/write/lseek) flag indicating if the file descriptor should be closed or not when process execs flag indicating if output to file should be appended to end of file or not others Per-process base POSIX.1 0: STDIN_FILENO, 1: STDOUT_FILENO, 2: STDERR_FILENO <unistd.h> Convention employed by the Unix shells and applications 2008-12-1 cs3320 15 File I/O - File Manipulation Operations open, close, read, write, lseek, dup, fcntl, ioctl, trunc, rename, chmod, chown, mkdir, cd, opendir, readdir, closedir, etc. Read(4, ) sync data block data block i-node i-node i-node System In-core Open File v-node Tables of Table list Opened Files (per process) 2008-12-1 cs3320 16 Typical File I/O Sequence int fd; /* file descriptor 0: std. in, 1: std. out, 2: std error*/ fd = open(filename,...); if (fd == -1) /* deal with error */ fcntl(fd,...) /* set IO flags if needed */ read(fd,...) /* read from file */ write(fd,...) /* write to file */ lseek(fd,...) /* seek within file */ close(fd); /* close file */ 2008-12-1 cs3320 17 File I/O open #include <sys/types> #include <sys/stat.h> #include <fcntl.h> int open(const char*pathname, int mode, int permission); File/Path Name O_RDONLY, O_WRONLY, O_RDWR O_APPEND, O_TRUNC O_CREAT, O_EXCL O_NONBLOCK open(pathname, O_WRONLY O_CREAT O_TRUNC, mode) 2008-12-1 cs3320 18

What is the output of the following program? #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> int main() { int fd1, fd2; fd1 = open("foo1.txt", O_RDONLY, 0); close(fd1); fd2 = open("foo2.txt", O_RDONLY, 0); printf("fd2 = %d\n", fd2); exit(0); open always returns lowest unopened descriptor File I/O creat() and close() #include <sys/types> #include <sys/stat.h> #include <fcntl.h> int creat(const char*pathname, int mode); open(pathname, O_WRONLY O_CREAT O_TRUNC, mode) This interface is made obsolete by open Only for write-access. Q: What if you want to create a file for READ and WRITE? #include <unistd.h> int close(int filedes); All open files are automatically closed by the kernel when a process terminates Closing a file descriptor releases any record locks on that file 2008-12-1 cs3320 19 2008-12-1 cs3320 20 mode Flags for O_CREAT Defined in <sys/stat.h> S_IRUSR: owner read permit S_IWUSR: owner write permit S_IXUSR: owner execute permit S_IRGRP: group read permit S_IWGRP: group write permit S_IROTH: others read permit S_IWOTH: owners write permit S_IXOTH: others execute permit open( myfile, O_CREAT, S_IRUSR S_IXOTH) File I/O - lseek #include <sys/types> #include <unistd.h> off_t lseek(int filedes, off_t offset, int whence); Current file offset in bytes changes file pointer whence: SEEK_SET, SEEK_CUR, SEEK_END determines how offset is to be used SEEK_SET : offset relative to start of file SEEK_CUR : offset relative to current position of file SEEK_END : offset relative to end of file off_t: typedef long off_t; /* 2 31 bytes */ or typedef longlong_t off_t; /* 2 63 bytes */ lseek fails if moved before start of file returns new file position if successful returns -1 if unsuccessful 2008-12-1 cs3320 21 2008-12-1 cs3320 22 Current Offset of lseek To find out current position use: currentoffset = lseek(fd, 0, SEEK_CUR); If you move past the end of file and write there, Unix automatically extends the size of the file and treats intermediate area as NULLS (0) Unix does not allocate disk area for intermediate space!! (see next example) 2008-12-1 cs3320 23 2008-12-1 cs3320 24

File size is 50 (bytes) 0000000 a b c d e f g h i j \0 \0 \0 \0 \0 \0 0000020 \0 \0 0000040 A B C D E F G H I J \0 \0 0000060 File I/O read and write #include <unistd.h> ssize_t read(int filedes, void *buf, size_t nbytes); copy upto count bytes from the file referenced by fd into buffer buf returns 0 if it attempts to copy after end of file returns -1 if unsuccessful the bytes are read from current position (file pointer) which is then updated accordingly Less than nbytes of data are read: EOF(0): terminal device (line-input), network buffering, record-oriented devices (e.g., tape) -1: error Offset is increased for every read() #include <unistd.h> ssize_t write(int filedes, const void *buf, size_t nbytes); Copy upto count bytes from a buffer buf into the file referenced by fd Write errors for disk-full or file-size-limit causes. When O_APPEND is set, the file offset is set to the end of the file before each write operation. 2008-12-1 cs3320 25 2008-12-1 cs3320 26 Suppose that foobar.txt consists of the 6 ASCII characters "foobar". Then what is the output of the following program? I/O Efficiency How do you move from home to dorm? int main() { int fd1, fd2; char c; fd1 = open("foobar.txt", O_RDONLY, 0); fd2 = open("foobar foobar.txt txt", O_RDONLY, 0); read(fd1, &c, 1); read(fd2, &c, 1); printf("c = %c\n", c); exit(0); The descriptors fd1 and fd2 each have their own open file table entry, so each descriptor has its own file position for foobar.txt. Thus, the read from fd2 reads the first byte of foobar.txt 2008-12-1 cs3320 27 2008-12-1 cs3320 28 Closing a file: close() int close(int fd); Frees fd; releases resources When a process terminates, all fds are automatically closed Still it is a good idea to close yourself Returns 0 if success -1 if failure 2008-12-1 cs3320 29 2008-12-1 cs3320 30

Read(4, ) File I/O Sharing Tables of Opened Files (per process) Memory System Open File Table Disk In-core v-node list Table per process: file des flags, a pointer #include <sys/file.h> int flock(int fd, int operation); //LOCK_SH LOCK_EX LOCK_UN sync data block data block i-node i-node i-node System Call stat() int stat(const char* name, struct stat* buf) stat() fills the buffer buf with information about file name The stat structure is defined in /usr/include/sys/stat.h and includes the following fields: st_mode the permission flags st_uid the user ID st_gid the group ID st_size the file size st_atime the last access time st_mtime the last modification time st_ctime the last status-change time 2008-12-1 cs3320 31 2008-12-1 cs3320 32 Macros in /usr/include/sys/stat.h S_ISDIR(st_mode) true if directory S_ISCHR(st_mode) true if file is a character special device S_ISBLK(st_mode) true if file is a block special device S_ISREG(st_mode) true if a regular file S_ISFIFO(st_mode) true if a pipe Variations of stat() lstat() : same as stat() except it returns information about the symbolic link itself rather than the file it refers to fstat() : same as stat() except it takes file descriptor as first parameter All return 0 if successful and -1 otherwise 2008-12-1 cs3320 33 2008-12-1 cs3320 34 Example Using stat() Call updatestat() if the file is a regular file character special file, or block special file. Either adds or updates the file's status entry If status has changes, updateentry() is called to display file's new status The decoding of time is done using localtime() and asctime() Directory manipulation DIR * opendir (const char *dirname) struct dirent * readdir (DIR *dirstream) closedir 2008-12-1 cs3320 35 2008-12-1 cs3320 36

Opening a Directory Stream Function: DIR * opendir (const char *dirname) The opendir function opens and returns a directory stream for reading the directory whose file name is dirname. The stream has type DIR *. If unsuccessful, opendir returns a null pointer. Data Type: struct dirent This is a structure type used to return information about directory entries. It contains the following fields: char d_name[] This is the null-terminated file name component. ino_t d_fileno This is the file serial number. unsigned char d_namlen This is the length of the file name, not including the terminating null character. Its type is unsigned char because that is the integer type of the appropriate size unsigned char d_type This is the type of the file, possibly unknown. The following constants are defined for its value: DT_UNKNOWN The type is unknown. On some systems this is the only value returned. DT_REG A regular file. DT_DIR A directory. DT_FIFO A named pipe, or FIFO. DT_SOCK A local-domain socket. DT_CHR A character device. DT_BLK A block device. 2008-12-1 cs3320 37 Reading and Closing a Directory Stream Function: struct dirent * readdir (DIR *dirstream) This function reads the next entry from the directory. It normally returns a pointer to a structure containing information about the file. This structure is statically allocated and can be rewritten by a subsequent call. If there are no more entries in the directory or an error is detected, readdir returns a null pointer. The following errno error conditions are defined for this function: EBADF The dirstream argument is not valid. Function: int closedir (DIR *dirstream) This function closes the directory stream dirstream. It returns 0 on success and -1 on failure. The following errno error conditions are defined for this function: EBADF The dirstream argument is not valid. 2008-12-1 cs3320 38 Sample code #include <stddef.h> #include <sys/types.h> #include <dirent.h> int main (void){ DIR *dp; struct dirent *ep; dp = opendir ("./"); if (dp!= NULL){ while (ep = readdir (dp)) puts (ep->d_name); (void) closedir (dp); else perror ("Couldn't open the directory"); return 0; 2008-12-1 cs3320 39 Reading Directory Information: getdents() int getdents(int fd, struct dirent* buf, int structsize) Reads the directory file with descriptor fd from its current position and fills structure pointed to by buf with the next entry. Synopsis #include <unistd.h> #include <linux/types.h> #include <linux/dirent.h> #include <linux/unistd.h> #include <errno.h> int getdents(unsigned int fd, struct dirent *dirp, unsigned int count); Description This is not the function you are interested in. Look at readdir(3) for the POSIX conforming C library interface. This page documents the bare kernel system call interface. The system call getdents() reads several dirent structures from the directory pointed at by fd into the memory area pointed to by dirp. The parameter count is the size of the memory area. The dirent structure is declared as follows: struct dirent { long d_ino; /* inode number */ off_t d_off; /* offset to next dirent */ unsigned short d_reclen; /* length of this dirent */ char d_name [NAME_MAX+1]; /* filename (null-terminated) */ 2008-12-1 cs3320 40 Reading Directory Information: getdents() The dirent struct is defined in /usr/include/sys/dirent.h and contains the following fields: d_ino : the inode number d_off : the offset of the next directory entry d_reclen : length of the dirent struct d_name : the filename Reading Directory Information: getdents() Returns length of the directory entry if successful 0 if last directory entry has already been read -1 if error processdirectory function skips. and.. and uses lseek to advance to the next directory entry 2008-12-1 cs3320 41 2008-12-1 cs3320 42

System call chmod() int chmod (const char* filename, int mode) int fchmod (int fd, int mode) These change the mode of filename to mode (specified as octal; ex. 0600) Set user ID and set group ID flags have values 04000 and 02000 respectively int main() { int flag; flag = chmod("test.txt",0600); if (flag == -1) perror("problem setting mode"); struct tm{ int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ #ifdef USE_BSD long int tm_gmtoff; /* Seconds east of UTC. */ const char *tm_zone; /* Timezone abbreviation. */ #else long int tm_gmtoff; /* Seconds east of UTC. */ const char * tm_zone; /* Timezone abbreviation. */ #endif ; 2008-12-1 cs3320 43 2008-12-1 cs3320 44 NAME strftime - format date and time SYNOPSIS #include <time.h> size_t strftime(char *s, size_t max, const char *format, const struct tm *tm); DESCRIPTION The strftime() function formats the broken-down time tm according to the format specification format and places the result in the character array s of size max. 2008-12-1 cs3320 45 NAME asctime, ctime, gmtime, localtime, mktime, asctime_r, ctime_r, gmtime_r, localtime_r - transform date and time to broken-down time or ASCII SYNOPSIS #include <time.h> char *asctime(const struct tm *tm); char *asctime_r(const struct tm *tm, char *buf); char *ctime(const time_t *timep); char *ctime_r(const time_t *timep, char *buf); struct tm *gmtime(const time_t *timep); struct tm *gmtime_r(const time_t *timep, struct tm *result); struct tm *localtime(const time_t *timep); struct tm *localtime_r(const time_t *timep, struct tm *result); time_t mktime(struct tm *tm); DESCRIPTION The ctime(), gmtime() and localtime() functions all take an argument of data type time_t which represents calendar time. When interpreted as an absolute time value, it represents the number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). 2008-12-1 cs3320 46 Process Management Every process in UNIX has some code some data a stack 1) The parameters 2) The address (on the stack) of the calling programs stack frame 3) The return address--where to go when the function returns 4) The automatic (local) variables a unique process ID (PID) Init Process When UNIX starts (boots), there is only one process, called init, with process ID = 1. The only way to create a new process is to duplicate an existing process So init is the ancestor of all subsequent processes. Initially, init duplicates (forks) several times and each child process replaces its code (execs) with the code of the executable getty which is responsible for user logins. 2008-12-1 cs3320 47 2008-12-1 cs3320 48

Parent and Child Processes It is very common for a parent process to suspend itself until one of its child processes terminates. For example: Consider the way a shell process executes a utility in the foreground: The shell first duplicates itself using fork() The child shell process replaces its code with that of the utility using exec(). (Differentiates) The parent process waits for the child process to terminate using wait() When the child process terminates using exit(), the parent process is informed (using a signal) the parent process presents the user with the shell prompt to accept the next command fork() getpid() getppid() exit() wait() exec family System Calls 2008-12-1 cs3320 49 2008-12-1 cs3320 50 System Call fork() pit_t fork(void) Causes a process to duplicate The child process is almost exactly a duplicate of the parent process inherits a copy of its parent's code, data, stack, open file descriptors, and signal tables The only difference is in the process IDs (pid) and parent process IDs (ppid) If fork() succeeds, it returns a value of 0 to the child process and the PID of the child process to the parent. If fork() fails, it returns a -1 to the parent process and the child process is not created. 2008-12-1 cs3320 51 Sample code #include <stdlib.h> int main(){ pid_t child_pid; /* storage place for the pid of the child process, and its exit status. */ int child_status, i=10,j=10; child_pid = fork(); /* lets fork off a child process... */ switch (child_pid) { /* check what the fork() call actually did */ case -1: /* fork() failed */ perror("fork"); /* print a system-defined error message */ exit(1); case 0: /* fork() succeeded, we're inside the child process */ j=i+10; printf("hello world from child! i=%d, j=%d\n,i,j); exit(0); /* here the CHILD process exits, not the parent. */ default: /* fork() succeeded, we're inside the parent process */ j=j+5; wait(&child_status); /* wait till the child process exits */ printf("hello world from parent! i=%d, j=%d\n",i,j); /* parent's process code may continue here... */ return 0; As before, suppose foobar.txt consists of 6 ASCII characters "foobar". Then what is the output of the following program? int main() { int fd; char c; fd = open("foobar.txt", O_RDONLY, 0); if(fork() == 0) {read(fd, &c, 1); exit(0); wait(null); read(fd, &c, 1); printf("c = %c\n", c); exit(0); System Call getpid() pid_t getpid(void) pid_t getppid(void) Return the process' ID and parent process ID respectively They always succeed The PPID value for process with ID=1 is 1 Child inherit s the parent s descriptor table. So child and parent share an open file table entry. Hence they share a file position. c= o 2008-12-1 cs3320 53 2008-12-1 cs3320 54

Example Program with getpid() main () { int pid; printf ("I'm the original process with PID %d and PPID %d.\n", getpid (), getppid ()); pid = fork (); /* Duplicate. Child & parent continue from here */ if (pid!= 0) /* pid is non-zero, so I must be the parent */ { printf ("I'm the parent process with PID %d and PPID %d.\n", getpid (), getppid ()); printf ("My child's PID is %d\n", pid); else /* pid is zero, so I must be the child */ { printf ("I'm the child process with PID %d and PPID %d.\n", getpid (), getppid ()); printf ("PID %d terminates.\n", getpid () ); /* Both processes execute this */ Example Program with getpid() $ myfork I'm the original process with PID 639 and PPID 416. I'm the parent process with PID 639 and PPID 416. My child's PID is 640 PID 639 terminates. $ I'm the child process with PID 640 and PPID 1. PID 640 terminates. 2008-12-1 cs3320 55 2008-12-1 cs3320 56 Orphan Processes If a parent process terminates before its child terminates, the child process is automatically adopted by the init process The following gprogram shows this. Example Program of Orphan main () { int pid; printf ("I'm the original process with PID %d and PPID %d.\n", getpid (), getppid ()); pid = fork (); /* Duplicate. Child & parent continue from here */ if (pid!= 0) /* Branch based on return value from fork () */ { /* pid is non-zero, so I must be the parent */ printf ("I'm the parent process with PID %d and PPID %d.\n", getpid (), getppid ()); printf ("My child's PID is %d\n", pid); else { /* pid is zero, so I must be the child */ sleep (5); /* Make sure that the parent terminates first */ printf ("I'm the child process with PID %d and PPID %d.\n", getpid (), getppid ()); printf ("PID %d terminates.\n", getpid () ); /* Both processes execute this */ 2008-12-1 cs3320 57 2008-12-1 cs3320 58 Example Program of Orphan $ orphan I'm the original process with PID 680 and PPID 416. I'm the parent process with PID 680 and PPID 416. My child's PID is 681 PID 680 terminates. $ I'm the child process with PID 681 and PPID 1. PID 681 terminates. System Call exit() void exit(int status) When a child process terminates, it sends its parent a SIGCHLD signal and waits for its termination code (status) to be accepted. Only lower 8 bits of status are used; so value 0-255 closes all of a process' file descriptors, deallocates its code, data, and stack; then terminates the process. A process which is waiting for its parent process to accept its return code is called a zombie process. A parent accepts a child's termination code by executing wait() 2008-12-1 cs3320 59 2008-12-1 cs3320 60

System Call exit() The kernel makes sure that all of a terminating process' children are adopted by init by setting their PPID's to 1; init always accepts its children's termination code. exit() never returns Example of exit() % cat myexit.c #include <stdlib.h> /* needed for exit */ main() { printf("i am going to exit with status code 42\n"); exit(42); % myexit I am going to exit with status code 42 % echo status is $? 42 2008-12-1 cs3320 61 2008-12-1 cs3320 62 Zombie Processes A process cannot leave the system until parent process accepts its termination code even if it has exit-ed If parent process is dead; init adopts process and accepts code If the parent process is alive but is unwilling to accept the child's termination code because it never executes wait() the child process will remain a zombie process. Zombie Processes Zombie processes do not take up system resources But do use up an entry in the system's fixed-size process table Too many zombie processes is a problem 2008-12-1 cs3320 63 2008-12-1 cs3320 64 main () { int pid; pid = fork (); /* Duplicate */ Zombie Example /* Branch based on return value from fork () */ if (pid!= 0) { /* Never terminate, never execute a wait () */ while (1) sleep (1000); else { exit (42); /* Exit with a silly number */ Zombie Example $ zombie & [1] 684 $ ps 684 p4 S 0:00 zombie 685 p4 Z 0:00 (zombie <zombie>) 686 p4 R 0:00 ps $ kill 684 [1]+ Terminated zombie $ ps 688 p4 R 0:00 ps $ 2008-12-1 cs3320 65 2008-12-1 cs3320 66

Waiting for a Child: wait() pid_t wait(int *status) causes a process to suspend until one of its child processes terminates. A successful call to wait() returns the PID of the child process that terminated places a status code into status Waiting for a Child: wait() Status code is encoded as: If the rightmost byte of status is zero the leftmost byte contains the low 8 bits of the value returned by the child's exit() or return() call If the rightmost t byte of status t is non-zero the rightmost 7 bits are equal to the Signal Number that caused the child to terminate the last bit is set to 1 if the child core dumped 2008-12-1 cs3320 67 2008-12-1 cs3320 68 Waiting for a Child: wait() If a process executes a wait() and has no children, wait() returns immediately with a value of -1 If a process executes a wait(), And one or more children are already zombies, Then wait() returns immediately with the status of one of the zombies Example Program using wait() main () { int pid, status, childpid; printf ("I'm the parent process and my PID is %d\n", getpid()); pid = fork (); /* Duplicate */ if (pid!= 0) /* Branch based on return value from fork () */ { printf ("I'm the parent process with PID %d and PPID %d\n", getpid (), getppid ()); /* Wait for a child to terminate. */ childpid = wait (&status); printf("a child with PID %d terminated with exit code %d\n", childpid, status >> 8); else { printf ("I'm the child process with PID %d and PPID %d\n", getpid (), getppid ()); exit (42); /* Exit with a silly number */ printf ("PID %d terminates\n", getpid () ); 2008-12-1 cs3320 69 2008-12-1 cs3320 70 Example Program using wait() $ mywait I'm the parent process and my PID is 695 I'm the parent process with PID 695 and PPID 418 I'm the child process with PID 696 and PPID 695 A child with PID 696 terminated with exit code 42 PID 695 terminates Differentiating a Process: exec With the exec family, a process replaces Its current code Data Stack PID and PPID stay the same Only the code that the process is executing changes 2008-12-1 cs3320 71 2008-12-1 cs3320 72

Differentiating a Process: exec Use the absolute or relative name int execl(const char* path, const char* arg0,..., const char* argn, NULL) int execv(const char* path, const char* argv[ ]) Differentiating a Process: exec Use $PATH variable to find the executable: int execlp(const char* path, const char* arg0,..., const char* argn, NULL) int execvp(const char* path, const char* argv[ ]) 2008-12-1 cs3320 73 2008-12-1 cs3320 74 Differentiating a Process: exec argi or argv[i]: ith command line argument for executable (arg0: name of executable) If executable is not found, -1 is returned otherwise the calling gprocess replaces its code, data, and stack with those of the executable and starts executing the new code A successful exec() never returns Example Using execl() main () { printf ("I'm process %d and I'm about to exec an ls -l\n", getpid ()); execl ("/bin/ls", "ls", "-l", NULL); /* Execute ls */ printf ("This line should never be executed\n"); $ myexec I'm Im process 710 and I'm Im about to exec an ls -l total 38 -rw-rw-r-- 1 raj raj 187 Jul 22 20:24 alarm.c -rw-rw-r-- 1 raj raj 226 Jul 22 20:22 background.c -rw-rw-r-- 1 raj raj 284 Jul 22 20:22 mychdir.c -rw-rw-r-- 1 raj raj 2058 Jul 22 20:23 vount.c -rwxrwxr-x 1 raj raj 4174 Jul 24 12:08 zombie -rw-rw-r-- 1 raj raj 298 Jul 22 20:20 zombie.c 2008-12-1 cs3320 75 2008-12-1 cs3320 76 Changing Directories: chdir() Every process has a current working directory Used when processing a relative path name A child process inherits the current working directory from its parent Example: when a utility is run from a shell, the utility process inherits the shell's current working directory Changing Directories: chdir() int chdir(const char* pathname) Sets a process' current working directory to pathname The process must have execute permission from the directory for chdir() to succeed chdir() returns -1 if it fails 0 if it succeeds 2008-12-1 cs3320 77 2008-12-1 cs3320 78

Example Using chdir() main () { /* Display current working directory */ system ("pwd"); /* Change working directory to root directory */ chdir ("/"); /* Display new working directory */ system ("pwd"); chdir ("/home/naveen"); /* Change again */ system ("pwd"); /* Display again */ $ mychdir /home/raj/3320/ch12 / /home/naveen $ 2008-12-1 cs3320 79 Changing Priorities: nice() Child process inherits priority of parent process Can change the priority using nice() int nice(int delta) Adds delta to the priority Legal values of priority it -20 to +19 Only super user can change to negative priority. Smaller the priority value, faster the process will run. 2008-12-1 cs3320 80 Getting and Setting User and Group IDs: The get functions always succeed The set methods will succeed only when executed by super user or if id equals real or effective id of the process. Example Using fork() and exec() Executes a program in background Original process creates a child process to exec the specified executable and terminates. The orphaned child process is adopted by init. uid_t getuid() uid_t geteuid() gid_t getgid() gid_t getegid() uid_t setuid(uid_t id) uid_t seteuid(uid_t id) uid_t setgid(gid_t id) uid_t setegid(gid_t id) 2008-12-1 cs3320 81 2008-12-1 cs3320 82 Example Using fork() and exec() main (int argc, char* argv[]) { if (fork () == 0) /* Child */ { /* Execute other program */ execvp (argv[1], &argv[1]); fprintf (stderr, "Could not execute %s\n", argv[1]); $ background gcc mywait.c Review C commands here work with OS Error Handling File I/O and management open read write close stat 2008-12-1 cs3320 83 2008-12-1 cs3320 84

System Commands fork() getpid() exit() wait() exec Review Review Working with directories and file entries getdents chown chmod Process Management chdir nice 2008-12-1 cs3320 85 2008-12-1 cs3320 86