33
1 Tutorial: CSI 3310 Dewan Tanvir Ahmed SITE, UofO

Tutorial: CSI 3310

  • Upload
    mercury

  • View
    78

  • Download
    1

Embed Size (px)

DESCRIPTION

Tutorial: CSI 3310. Dewan Tanvir Ahmed SITE, UofO. Today’s Objective. Go through the last lab Play with exec() fork() Dup2 pipe. Process. A process in Unix terms is an instance of an executing program. - PowerPoint PPT Presentation

Citation preview

Page 1: Tutorial: CSI 3310

1

Tutorial: CSI 3310

Dewan Tanvir AhmedSITE, UofO

Page 2: Tutorial: CSI 3310

2

Today’s Objective

Go through the last lab Play with

exec() fork() Dup2 pipe

Page 3: Tutorial: CSI 3310

3

Process1. A process in Unix terms is an instance of an executing program. 2. Each process incorporates program code, the data values within

program variables, and values held in hardware registers, program stack etc.

3. Associated with each process is a process control block (PCB) which stores all the information related to the process.

1. fork .... Creates a new process.2. exec .... Overlays the memory space of the process with a new program.3. wait .... synchronizes processes.4. exit .... Terminates a process

Page 4: Tutorial: CSI 3310

4

fork()• fork() creates a new child process• Points to note

– the OS copies the current program into the new process, – resets the program pointer to the start of the new program (child fork

location), and – both processes continue execution independently as two separate

processes• The child gets its own copy of the parent’s:

– data segments– heap segment– stack segment– file descriptors

Page 5: Tutorial: CSI 3310

5

fork() Return Values

• fork() is the one Unix function that is called once but returns twice!!:

• If fork() returns 0:– you’re in the new child process

• If fork() returns > 1 (i.e., the pid of the new child process)– you’re back in the parent process

Page 6: Tutorial: CSI 3310

6

fork()

Page 7: Tutorial: CSI 3310

7

Waiting on Our Children• Unlike life, parents should always hang around for their children’s

lives (runtimes) to end, that is to say:– Parent processes should always wait for their child processes to end

• When a child process dies, a SIGCHLD signal is sent to the parent as notification

• The SIGCHLD signal’s default disposition is to ignore the signal

• A parent can find out the exit status of a child process by calling one of the wait() functions

Page 8: Tutorial: CSI 3310

8

Problem Children:Orphans and Zombies

• If a child process exits before it’s parent has called wait(), it would be inefficient to keep the entire child process around, since all the parent is going to want to know about is the exit status:– A zombie is a child process that has exited before it’s parent’s has

called wait() for the child’s exit status

– A zombie holds nothing but the child’s exit status (held in the program control block)

– Modern Unix systems have init (pid == 1) adopt zombies after their parents die, so that zombies do not hang around forever as they used to, in case the parent never did get around to calling wait

Page 9: Tutorial: CSI 3310

9

Points to note#include <sys/types.h> #include <unistd.h>#include <stdio.h> int main(void){

pid_t fork_pid; FILE *my_file; my_file=fopen("MY_FORK_FILE.txt","w"); fprintf(my_file," Hello from main \n"); fork_pid=fork(); fprintf(my_file," After fork %d\n",fork_pid); return 0;

}

#include <sys/types.h> #include <unistd.h>#include <stdio.h> int main(void){

pid_t fork_pid; FILE *my_file; my_file=fopen("MY_FORK_FILE.txt","w"); fprintf(my_file," Hello from main \n"); fork_pid=fork(); fprintf(my_file," After fork %d\n",fork_pid); return 0;

}

Hello from main After fork 0 Hello from main After fork 14818

Hello from main After fork 0 Hello from main After fork 14818

The first thing you should note is that the output from the child process appears in the same file as the parent process.

One characteristic of fork is that all file descriptors that are open in the parent are duplicated in the child.

Page 10: Tutorial: CSI 3310

10

Exec• The only way in which

– a program is executed in Unix is for an existing program to issue an exec system call.

– The exec calls overlays the memory space of the calling process with a new program.

– When used together, fork and exec provides the means for the programmer to start another program, yielding multitasking.

Page 11: Tutorial: CSI 3310

11

Exec()..

Page 12: Tutorial: CSI 3310

12

The exec() Functions:Out with the old, in with the new

• The exec() functions all replace the current program running within the process with another program

• There are two families of exec() functions, – the “l” family (list), and – the “v” family (vector)

• What is the return value of an exec() call?

Page 13: Tutorial: CSI 3310

13

The execl... functions• int execl(const char * path, const char * arg0, ...);

– executes the command at path, – passing it the environment as a list: arg0 ... argn

– thus, the execl family breaks down argv into its individual constituents, and then passes them as a list to the execl?

• int execlp(const char * path, const char * arg0, ...);– same as execl, but – uses $PATH resolution for locating the program in path, thus

an absolute pathname is not necessary

• int execle(const char * path, const char * arg0, ... char * envp[]);– allows you to specifically set the new program’s environment,

which replaces the default current program’s environment

Page 14: Tutorial: CSI 3310

14

The execv... functions• int execv(const char * path, char *const argv[]);

– executes the command at path, – passing it the environment contained in a single argv[] vector

• int execvp(const char * path, char *const argv[]); – same as execv, – but uses $PATH resolution for locating the program in path

• int execve(const char * path, char *const argv[], char * const envp[]); – note that this is the only system call of the lot

Page 15: Tutorial: CSI 3310

15

File Descriptor• Contains

– reference to system file structure

• Denoted by small integer– passed to system calls to specify which process-to-file connection

should be affected• Created by open( ), dup( ), dup2( ), pipe( ), socket( )• Removed by close( )• Duplicated by fork()• Retained across exec() (unless FD_CLOEXEC)

Page 16: Tutorial: CSI 3310

16

Standard File Descriptors• Each process normally has file descriptors for standard input,

standard output, standard error• Denoted by

– STDIN_FILENO– STDOUT_FILENO– STDERR_FILENO

• Older programs use 0, 1, 2• Provide unbuffered access to data in files via

– read( ), write( ), lseek( )

• Buffered FILE structures stdin (scanf), stdout (printf), stderr are layered on unbuffered files

Page 17: Tutorial: CSI 3310

17

Inter Process Communication (IPC)

• For processes to cooperate in performing a task, they need to share data.

• The fundamentals of network programming lies in processes' ability to share data among themselves.

• Unix allows concurrent processes to communicate by using a variety of IPC methods– Signals– message queues– shared memory– semaphores and – sockets.

Page 18: Tutorial: CSI 3310

18

Pipe• Pipe is called with a two integer array• hold the file descriptors associated with the pipe

– the first element in the array (p[0]) opens the pipe for reading – while the other file descriptor (p[1]) opens the pipe for writing.

• Once created we can use pipes to communicate with the process itself or with any child process.

Page 19: Tutorial: CSI 3310

19

Concept…Stage 1

The original process A (the shell for example) creates a pipe, receiving

descriptors on each end.

Stage 2Process A forks twice, creating child

processes B and C. The children inherit the parent's open descriptors,

including those on the two ends of the pipe, so at this stage, all three

processes have descriptors on both ends of the pipe.

Page 20: Tutorial: CSI 3310

20

Concept…

Stage 3Each process closes the descriptors it

doesn't need. B closes the downstream end, C closes the

upstream end, and A closes both. Note that B and C inherit their own copies of A's descriptors, so that closing a descriptor in the parent

doesn't affect the child's descriptors.

Page 21: Tutorial: CSI 3310

21

Concept…

Stage 4Processes B and C exec() the

programs they need to run. Again, the descriptors remain intact across the exec() call. B can then write to the

upstream end of the pipe, and C can read from the downstream end.

Inter Process communication!!!

Page 22: Tutorial: CSI 3310

22

Pipe• Note: A buffer is a system maintained data structure accessible to

both ends of the pipe.• The writer writes on to the buffer while the reader reads from it.

• How do we access the pipe?– Obviously the array is not going to exist after the exec(), so how do

we access the pipe?– Before the exec(), we have to reassign the standard output of the

process to the pipe.– We can do this using a system call to duplicate file descriptors called

“dup2()”

Page 23: Tutorial: CSI 3310

23

dup2()

• dup2(target, new)• The file descriptor new will point to the same file as target after

the call.• If our target is the standard output stream of the process, then

we will redirect the standard output to the pipe.• The standard output will survive the exec() call.

Page 24: Tutorial: CSI 3310

24

close()• The close() system call is used to close pipes and files.• We need to close() the open pipes in the child process before

we exec() the new process.• If not, the open pipes may be destroyed by the exec() call, also

destroying our newly created connection.

Page 25: Tutorial: CSI 3310

25

int main(int argc, char *argv[]) { pid = fork(); if (pid == 0) { fd = open("temp", O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); dup2(fd, STDOUT_FILENO); if (execl(“/bin/ls”, “ls”, NULL) == -1) perror("execl"); } else { close(fd); wait(&status); }}

Create a subprocess from program “ls”; redirect standard output of “ls” into file named “temp”

Unix shell notation: $ ls > temp

Example: ls > temp

Page 26: Tutorial: CSI 3310

26

Example – Execl/Execlp

#include <unistd.h>#include <stdio.h>int main(void){ int status; if (fork()){ // Parent: Do you know why? } else { // Child printf(" HELLO from Child \n"); status=execl("/bin/ls","ls","-l","-t",'\0'); if (status != 0)perror("execl error:"); } return 0;}

Page 27: Tutorial: CSI 3310

27

Output HELLO from Child {ncitl0}dahmed(61)$ total 664-rwx------ 1 dahmed grad 5082 May 15 17:37 a.out-rw-r--r-- 1 dahmed grad 352 May 15 17:37 exels.c-rw-r--r-- 1 dahmed grad 528 May 15 17:06 pipe.c-rwx------ 1 dahmed grad 6371 May 15 17:01 mymon-rw-r--r-- 1 dahmed grad 1938 May 15 17:01 mymon.c-rw------- 1 dahmed grad 289 May 15 16:08 sat.c-rw-r--r-- 1 dahmed grad 478 May 15 16:07 redir.c-rw------- 1 dahmed grad 75 May 15 15:28 exeSleep.c-rwx------ 1 dahmed grad 4831 May 15 15:12 sat-rwx------ 1 dahmed grad 5779 May 15 14:00 pt-rw-r--r-- 1 dahmed grad 561 May 15 14:00 pt.c-rwx------ 1 dahmed grad 6272 May 15 12:27 procmon-rw-r--r-- 1 dahmed grad 2379 May 15 05:15 procmon.cdrwx------ 3 dahmed grad 512 May 15 04:50 lab1-rw------- 1 dahmed grad 521096 May 14 11:12 Trash-rw-r--r-- 1 dahmed grad 61440 May 9 14:17 lab1.tardrwxr-xr-x 18 dahmed grad 1024 May 8 16:43 public_htmldrwx------ 2 dahmed grad 512 Apr 29 21:44 Maildrwxr-xr-x 2 dahmed grad 512 Aug 23 2005 pinedrwxr-xr-x 6 dahmed grad 512 Aug 23 2005 sshdrwxr-xr-x 7 dahmed grad 512 Aug 23 2005 netscape-rw-r--r-- 1 dahmed grad 11576 Jan 21 2004 calcloop

Page 28: Tutorial: CSI 3310

28

Question?

• Modify the above code so that it works when "/bin/ls" is replaced with "ls", i.e. which version of exec should you now be using?

status=execlp("ls","ls","-l","-t",'\0');

Page 29: Tutorial: CSI 3310

29

Simple pipe Example…int main(){ int i,j,p[2]; char s[100]; char s2[100]; i=pipe(p);

printf("pipe returned %d %d %d\n",i,p[0],p[1]); for (j=0; j<5; j++){ sprintf(s,"I am a string %d\n",j); i=write(p[1],s,strlen(s)); printf("Write completed i=%d\n",i); i=read(p[0],s2,100); printf("Read from the pipe completed i=%d\n\t%s\

n",i,s2); }}

Page 30: Tutorial: CSI 3310

30

Sample outputpipe returned 0 3 4Write completed i=16Read from the pipe completed i=16 I am a string 0

Write completed i=16Read from the pipe completed i=16 I am a string 1

Write completed i=16Read from the pipe completed i=16 I am a string 2

Write completed i=16Read from the pipe completed i=16 I am a string 3

Write completed i=16Read from the pipe completed i=16 I am a string 4

Page 31: Tutorial: CSI 3310

31

#include <stdio.h>#include <unistd.h>#define MSGSIZE 4096main() { char inbuf[MSGSIZE]; int p[2], j; pid_t pid; if (pipe(p) == -1) { printf("Error opening pipe\n"); exit(1); } switch(pid = fork()) { case -1: perror("Error with the fork()\

n"); exit(2);

Example: dup2 and pipe…case 0: close(p[0]);

dup2(p[1], 1); close(p[1]); execlp("ls", "ls", (char *)0);

break; default:

read(p[0], inbuf, MSGSIZE);

printf("%s", inbuf); close(p[0]); close(p[1]);

}}

Page 32: Tutorial: CSI 3310

32

Pipe drawbacks• Pipes can only be used to connect processes that have a common

ancestry, eliminating the possibility for a true client-server application to exist.

• Pipes cannot be permanent, as they have to be created and destroyed with the process.

Page 33: Tutorial: CSI 3310

33

Thank You!