Understanding Unix Process Management in Computer Systems II

Slide Note
Embed
Share

This overview delves into the creation, termination, memory layout, and dynamic memory management of Unix processes in Computer Systems II. It covers the distinctions between code, executables, and processes, the memory layout of Unix processes, management of heap memory using malloc and free functions, and the importance of process identifiers. The content provides a comprehensive understanding of how Unix processes function and the essential concepts related to their management.


Uploaded on Oct 07, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Computer Systems II Creating and Terminating Unix Processes

  2. Recap: Code vs. Executable vs. Process C source code C statements organized into functions Stored as a collection of files (.c and .h) C source code Executable module Binary image generated by compiler Stored as a file (e.g., a.out) compiling Executable Process Instance of a program that is executing Managed by the operating system running Process

  3. Recap: Memory Layout of a Unix Process 0 (machine code) Text (initialized global variables) Data (uninitialized global variables) BSS (dynamically allocated memory) Heap Stack (local variables) High Memory Address

  4. Heap: Dynamic Memory #include <stdlib.h> void *malloc(size_t size); void free(void *ptr); 0 Text Heap p1 char *p1 = malloc(3); char *p2 = malloc(1); char *p3 = malloc(4); free(p2); ... Data BSS Heap Stack 0xFFFFFFFF

  5. Heap: Dynamic Memory #include <stdlib.h> void *malloc(size_t size); void free(void *ptr); 0 Text Heap p1 char *p1 = malloc(3); char *p2 = malloc(1); char *p3 = malloc(4); free(p2); ... Data p2 BSS Heap Stack 0xFFFFFFFF

  6. Heap: Dynamic Memory #include <stdlib.h> void *malloc(size_t size); void free(void *ptr); 0 Text Heap p1 char *p1 = malloc(3); char *p2 = malloc(1); char *p3 = malloc(4); free(p2); ... Data p2 p3 BSS Heap Stack 0xFFFFFFFF

  7. Heap: Dynamic Memory #include <stdlib.h> void *malloc(size_t size); void free(void *ptr); 0 Text Heap p1 char *p1 = malloc(3); char *p2 = malloc(1); char *p3 = malloc(4); free(p2); ... Data BSS p3 Heap No garbage collector! Everything allocated with malloc must be deallocated with free Stack 0xFFFFFFFF

  8. Recap: Process Identifiers Each process in the system has a unique identifier What does this code print out? #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main() { pid_t myid; myid = getpid(); printf( myid = [%d]\n , myid); return 0; } getpid returns the identifier of the calling process

  9. Creating a New Unix Process: fork The fork system call creates a new process in the system - Calling process becomes Parent - New process is its Child (copy of Parent) - Parent and child execute concurrently Parent fork() Child

  10. Tree of Unix Processes After a successful fork, both parent and child keep running, and each can fork off other processes The result is a Processs Tree The root of the tree is a special process created by the OS during startup

  11. The fork System Call Syntax is pid_t fork(void); Sample call: pid_t ret; ret = fork(); Calling process split into two: parent and child Child is an identical copy of the parent, with one exception: ret = 0 in the child process ret = non-zero value in the parent ret = -1 if fork is unsuccessful

  12. The fork System Call Illustrated fork() ret = fork(); ret = -1 if unsuccessful Text Text Data Data ret = 0 in the child Heap Heap ret = the child s identifier in the parent process ret = 0 Stack Stack ret = xxx Parent Child

  13. Try This Out #include ??? /* what header files are needed? */ #include <stdio.h> int main() { pid_t ret; pid_t myid; /* fork another process */ ret = fork(); if (ret < 0) { /* error occurred */ printf("Fork Failed \n"); return 1; } myid = getpid(); printf( ret = [%d], myid = [%d]\n , ret, myid); return 0; }

  14. fork: Parent and Child The child process inherits from parent - identical copy of memory - CPU registers - all files that have been opened by the parent Execution proceeds concurrently with the instruction following the fork system call

  15. How fork Works (1) pid = 25 Data Resources Text Stack PCB File ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } printf( fork error ); exit(1); UNIX

  16. How fork Works (2) pid = 25 pid = 26 Data Data Resources Text Text Stack Stack PCB PCB File ret = 0 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } ret = 26 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } printf( fork error ); exit(1); printf( fork error ); exit(1); UNIX

  17. How fork Works (3) pid = 25 pid = 26 Data Data Resources Text Text Stack Stack PCB PCB File ret = 0 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } ret = 26 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } printf( fork error ); exit(1); printf( fork error ); exit(1); UNIX

  18. How wait Works Parent blocks until child terminates - If the parent has multiple children, one wait call causes parent to wait for only one arbitrary child - If the parent must wait for all children, it needs to invoke multiple wait calls (one per child) ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } printf( fork error ); exit(1); printf( fork error ); exit(1); Parent blocked UNIX

  19. How exit Works When the child terminates say, by calling exit the operating system sends a signal to unblock the parent - Parent is now ready to complete its execution ret = 0 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } ret = 26 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); } printf( fork error ); exit(1); printf( fork error ); exit(1); Parent unblocked UNIX

  20. How fork Works (6) pid = 25 Data Resources Text Stack PCB File ret = 26 ret = fork(); switch(ret) { case -1: case 0: // I am the child <code for child > exit(0); default: // I am parent ... <code for parent > wait(0); < > Parent ready to complete execution printf( fork error ); exit(1);

  21. Recap: Managing Unix Processes List processes using the ps (process status) ommand: ps -f The first column of the result is the process identifier To force a process to finish executing, use kill: kill s KILL processid (or) kill SIGKILL processid (or) kill 9 processid

  22. Fork Example 1: What Output? int x = 5; int main() { pid_t ret; ret = fork(); if (ret != 0) { printf( parent: x = %d\n , --x); exit(0); } else { printf( child: x = %d\n , ++x); exit(0); } }

  23. Fork Example 2 Both parent and child continue forking: L0 L1 Bye P void fork2() { printf("L0\n"); fork(); printf("L1\n"); fork(); printf("Bye\n"); } L1 Bye C1 C2 Bye C3 Bye

  24. Fork Example 3 Both parent and child continue forking: L0 L1 L2 Bye P void fork3() { printf("L0\n"); fork(); printf("L1\n"); fork(); printf("L2\n"); fork(); printf("Bye\n"); } L1 L2 Bye L2 Bye C1 C2 C4 Bye L2 Bye C6 C5 C3 Bye Bye C7 Bye

  25. Fork Example 4 Only the parent continues forking: L0 L1 L2 void fork4() { int ret; P Bye printf("L0\n"); ret = fork(); if (ret != 0) { printf("L1\n"); ret = fork(); if (ret != 0) { printf("L2\n"); fork(); } } printf("Bye\n"); } C1 C2 C3 Bye Bye Bye

  26. Fork Example 5 Only the child continues forking: void fork5() { int ret; L0 Bye P printf("L0\n"); ret = fork(); if (ret == 0) { printf("L1\n"); ret = fork(); if (ret == 0) { printf("L2\n"); fork(); } } printf("Bye\n"); } C1 L1 Bye C2 L2 Bye C3 Bye

  27. Recap fork creates a duplicate of the calling process returns 0 to the child, and child identifier to the parent returns -1 in case of failure wait invoked by parent parent blocks until one (arbitrary) child terminates exit terminates the calling process