Presentation is loading. Please wait.

Presentation is loading. Please wait.

Contents 1. Preface/Introduction 2. Standardization and Implementation 3. File I/O 4. Standard I/O Library 5. Files and Directories 6. System Data Files.

Similar presentations


Presentation on theme: "Contents 1. Preface/Introduction 2. Standardization and Implementation 3. File I/O 4. Standard I/O Library 5. Files and Directories 6. System Data Files."— Presentation transcript:

1 Contents 1. Preface/Introduction 2. Standardization and Implementation 3. File I/O 4. Standard I/O Library 5. Files and Directories 6. System Data Files and Information 7. Environment of a Unix Process  8. Process Control 9. Signals 10.Inter-process Communication

2 Process Control  Objectives  Process Control: Process Creation, Process Execution, Process Termination.  Process Properties E.g., ID ’ s.  Related Functions E.g., system()

3 Process Control: Process Identifiers  Process Identifiers Process ID – a nonnegative unique integer  Special Processes  PID 0 – Swapper (i.e., the scheduler) Kernel process, part of kernel No program on disks correspond to this process  PID 1 – init responsible for bringing up a Unix system after the kernel has been bootstrapped. (/etc/rc* & init or /sbin/rc* & init). Never dies. Init is a user process with superuser privileges  PID 2 - pagedaemon responsible for paging Kernel process

4 Process Control: Identifiers #include pid_t getpid(void);id of caller pid_t getppid(void);id of parent uid_t getuid(void);real uid of caller uid_t geteuid(void);effective uid of caller gid_t getgid(void);real gid of caller gid_t getegid(void);effective gid of caller None of them has an error return code.

5 fork #include pid_t fork(void);  The only way beside the bootstrap process to create a new process.  Called once but return twice 0 for the child process (getppid) Child pid for the parent (one parent may have many children)  Copies of almost everything but no sharing of memory, except text Optimization: Copy-On-Write (fork() – exec())

6 fork  Program 8.1 fork(), race conditions, write (unbuffered) vs standard I/O functions (buffered). Also, we do not know if child starts executing before parent or vice versa – even with sleep()!!!  File sharing Sharing of file offsets (including stdin, stdout, stderr): indirectly, as if dup function is called for every file descriptor. Below is a schematic of parent and child tables after call to fork: important for parent and child to share same offsets for proper offset update ; requires some form of synchronization (for not mixing outputs)

7 #include #include"ourhdr.h" intglob = 6;/* static global variable */ charbuf[] = "a write example\n"; int main(void) { intvar;/* automatic variable on the stack */ pid_tpid; var = 88; if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) err_sys("write error"); printf("before fork\n");/* we don't flush stdout */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { glob++; var++; } else sleep(2);/* delay of 2 seconds */ printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var); exit(0); } Program 8.1

8 Execution trace of program 8.1 $ a.out a write to stdout before fork pid = 430, glob = 7, var = 89child’s variables were changed pid = 429, glob = 6, var = 88parent’s variables were not changed $ a.out > temp.txt $ cat temp.txt a write to stdout before fork pid = 432, glob = 7, var = 89 before fork effect of buffered standard io pid = 431, glob = 6, var = 88

9 fork  Normal cases for handling descriptors after fork: 1. The parent waits for the child to complete. Simple; offsets updated by child with no problem; parent can continue without problem after child terminates. 2. The parent and child each go their own way. Parent and child close descriptors they do not need: no interference for using descriptors.  Inherited properties: Real/effective [ug]id, supplementary gid, process group ID, controlling terminal, set[ug]id flag, current working dir, root dir, file-mode creation mask, signal mask, FD_CLOEXEC flags, environment, attached shared memory segments, resource limits  Differences on properties: Returned value from fork, process ID, parent pid, file locks not inherited, pending alarms cleared for child, pending signals set to empty for child

10 fork  Reasons for fork to fail Too many processes in the system (something wrong in the system!!!!) The total number of processes for the real uid exceeds the limit CHILD_MAX  Usages of fork Duplicate a process to run different sections of code  Example: network servers. Parent waits for a service request from client. When request arrives, parent forks and let child handle the request. Parent goes back to wait for next request. Want to run a different program: examples are shells (on some systems, there is a single operation spawn = fork+exec)

11 exit Five ways to terminate: Normal termination Return from main(). Call exit() – ANSI C closes io streams, calls exit handlers Call _exit() – POSIX.1 called by exit Abnormal termination Call abort() Generates SIGABRT signal Be terminated by a signal: segmentation fault, divide by 0, kill(), … In all cases, kernel eventually takes control to close file descriptors, free memory, start another process

12 Process termination and return codes How a child process can notify parent the condition of termination? For exit and _exit, we can specify return code as exit status. For abnormal termination, kernel generates termination status to show reason for abnormal termination. Possible for parent of process to obtain this termination status through wait or waitpid functions.

13 Process termination problems Question: what happens if parent terminates before child or child terminates before parent? To whom is the terminating status returned? The child process has terminated, but its parent has not yet waited for it. Kernel keeps minimum info for parent: process ID, termination status, … available to parent when parent is ready to call wait or waitpid functions.  zombie process; ps prints process status as Z for a zombie process. The parent terminates before the child: child is inherited by init process (its parent ID becomes 1); guarantees that all processes have parents.  When a parent terminates, kernel checks all children and designates init as parent  Clean up of the zombies by the init process if needed What happens when process inherited by init terminates? Zombie? Answer is NO; init simply call wait to fetch terminating status; avoid that systems to be loaded with zombies.

14 wait & waitpid SIGCHLD signal from the kernel if a child terminates in order to notify parent. Default action is ignoring, but parent may wait for child termination through wait system calls. #include pid_t wait(int *statloc); ret pid if ok, -1 on error pid_t waitpid(pid_t pid, int *statloc, int options); ret pid if ok, -1 on error wait, waitpid cause calling process to block if all children are still running; return immediately with termination status of a child if child has terminated and parent waiting for termination status; returns immediately with an error if calling process does not have any child. wait can block caller until ANY of its children terminate (pid is returned by wait); waitpid allows to wait for a specific child to terminate and has an option not to be blocked. if child is a zombie and has terminated, wait returns immediately with that child ’ s status; blocks otherwise

15 wait & waitpid statloc is a pointer to an integer. If it is not NULL, it will point to location containing termination status of terminated process. POSIX defines set of macros to test return status In summary:  Three situations in calling wait/waitpid Block Return with the termination status of a child Return with an error.

16 wait & waitpid Macros to test termination status. Exit status WIFEXITED(status): true if status was returned for a child that terminated normally. We can use WEXITSTATUS(status) macro to fetch exit status as returned by exit or _exit. Signal # WIFSIGNALED(status): true if status returned for a child that terminated abnormally because of a signal it did not catch. We can use WTERMSIG(status) macro to fetch signal number that caused termination. Others WCOREDUMP(status) returns true if a core file of the terminated process was generated WIFSTOPPED(status): true if status is returned for a child currently stopped. WSTOPSIG(status) can be used to fetch signal number that caused child to be stopped

17 wait & waitpid Function pr_exit in Program 8.2 Note: no standard mapping of signal numbers to descriptive names. Need to took into to see that SIGABRT has value of 6. pr_exit implements a simple mapping. Program 8.3 generates exit/termination statuses and makes use of pr_exit. pid_t waitpid(pid_t pid, int *statloc, int options);  pid pid == -1 wait for any child; equivalent to wait pid > 0 wait for the child with pid pid == 0 wait for any child with the same group id pid < -1 wait for any child with the group ID = |pid|  pid + termination status (through statloc) of the child is returned if OK, or an error is returned if calling process has no children, specified process or group do not exist, pid is not a child of calling process.

18 #include #include"ourhdr.h" void pr_exit(int status) { if (WIFEXITED(status)) printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status), #ifdefWCOREDUMP WCOREDUMP(status) ? " (core file generated)" : ""); #else ""); #endif else if (WIFSTOPPED(status)) printf("child stopped, signal number = %d\n", WSTOPSIG(status)); } Program 8.2

19 #include #include"ourhdr.h" int main(void) { pid_tpid; intstatus; if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0)/* child */ exit(7); if (wait(&status) != pid) /* wait for child */ err_sys("wait error"); pr_exit(status); /* and print its status */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0)/* child */ abort();/* generates SIGABRT */ if (wait(&status) != pid) /* wait for child */ err_sys("wait error"); pr_exit(status);/* and print its status */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0)/* child */ status /= 0; /* divide by 0 generates SIGFPE */ if (wait(&status) != pid) /* wait for child */ err_sys("wait error"); pr_exit(status);/* and print its status */ exit(0); } PRORAM 8.3

20 Execution trace of program 8.3 $a.out normal termination exit status = 7 abnormal termination, signal number = 6 (core file generated) abnormal termination, signal number = 8 (core file generated)

21 wait & waitpid Errors No such child or wrong parent Option for waitpid WNOHANG: waitpid will not block if specified child is not immediately available. In this case, returns 0 WUNTRACED: job control. status of any child specified by pid that has stopped is returned if its status has not yet been reported since stopping. WIFSTOPPED macro determines if return value corresponds to a stopped child. waitpid provides 3 features not part of wait: – lets us wait for one particular process – non-blocking version – support job control through WUNTRACED option Program 8.4: forks a child but we do not want to wait for child and we do not want child to become a zombie until we terminate: call fork twice!!! -> inheritance by init

22 #include #include"ourhdr.h" int main(void) { pid_tpid; 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 that when we're done, init will reap our status. */ sleep(2); /* TRY TO make sure 1rst child terminates -> init is parent*/ printf("second child, parent pid = %d\n", getppid()); exit(0); } if (waitpid(pid, NULL, 0) != pid) /* wait for 1st 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); } PROGRAM 8.4 $a.out second child, parent pid=1

23 Execution trace $ a.out $ second child, parent pid = 1 1)Call sleep to try to make sure (but NO GUARANTEE!!!) 1rst child terminates before printing parent ID. After fork, either the parent or child can continue execution (we cannot know for sure which one resumes execution first). If no sleep in 2 nd child and it resumes execution after fork before parent, process ID that it prints would be the parent ID not 1. 2)Shell prints its prompt when original process terminates, which is before the 2 nd child prints its parent’s process ID.

24 Race Conditions  Def: When multiple processes are trying to access to shared data (updating), the final outcome depends on the order in which the processes run. Happens when assumptions are made about order of process execution after fork calls. Signaling and synchronization mechanism typically used to cope with this problem.  Example: Program 8.4, potential race condition Who is the parent of the 2nd child? No guarantee SLEEP orders correctly process execution!!!!  Program 8.5: race condition because it heavily depends on the order of execution of processes: Mixture of output by putc + setting of unbuffering for stdout

25 #include #include"ourhdr.h" static void charatatime(char *); int main(void) { pid_tpid; 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; intc; setbuf(stdout, NULL);/* set unbuffered */ for (ptr = str; c = *ptr++; ) putc(c, stdout); }PROGRAM 8.5

26 Execution trace of program 8.5 $ a.out -- 1 st exec looks correct output from child-- but this does not mean output from parent-- no race condition !!! $ a.out-- 2 nd exec with mixed output oouuttppuutt ffrroomm cphairledn t -- because of newline from child $ a.out-- mixed output oouuttppuutt ffrroomm pcahrielndt $ a.out-- mixed output ooutput from parent utput from child

27 Model for proper coordination to avoid race condition Assume parent and child run in parallel after fork. Requirement for proper coordination is to allow each process to “ report ” to other processes when it has finished performed a given action needed by the other process. #include “ ourhdr.h ” TELL_WAIT(); /* setup TELL_xxx and WAIT_xxx */ if ((pid=fork()) < 0) err_sys( “ fork error ” ); else if (pid==0) { ……… child does necessary action ………… TELL_PARENT(getppid());/* tell parent we finished*/ WAIT_PARENT();/* and wait for parent*/ ………….. exit(0); } ……… parent does necessary action ………… TELL_CHILD(pid); /* tell child we finished*/ WAIT_CHILD(); /* and wait for child*/ ……….. exit(0) }

28 #include #include"ourhdr.h" static void charatatime(char *); int main(void) {pid_tpid; 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; intc; setbuf(stdout, NULL);/* set unbuffered */ for (ptr = str; c = *ptr++; ) putc(c, stdout); } Program 8.6: modification of 8.5

29 exec Replace the text, data, heap, and stack segments of a process with a new program! New program starts executing at its main function. Typically called after fork. #include 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[]); l, v, and e stand for list, vector, and environment, respectively.

30 exec #include int execlp(const char *filename, const char *arg0, … /* (char *) 0 */); int execvp(const char *filename,, char *const argv[]);  With p, a filename is specified.If it contains ‘ / ’, taken as pathname; otherwise filename searched in directories specified in PATH PATH=/bin:/usr/bin:/user/local/bin:. if the file is not a machine executable, exec assumes a script file and /bin/sh is invoked with “ filename ” as input to the shell. Figure 8.5 shows a summary of exec function differences

31 Functionpathnamefilenamearg listargv[]environenvp[] execl execlp execle execv execvp execve Letter in name plve Figure 8.5: Differences between exec functions

32 exec Inherited from the calling process: pid, ppid, real [ug]id, supplementary gid, proc gid, controlling terminal, time left until alarm clock, current working dir, root dir, file mode creation mask, file locks, proc signal mask, pending signals, resource limits If FD_CLOEXEC flag set for descriptors, they are automatically closed across exec. Requirements & Changes Closing of open dir streams, effective user/group ID, may change depending on set-user-ID bits

33 exec In many Unix implementations, only execve is a system call. Program 8.7 demonstrates exec functions Program 8.8 The prompt bet the printing of argv[0] and argv[1].

34 #include #include"ourhdr.h" char*env_init[] = { "USER=unknown", "PATH=/tmp", NULL }; int main(void) {pid_tpid; if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) {/* specify pathname, specify environment */ if (execle("/home/ahmed/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); }PROGRAM 8.7: Example of exec function

35 #include"ourhdr.h" int main(int argc, char *argv[]) { inti; 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++) /* and all env strings */ printf("%s\n", *ptr); exit(0); } PROGRAM 8.8: echo command-line arg and env

36 Execution trace of program 8.7 $a.out argv[0] : echoall -- first exec argv[1] : myarg1 argv[2] : MY ARG2 USER=unknown PATH=/tmp argv[0] : echoall -- second exec $ argv[1] : only one arg USER=ahmed HOME=/home/ahmed LOGNAME=ahmed …. EDITOR=/usr/bin/vi


Download ppt "Contents 1. Preface/Introduction 2. Standardization and Implementation 3. File I/O 4. Standard I/O Library 5. Files and Directories 6. System Data Files."

Similar presentations


Ads by Google