Operating
This presentation is the property of its rightful owner.
Sponsored Links
1 / 60

operating systems PowerPoint PPT Presentation


  • 81 Views
  • Uploaded on
  • Presentation posted in: General

operating systems. Processes in Unix. The Process ID. operating systems. Unix identifies each process with a unique integer called a process ID . The process that executes the request for creating a process is called the parent of the process.

Download Presentation

operating systems

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Operating systems

operating

systems

Processes in Unix


Operating systems

The Process ID

operating

systems

Unix identifies each process with a unique integer

called a process ID.

The process that executes the request for creating

a process is called the parent of the process.

The created process is called the child process.


Operating systems

operating

systems

Getting the Process ID

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main ( )

{

printf(“Process ID: %ld\n”, (long)getpid());

printf(“Parent process ID: %ld\n”, (long)getppid());

printf(“Process owner ID: %ld\n”, (long)getuid());

exit (0);

}

ex1.c


Operating systems

operating

systems

Process Termination

  • Normal Termination

    • return from main

    • calling exit

    • calling _exit

  • Abnormal Termination

    • calling abort

    • terminated by a signal

calls exit

cleans up, closes all files

leaves files open, does not flush buffers


Operating systems

operating

systems

The atexit function

ANSI C allows us to register up to 32 functions that are

automatically called by exit( ).

int atexit (void (*func) (void));


Operating systems

User Process

exit

handler

_exit

user

functions

call & return

return

call

call & return

exit

handler

exit( )

main( )

_exit

call & return

return

call

C start-up

routine

I/O

cleanup

_exit

exec

Kernel


Operating systems

operating

systems

More Process Termination

When a process terminates, the operating system

de-allocates the resources held by the process, and

notifies other processes of its demise.

When a process exits, its orphaned children are adopted

by the init*process. If it’s parent process is not waiting

for it when it terminates, it becomes a zombie process.

* launchd on OS-X (do ps –ax)


Operating systems

operating

systems

Process Creation Using fork( )

makes a copy of the parent’s system image and

begins executing at the currentinstruction

child process gets a copy of the parent’s data

space, heap and stack. They do not share memory!

The fork() call returns 0 to the child process, and

the pid of the child to the parent process.

Whether the parent or the child executes first,

once the child is created, depends upon the scheduling

algorithm used by the kernel.


Operating systems

operating

systems

*

Children Also Inherit

user and group IDs

controlling terminal

current working directory

root directory

file mode creation masks

all open file descriptors

signal mask and dispositions

environment

attached shared memory segments

resource limits

* Keep in mind that the child process does not share

these, but has copies of its own that it inherits from

the parent.


Operating systems

operating

systems

Children Are Different Because …

They return a different value from fork

They have different process IDs

They have different parent process IDs

The child does not inherit file locks set by the parent

The set of pending signals for the child is set to

the empty set


Operating systems

Try the following code

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

x = 0;

fork( );

x = 1;

printf(“I am process %ld and my x value is %d\n”,

(long)getpid( ), x);

return 0;

}

What happened?

fork.c


Operating systems

Try the following code

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

x = 0;

fork( );

x = 1;

printf(“I am process %ld and my x value is %d\n”,

(long)getpid( ), x);

return 0;

}

At this point, there is one process.


Operating systems

Try the following code

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

x = 0;

fork( );

x = 1;

printf(“I am process %ld and my x value is %d\n”,

(long)getpid( ), x);

return 0;

}

A child process is created. It has the identical

code and execution environment as the parent.

fork.c


Operating systems

Try the following code

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

x = 0;

fork( );

x = 1;

printf(“I am process %ld and my x value is %d\n”,

(long)getpid( ), x);

return 0;

}

Both processes now execute this code, changing its own

value of x, printing it, and exiting. The order depends

on the scheduler.


Operating systems

Try the following code

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

x = 0;

fork( );

x = 1;

printf(“I am process %ld and my x value is %d\n”,

(long)getpid( ), x);

return 0;

}

Could the child process do something different from

the parent process?


Operating systems

Yes ... test the return value of the fork( )

#include <stdio.h>

#include <unistd.h>

int main ( )

{

int x;

pid_t childpid;

x = 0;

childpid = fork( );

if ( childpid == -1)

{

perror(“failed to fork a new process”);

return 1;

}

fork1.c


Operating systems

if (childpid == 0)

{

x = 1;

printf(“I am the child, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

else

{

x = 2;

printf(“I am the parent, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

return 0;

}

What happened?


Operating systems

Both processes return here from

the fork( ) call. However, the return

value to the parent is the pid of the

child process. The return value to

the child is zero.

if (childpid == 0)

{

x = 1;

printf(“I am the child, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

else

{

x = 2;

printf(“I am the parent, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

return 0;

}


Operating systems

if (childpid == 0)

{

x = 1;

printf(“I am the child, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

else

{

x = 2;

printf(“I am the parent, my ID = %ld, my x = &d\n”,

(long)getpid( ), x);

}

return 0;

}

The child process

executes this block,

And ...

the parent process

executes this block


Operating systems

operating

systems

What does this code do?

int main(int argc, char *argv[ ] )

{

pid_t childpid = 0;

int i, n;

n = atoi ( argv[1] );

for ( i = 1; i < n; i++)

if (childpid = fork( ) )

break;

fprintf(stderr, “i:%d process ID:%ld parent ID: %ld child ID %ld\n”,

i, (long)getpid( ), (long)getppid( ), (long)childpid );

return 0;


Operating systems

Creates a Chain of Processes

operating

systems

int main(int argc, char *argv[ ] )

{

pid_t childpid = 0;

int i, n;

n = atoi ( argv[1] );

for ( i = 1; i < n; i++)

if (childpid = fork( ) )

break;

fprintf(stderr, “i:%d process ID:%ld parent ID: %ld child ID %ld\n”,

i, (long)getpid( ), (long)getppid( ), (long)childpid );

return 0;

process 1

process 2

// non zero means I’m the parent

process 3

the parent breaks

out of the loop …

the child continues

through the loop one

more time, forks a new

child process and becomes

the parent for the next

iteration.

process 4

a chain

for n = 4

chain.c


Operating systems

Creating a fan of processes

operating

systems

int main(int argc, char *argv[ ] )

{

pid_t childpid = 0;

int i, n;

n = atoi ( argv[1] );

for ( i = 1; i < n; i++)

if (childpid = fork( ) <= 0 )

break;

fprintf(stderr, “i:%d process ID:%ld parent ID: %ld child ID %ld\n”,

i, (long)getpid( ), (long)getppid( ), (long)childpid );

return 0;

parent

process

child 3

child 1

child 2

the child breaks

out of the loop …

the parent continues

through the loop creating

a new child. This continues

until the loop condition

is satisfied.


Operating systems

Run the example fan1.c a few times.

What do you notice about the output?

The order of the output is not in the order expected.

This is because the parent just exits when it is done,

the children may not have finished at this point. The

order of execution depends upon how the processes

were scheduled to run. Can we make the parent wait

to exit until all of its children have finished?


Operating systems

operating

systems

The wait( ) System Call

  • When a fork ( ) occurs, both the parent and the child proceed

  • with execution at the point of the fork.

  • If the parent wants to wait for the child to finish before

  • continuing, it executes a wait( ). wait() causes the caller to

  • stop until

    • the child terminates, or

    • the caller receives a signal

  • wait( ) returns immediately if there are no children executing

  • the return value of wait() is:

    • the pid of the terminating child process, or

    • -1 if there is no child to wait for or a signal occurred

      • errno = ECHILD indicates there was no child

      • errno = EINTR indicates there was a signal


Operating systems

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait (int *status);

operating

systems

returns -1 or pid of the

terminating child.

the return status of the child is

stored in status. Test with the macros

WIFEXITED - true if child terminated normally

WIFSIGNALED – true if child terminated abnormally

because it failed to catch a signal

WIFSTOPPED - true if a child is currently stopped


Operating systems

operating

systems

Handling a wait that is interrupted by a signal

#include <errno.h>

#include <sys/wait.h>

pid_t r_wait (int* status_loc)

{

int retval;

while ( ( (retval = wait(status_loc) ) == -1 && (errno == EINTR) );

return retval;

}

if the wait returns because of a signal, stay in this loop


Operating systems

Fixing the fan program . . .

n = atoi(argv[1]);

for (i = 1; i < n; i++)

if ( (childpid = fork( ) ) <= 0)

break;

while (r_wait(NULL) > 0);

fprintf(stderr, ... )

see fan2.c


Operating systems

Fixing the fan program . . .

n = atoi(argv[1]);

for (i = 1; i < n; i++)

if ( (childpid = fork( ) ) <= 0)

break;

while (r_wait(NULL) > 0);

fprintf(stderr, ... )

what happens if you replace the while statement with

r_wait(NULL);

see fan2.c


Operating systems

How many outputs are possible from this program?

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}


Operating systems

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}

1. The fork fails, the program will output

“failed to fork”


Operating systems

child code

parent code

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}

2. The child prints its message, but then

the parent catches a signal before the

child actually returns.

I am a child 3427

a signal may have interrupted this call


Operating systems

child code

parent code

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}

3. The child prints its message and returns.

The wait returns normally

I am a child 3427

I am a parent 3424


Operating systems

child code

parent code

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}

4. The parent catches a signal and prints

its “signal” message before the child

prints its message.

A signal may have interrupted the call

I am child 3427


Operating systems

child code

parent code

int main ( )

{

pid_t childpid;

childpid = fork( );

if (childpid == -1) {

perror(“failed to fork”);

return 1;

}

if (childpid == 0)

fprintf(stderr, I am a child %ld\n”, (long)getpid( ) );

else if (wait(NULL) != childpid)

fprintf(stderr, “A signal may have interrupted the wait\n”);

else

fprintf(stderr, I am a parent %ld\n”, (long)getpid( ) );

return 0;

}

5. The parent catches a signal before the

child prints its message, but it prints

its “signal” message after the child prints.

I am child 3427

A signal may have interrupted this call


Operating systems

Status Values

The status parameter of the wait( ) system call is an int*

If it is not NULL, the return status of the child is stored

in the integer variable pointed to. The child status is

returned by

return n

exit (n)

A zero value indicates that the child process exited normally.


Operating systems

Keep in mind that the wait( ) system call blocks

if there are any child processes executing. What

if we want to see if a child process has terminated,

but not block?


Operating systems

operating

systems

waitpid

pid_t waitpid (pid_t pid, int *stat_loc, int options);

the process to be waited for, or

-1 if you want to wait for any child

process to finish.

the interesting option is

WNOHANG which causes

waitpid to return even if there

is there is no child for which

status is available.

returns the pid of the child

or -1 if there is an error,

or 0 if there are children to be waited for,

but none of them are done


Operating systems

operating

systems

#include <sys/types>

#include <sys/wait.h>

#include <errno.h>

int status;

pid_t waited_for_pid;

while (waited_for_pid = waitpid (-1, &status, WNOHANG) )

if ((waited_for_pid == -1) && (errno != EINTR)

break;

this code segment waits for any child, without blocking,

if there are no children with status available. It stays in the

loop if the waitpid is interrupted by a signal.


Operating systems

Waiting for a Parent to Finish

operating

systems

A parent can wait for a child to finish by using the wait

or waitpid calls.

However, what does a child do when it wants to wait for

the parent to finish?

while (getppid( ) != 1)

sleep(1);

why?

this type of code is called polling, and burns up cpu time

To avoid race conditions and polling, we use signals


Operating systems

operating

systems

Zombies

If a child process completes before its parent does,

some vestige of the process has to hang around so

that the parent can determine its termination status

with a wait( ).

This is called a zombie process.


Operating systems

operating

systems

Orphans

What happens if the parent process exits before its

child process does. The child has to have a parent, so

it is adopted by the init process.


Operating systems

operating

systems

Forks Are Used

When a process wants to duplicate itself so that the

parent and the child can execute different parts of the

program simultaneously. This is common for server

software.

When a process wants to execute a different program.

This is common for shells.


Operating systems

operating

systems

exec( )

fork ( ) – creates a copy of the calling process.

exec ( ) – overlays the calling process with a new process.

Traditional approach is for the parent to fork( ) a new

process, which then does an exec to overlay the process

with the new program. The parent then stays around.

The exec copies a new executable into the process image.

The program text, variables, stack, and the heap are

overwritten.


Operating systems

Process B

program A

fork( );

rhtj,nn vio nlk;jh eahg

jkfsdajhfk.ADFSkfdnkZX

dfjklA:LDhlADjlkd

fakJLc

dsakl;naS

hlhkasf

jghji

fhnjkjsdf

fdsnjhkjsd

fht9

hjfhksa

}

jkds,n,ds

mkfl

jmhjsd fhjsdf

‘jkfg {

kjl;sdfdsf

fdsjklsdf

rhtj,nn vio nlk;jh eahg

jkfsdajhfk.ADFSkfdnkZX

dfjklA:LDhlADjlkd

fakJLc

dsakl;naS

fork( );

{

exec( );

‘ fdsnjhkjsd

}

hjfhksa

}

jkds,n,ds

mkfl

jmhjsd fhjsdf

‘jkfg {

kjl;sdfdsf

fdsjklsdf

exec( )

Process A

program A

rhtj,nn vio nlk;jh eahg

jkfsdajhfk.ADFSkfdnkZX

dfjklA:LDhlADjlkd

fakJLc

dsakl;naS

fork( )

{

exec( )

‘ fdsnjhkjsd

}

hjfhksa

}

jkds,n,ds

mkfl

jmhjsd fhjsdf

‘jkfg {

kjl;sdfdsf

fdsjklsdf

program C


Operating systems

operating

systems

execl( )

This family of functions is useful when the number of

command line arguments is known at compile time

first command

line argument

second command

line argument

#include <unistd.h>

int execl(const char *path, const char *arg0, const char *arg1, …

const char *argn, NULL);

A NULL

pointer

final command

line argument

path to the

executable


Operating systems

Example

int main ( )

{

pid_t childpid;

int stat;

if ((childpid = fork() == -1)

{

perror(“Error in fork.”);

exit(1);

}

else if (childpid == 0)

{

if (execl(“/bin/ls”, “ls”, “-l”, NULL) < 0)

{

perror(“Error in exec.”);

exit(1);

}

}

else if (childpid != wait(&stat))

{

perror(“A Signal occurred before the child exited.”);

exit(1);

}

return (0);

}

operating

systems

This is child code. It replaces

the current process with /bin/ls

This is parent

code.

dols.c


Operating systems

operating

systems

Variations of execl( )

#include <unistd.h>

int execlp(const char *file, const char *arg0,

const char *arg1, … , const char *argn, NULL);

int execle (const char *path, const char *arg0,

const char *arg1, …, const char argn, NULL,

char *const envp[]);

This variation uses the PATH environment

variable to locate the executable

This variation passes a pointer to

an array of strings that holds a new

environment for the command.


Operating systems

execv( )

operating

systems

This family of functions is used to pass command

line arguments to the new process

#include <unistd.h>

int execv(const char *path, char *const argv[]);

an argument array, just as

if these had come from the

command line . You have to

build this!

path to the

executable

execv also has execvp and execve variations.


Operating systems

create the executable myexec.

Then typing myexec ls –l will

result in this function calling ls -l

int main (int argc, char *argv[]){ pid_t childpid; int status; if ((childpid = fork()) == -1) { perror("The fork failed"); exit(1); } else if (childpid == 0) { if (execvp(argv[1], &argv[1]) <0) { perror("The exec failed"); exit(1); } } else { while(childpid != wait(&status)) { if ((childpid == -1) && (errno != EINTR)) break; } } return (0);}

operating

systems

argv[0] is the first argument

when this command is executed,

so &argv[1] points to the two

tokens ls and -l

execvp constructs the

pathname using the

PATH environment variable.

the parent waits for the child

to terminate.


Operating systems

operating

systems

A Shell

is a command interpreter which prompts for commands,

reads the commands from standard input, forks children

to execute the commands, and waits for the children to

finish.

When you end a command with &, the shell creates the

child process, but does not wait for it to finish. The child

is known as a background process.


Operating systems

operating

systems

A daemon

a background process that runs indefinitely.


Operating systems

operating

systems

Terminal Log-ins

/etc/ttys contains one line per terminal device

when the system is bootstrapped, the kernel creates

process 1, the init process

*

init reads /etc/ttys and for each terminal device in the file,

it forks a new process and execs the getty program

* launchd on OS-X (do ps –ax)


Operating systems

operating

systems

init

fork (once per terminal)

init

init

init

. . .

exec

exec

exec

getty

getty

getty


Operating systems

operating

systems

getty opens a terminal device and issues a login message

When a user name is entered, getty execs login

login gets the password and checks to see if all is well

If it is, login changes to the user’s home directory,

changes ownership of the terminal, initializes the

environment, and execs the shell specified for the user.


Operating systems

init

operating

systems

fork

init

exec

getty

exec

login

exec

shell


Process groups

operating

systems

In addition to having a process ID, each process belongs to

a process group. A process group is a collection of one

or more processes.

Process Groups

Session

A session is a collection of one or more process groups.


An example using redirection

operating

systems

An Example using redirection

This program exploits the fact that open file

descriptors are preserved across fork and

exec calls.


Operating systems

upper

#include <stdio.h>

#include <ctype.h>

int main( )

{

int ch;

while ((ch = getchar( ) ) != EOF)

{

putchar(toupper(ch));

}

exit(0);

}

operating

systems

This program is written as a filter. It reads in text and converts

it to upper case.

upper.c


Operating systems

operating

systems

What if we want to invoke this filter

from inside of a program?


Operating systems

#include <unistd.h>

#include <stdio.h>

int main ( int argc, char *argv[])

{

char *filename;

filename = argv[1];

// now call freopen to open the file on standard input

if (!freopen(filename, "r", stdin))

{

printf("Could not re-direct file to stdin\n");

exit(1);

}

// now exec the upper program

execl( "./upper", "upper", 0);

// since the exec replaces the current program, the following

// lines are not executed unless the exec fails.

perror("could not exec ./upper");

exit(3);

}

Closes the file descriptor for stdin

Then re-opens the file as stdin

execupper.c


  • Login