56
Processes • A process is a program in execution • A process has (among other things) a number (pid) and a state. The pid enables the OS to distinguish between processes • A process is a heavyweight process. • A thread is a lightweight process.

Processes A process is a program in execution A process has (among other things) a number (pid) and a state. The pid enables the OS to distinguish between

  • View
    213

  • Download
    0

Embed Size (px)

Citation preview

Processes

• A process is a program in execution

• A process has (among other things) a number (pid) and a state. The pid enables the OS to distinguish between processes

• A process is a heavyweight process.

• A thread is a lightweight process.

Variable TypesBy Storage Class:• Static – Once allocated, static variables persist

throughout execution of the process. They are defined as:

– external variable names, – outside any function, or – defined inside a function with a static qualifier

• Automatic – Automatic variables come into existence when the block or function they are defined in begins execution and they cease to exist when the block or function exits. They are:

– local variable names or – parameters in a function that are not defined with a

static qualifier.

Variable TypesBy linkage class:

• Internal – Not visible to other files that are linked together. Variable names defined inside a function or outside a function with the static qualifier.

• External – Visible to other files that are linked together. Variable names defined outside a function and with no static qualifier.

Static Qualifier

Object Where Declared? Static Modifies Static Applied?

Storage Class

Linkage Class

variable

variable

variable

variable

function

function

inside a function

inside a function

outside any function

outside any function

outside any function

outside any function

storage class

storage class

linkage class

linkage class

linkage class

linkage class

yes

no

yes

no

yes

no

static

automatic

static

static

static

static

internal

internal

internal

external

internal

external

Program Layout

Command Line Arguments and Environment Variables

Stack

Heap

Un-initialized static data

Initialized static data

Program text

argc, argv, environment

Activation records for function calls

(return address, parameters, saved

registers, automatic variables)

allocations from malloc family

Static Variables

• If not explicitly initialized, they are initialized to 0 at runtime.

• Initialized and un-initialized occupy different sections of the program image.

• Initialized static variables are part of the executable module on disk, whereas un-initialized static variables are not.

Static Variable ExampleVersion 1:

int myarray[5000] = {1,2,3,4};void main(int argc, char *argv[]) { myarray[0] = 3; }

Version 2:int myarray[5000];void main(int argc, char *argv[]) { myarray[0] = 3;

Do an ls –l after compiling both versions. If integer is 4 bytes, version 1 executable is roughly 20,000 bytes larger.

Static Variables and Thread Safe

• Static variables can make a program unsafe for threaded execution.

• Readdir uses a static variable to hold return values.

• This strategy is also used for client/server stubs when marshaling/un-marshaling arguments for remote procedure calls.

• Therefore, avoid static variables in a threaded environment wherever possible.

Show History – list.h

/* Program 2.1 *//* list.h file */#include <sys/types.h>#include <time.h>

typedef struct data_struct { time_t time; char *string;} data_t;

int add_data(data_t data);data_t *get_data(void);int rewind_list(void);

listlib.c declarations

/* Program 2.2 */#include <stdlib.h>#include <string.h>#include "list.h"

typedef struct list_struct { data_t item; struct list_struct *next;} list_t;

static list_t *head_ptr = NULL;static list_t *tail_ptr = NULL;static list_t **trav_ptr = &head_ptr;static data_t temp;

listlib.c – add_data/* Allocate a node to hold data and add to end of list. Return 0 if successful or -1 if unsuccessful. */int add_data(data_t data){ list_t *newnode; if ((newnode = (list_t *)(malloc(sizeof(list_t) + strlen(data.string) + 1))) == NULL) return -1; newnode->item.time = data.time; newnode->item.string = (char *)(newnode + sizeof(list_t)); strcpy(newnode->item.string, data.string); newnode->next = NULL; if (head_ptr == NULL) head_ptr = newnode; else tail_ptr->next = newnode; tail_ptr = newnode; return 0;}

listlib.c – get_data /* Return a pointer in temp that has a copy of the data contained in the current node *trav_ptr. If at the end of the list return NULL. In any case, update trav_ptr. */data_t *get_data(void) { list_t *t; t = *trav_ptr; if (t == NULL) return NULL; if (temp.string != NULL) free (temp.string); if ( (temp.string = (char *) malloc(strlen(t->item.string) + 1)) == NULL) return NULL; temp.time = t->item.time; strcpy(temp.string, t->item.string); trav_ptr = &(t->next); return &temp; }

listlib.c – rewind_list

/* Set trav_ptr to contain the address of head_ptr. If head_ptr is NULL, return -1 indicating an empty list. Otherwise return 0. */

int rewind_list(void){ trav_ptr = &head_ptr; if (head_ptr == NULL) return -1; else return 0;}

keeploglib.c/* Program 2.4 */#include <stdio.h>#include <stdlib.h>#include "list.h" /* Execute cmd and store cmd and time of execution in history list. */int runproc(char *cmd){ data_t execute; time(&(execute.time)); execute.string = cmd; if (system(cmd) == -1) return -1; return add_data(execute);}/* Output the history list of the file f */void showhistory(FILE *f){ data_t *infop; rewind_list(); while ((infop = get_data()) != NULL) fprintf(f, "Command: %s\nTime: %s\n", infop->string, ctime(&(infop->time))); return;}

keeplog.c/* Program 2.3 */#include <stdio.h>#include <stdlib.h>#include <limits.h>#include <string.h>#ifndef MAX_CANON#define MAX_CANON 8192#endif void showhistory(FILE *f);int runproc(char *cmd);void main(int argc, char *argv[]) { char cmd[MAX_CANON]; int history = 1; if (argc == 1) history = 0; else if ((argc > 2) || strcmp(argv[1], "history")) { fprintf(stderr, "Usage: %s [history]\n", argv[0]); exit(1); } while(fgets(cmd, MAX_CANON, stdin) != NULL) { if (*(cmd + strlen(cmd) - 1) == '\n') *(cmd + strlen(cmd) - 1) = 0; if (history && !strcmp(cmd, "history")) showhistory(stdout); else if (runproc(cmd)) break; } printf("\n\n>>>>>>The list of commands executed is:\n"); showhistory(stdout); exit(0); }

Process ID (pid)

• Parent Process

• Child Process

• getpid(void) – returns the pid of the currently running process.

• getppid(void) – returns the pid of the parent of the currently running process.

User ID (uid)

• Each process is identified with a particular user called the owner.

• Each user has a unique ID (uid).

• getuid(void) – returns the process uid.

• geteuid(void) – returns the process Effective User ID (euid).

euid

• Each process has an Effective User ID (euid) that determines the privileges a process has for accessing resources such as files.

• The euid can change during execution.

Process/User ID Example

/* Example 2.1 */#include <stdio.h>#include <sys/types.h>#include <unistd.h>

void main(void){ printf("Process ID: %ld\n", (long)getpid()); printf("Parent process ID: %ld\n", (long)getppid()); printf("Owner user ID: %ld\n", (long)getuid()); printf("Owner euser ID: %ld\n", (long)geteuid());}

Process States

new

blocked

ready donerunning

ps

• Displays information about processes.

• Posix.2

• Spec 1170

ps -lheader MeaningF

S

UID

PID

PPID

C

PRI

NI

ADDR

SZ

WCHAN

TTY

TIME

COMMAND

Flags associated with the process

The process state

The user ID of the process owner

The process ID

The parent process ID

The processor utilization used for scheduling

The priority of the process

The nice value

The memory address of the process

The size of the process image

The address of the event if the process is sleeping

The controlling terminal

Cumulative execution time

Command name

fork(void) system call#include <sys/types.h>#include <unistd.h>

pid_t fork(void)_____________________________________Creates child process by copying parent’s memory image

fork return values

• Returns 0 to child

• Returns child PID to parent

• Returns –1 on error

Fork AttributesChild inherits:• Parent’s memory image • Most of the parent’s attributes including

environment and privilege.• Some of parent’s resources such as open files.

Child does not inherit:• Parent pid.• Parent time clock (child clock is set to 0).

fork Example#include <stdio.h>#include <unistd.h>#include <sys/types.h>void main(void){ pid_t childpid;

if ((childpid = fork()) == 0) { fprintf(stderr, "I am the child, ID = %ld\n", (long)getpid()); /* child code goes here */ } else if (childpid > 0) { fprintf(stderr, "I am the parent, ID = %ld\n", (long)getpid()); /* parent code goes here */ }}

fork (Chain)#include <stdio.h>#include <unistd.h>#include <sys/types.h>void main(void){ int i; int n; pid_t childpid; n = 4; for (i = 1; i < n; ++i) if (childpid = fork()) break; fprintf(stderr,"This is process %ld with parent %ld\n", (long)getpid(), (long)getppid()); sleep(1);}

fork (Fan)#include <stdio.h>#include <sys/types.h>#include <unistd.h>

void main(void){ int i; int n; pid_t childpid;

n = 4; for (i = 1; i < n; ++i) if ((childpid = fork()) <= 0) break; fprintf(stderr, "This is process %ld with parent %ld\n", (long)getpid(), (long)getppid()); sleep(1);}

fork (Tree)#include <stdio.h>#include <sys/types.h>#include <unistd.h>

void main(void){ int i; int n; pid_t childpid;

for (i = 1; i < n; ++i) if ((childpid = fork()) == -1) break; fprintf(stderr, "This is process %ld with parent %ld\n", (long)getpid(), (long)getppid()); sleep(1);}

pid_t wait(int *stat_loc)• Causes caller to pause until a child terminates, or stops

until the caller receives a signal.• If wait returns because a child terminates, the return value

(of type pid_t) is positive and is the pid of that child.• Otherwise wait returns –1 and sets errno.• stat_loc is a pointer to an integer variable.• If caller passes something other than NULL, wait stores

the return status (terminate status?) of the child.• POSIX specifies the following macros for testing the

return status: WIFEXITED, WEXITSTUS, WIFSIGNALED, WTERMSIG, WIFSTOPPED, and WSTOPSIG.

• Child returns status by calling exit, _exit, or return.

errno for wait

• ECHILD indicates there are no unwaited for child processes.

• EINTR indicates that the call was interrupted by a signal.

wait (Race Conditions)/* Program 2.5 */#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h> void main (void) { pid_t childpid; int status; if ((childpid = fork()) == -1) { perror("The fork failed"); exit(1); } else if (childpid == 0) fprintf(stderr, "I am the child with pid = %ld\n", (long)getpid()); else if (wait(&status) != childpid) fprintf(stderr, "A signal must have interrupted the wait\n"); else fprintf(stderr, "I am the parent with pid = %ld and child pid = %ld\n", (long)getpid(), (long)childpid); exit(0); }

Wait for Child or Error#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <errno.h>void main(void) { int status; pid_t childpid; pid_t waitreturn; childpid = fork(); if (childpid == 0) { fprintf(stderr,"Child %ld will sleep for 5 seconds\n",(long)getpid()); sleep(5); fprintf(stderr,"Child %ld will now exit\n",(long)getpid()); exit(0); } fprintf(stderr,"Parent %ld will wait for child %ld\n", (long)getpid(),(long)childpid); while(childpid != (waitreturn = wait(&status))) if ((waitreturn == -1) && (errno != EINTR)) break; }

waitpid – WNOHANG #include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <errno.h>void main(void) { int status; pid_t childpid; pid_t waitreturnpid; childpid = fork(); if (childpid == 0) { fprintf(stderr,"Child %ld will sleep for 5 seconds\n",(long)getpid()); sleep(5); fprintf(stderr,"Child %ld will now exit\n",(long)getpid()); exit(0); } sleep(8); fprintf(stderr,"Parent %ld will wait for any child\n",(long)getpid()); while(waitreturnpid = waitpid(-1, &status, WNOHANG)) if (!((waitreturnpid == -1) && (errno != EINTR))) break; fprintf(stderr,"Parent will exit after receiving %ld from waitpid\n", waitreturnpid); }

Fan with wait#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <errno.h>void main(void) { int i; int n; pid_t childpid; int status; n = 4; for (i = 1; i < n; ++i) if ((childpid = fork()) <= 0) break; for( ; ; ) { childpid = wait(&status); if ((childpid == -1) && (errno != EINTR)) break; } fprintf(stderr, "I am process %ld, my parent is %ld\n", (long)getpid(), (long)getppid()); }

Chain with wait#include <stdio.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <errno.h> void main(void) { int i; int n; pid_t childpid; int status; pid_t waitreturn; n = 4; for (i = 1; i < n; ++i) if (childpid = fork()) break; while(childpid != (waitreturn = wait(&status))) if ((waitreturn == -1) && (errno != EINTR)) break; fprintf(stderr, "I am process %ld, my parent is %ld\n", (long)getpid(), (long)getppid()); }

Background Processes

• Child process becomes background process when it executes setsid().

• Child that becomes background process never returns to parent.

• Background processes cannot be interrupted with ctrl-c.

execl, execlp, execle“l” – Passes command directly as a parameter

in exec.

• execl searches for command in fully qualified pathname passed as exec parameter or in current directory

• execlp uses PATH environment variable to find command

• execle uses environment passed as exec parameter to find command

execv, execvp,execve“v” – Passes command as member of argument array

(i.e., argv[] or makeargv[])

• execv searches for arg array command in fully qualified pathname passed in exec or in current directory

• execvp uses PATH environment variable to find arg array command

• execve uses environment passed as exec parameter to find arg array command

execl Example/* Program 2.6 */#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>void main(void) { pid_t childpid; int status; if ((childpid = fork()) == -1) { perror("Error in the fork"); exit(1); } else if (childpid == 0) { /* child code */ if (execl("/usr/bin/ls", "ls", "-l", NULL) < 0) { perror("Exec of ls failed"); exit(1); } } else if (childpid != wait(&status)) /* parent code */ perror("A signal occurred before the child exited"); exit(0); }

execvp Example/* Program 2.7 */#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <errno.h>void main(int argc, char *argv[]) { pid_t childpid, waitreturn; int status; if ((childpid = fork()) == -1) { perror("The fork failed"); exit(1); } else if (childpid == 0) { /* child code */ if (execvp(argv[1], &argv[1]) < 0) { perror("The exec of command failed"); exit(1); } } else /* parent code */ while(childpid != (waitreturn = wait(&status))) if ((waitreturn == -1) && (errno != EINTR)) break; exit(0); }

Use of makeargv#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>int makeargv(char *s, char *delimiters, char ***argvp);void main(int argc, char *argv[]) { char **myargv; char delim[] = " \t"; pid_t childpid, waitreturn; int status; if (argc != 2) { fprintf(stderr, "Usage: %s string\n", argv[0]); exit(1); } if ((childpid = fork()) == -1) { perror("The fork failed"); exit(1); } else if (childpid == 0) { /* child code */ if (makeargv(argv[1], delim, &myargv) < 0) { fprintf(stderr, "Argument array could not be constructed\n"); exit(1); } else if (execvp(myargv[0], &myargv[0]) < 0) { perror("The exec of command failed"); exit(1); } } else /* parent code */ while(childpid != (waitreturn = wait(&status))) if ((waitreturn == -1) && (errno != EINTR)) break; exit(0); }

Attributes Preserved by Calls to execAttribute Relevant System Call

Process ID

Parent process ID

Process group ID

Session membership

Real user ID

Real group ID

Supplementary group IDs

Time left on alarm signal

Current working directory

Root directory

File mode creation mask

Process signal mask

Pending signals

Time elapsed

getpid()

getppid()

getpgid()

getsid()

getuid()

getgid()

getgroups()

alarm()

getcwd()

unmask()

sigprocmask()

sigpending()

times()

Daemon

A background process that runs indefinitely.

Examples:

• Solaris 2 pageout daemon

• Mailer daemon

Background Processes/* Program 2.9 */#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int makeargv(char *s, char *delimiters, char ***argvp);void main(int argc, char *argv[]) { char **myargv; char delim[] = " \t"; pid_t childpid; if (argc != 2) { fprintf(stderr, "Usage: %s string\n", argv[0]); exit(1); } if ((childpid = fork()) == -1) { perror("The fork failed"); exit(1); } else if (childpid == 0) { /* child becomes a background process */ if (setsid() == -1) perror("Could not become a session leader"); else if (makeargv(argv[1], delim, &myargv) < 0) fprintf(stderr, "Argument array could not be constructed\n"); else if (execvp(myargv[0], &myargv[0]) < 0) perror("The exec of command failed"); exit(1); } /* child should never return */ exit(0); } /* parent exits */

Biff

• Biff’s inventor had a dog that barked at mail carriers.

• Sends a ctrl-g (ASCII 7) to standard error.

• If there is mail:– The open succeeds.– Printing ASCII 7 causes a beep.

Biff

Environment List

• Array of pointers to strings of the form name = value.

• Name specifies an environment variable

• Value specifies a string of values.

Environment VariablesVariable Meaning

HOME

LANG

LC_ALL

LC-COLLATE

LC_CTYPE

LC_MONETARY

LC_NUMERIC

LC_TIME

LOGNAME

PATH

TERM

TZ

User’s initial working directory

Locale when not specified by LC_ALL or LC_*

Overriding name of locale

Name of locale for collating information

Name of locale for character classification

Name of locale for monetary editing

Name of locale for numeric editing

Name of locale for date/time information

Login name associated with a process

Path prefixes for finding the executable

Terminal type for output

Time zone information

Environment Variables (cont)

• In execl, execlp, execv, execvp child inherits environment parent has just prior to execution of exec.

• In execle and execve, child sets its own environment.

Environment Variables (cont)

• environ

• getenv

• env

Process Termination

Normal or abnormal.

• Cancel pending timers and signals

• Release virtual memory resources

• Release other process-held system resources such as locks

• Close open files

Zombies

• If a parent process is not waiting for a child when it finishes, the child cannot be terminated by its parent. We call these child processes zombies.

• Orphaned child processes become zombies when they terminate.

• System init process (process whose ID is 1) gets rid of orphaned zombies.

Normal Termination

• Return from main.

• Call to C function exit

• Call to _exit system call.

(note that C function exit calls user-defined exit handlers that usually provides extra cleanup before calling on _exit).

exit and _exit

• Take an integer parameter status that indicates the status of the program.

• 0 normal termination.

• Programmer defined non-zero indicates error.

• At exit C function installs user-defined exit handler. Last-installed, first executed.

Abnormal Termination

• Call abort.

• Process a signal that causes termination.

Critical Sections

• Interleaved printing.

• Multi-process to shared memory where at least one process is writing.