System Calls: pipes CSRU3130 Ellen Zhang.

Slides:



Advertisements
Similar presentations
Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.
Advertisements

CSCC69: Operating Systems
CSC 501 Lecture 2: Processes. Von Neumann Model Both program and data reside in memory Execution stages in CPU: Fetch instruction Decode instruction Execute.
UNIX Process Control Bach 7 Operating Systems Course Hebrew University Spring 2007.
1 Processes Professor Jennifer Rexford
1 Processes and Pipes COS 217 Professor Jennifer Rexford.
Page 1 Task Control: Signals and Alarms Chapter 7 and 8 B. Ramamurthy.
Exec function Exec function: - replaces the current process (its code, data, stack & heap segments) with a new program - the new program starts executing.
Process Process: the UNIX abstraction of a stand-along computer that manages resources (memory, CPU, I/O resources) comprising a running program. Processes.
1 Tuesday, June 13, Our continuing mission: To seek out knowledge of C, to explore strange UNIX commands, and to boldly code where no one has man.
Signals Hua LiSystems ProgrammingCS2690Signals. Topics: Sending Signals -- kill(), raise() Signal Handling -- signal() sig_talk.c -- complete example.
CS Lecture 16 Outline Inter-process Communication (IPC) – Pipes – Signals Lecture 161CS Operating Systems 1.
Today’s topic Inter-process communication with pipes.
Unix Processes Slides are based upon IBM technical library, Speaking Unix, Part 8: Unix processes Extended System Programming Laboratory (ESPL) CS Department.
Unix Pipes Pipe sets up communication channel between two (related) processes. 37 Two processes connected by a pipe.
Shell (Part 2). Example r What if we want to support something like this: m ps –le | sort r One process should execute ps –le and another should execute.
System Commands and Interprocess Communication. chroot int chroot(const char *path); chroot changes the root directory to that specified in path. This.
Pipes A pipe is a simple, synchronized way of passing information between processes A pipe is a special file/buffer that stores a limited amount of data.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 8: Opening Files and Starting Processes.
CS162B: Pipes Jacob T. Chan. Pipes  These allow output of one process to be the input of another process  One of the oldest and most basic forms of.
ITEC 502 컴퓨터 시스템 및 실습 Chapter 2-1: Process Mi-Jung Choi DPNM Lab. Dept. of CSE, POSTECH.
Agenda  Working with Processes: Purpose Running Programs within same process (execl, execlp, execle, execv, execvp, execve) “Spawning” other process (fork,
Scis.regis.edu ● CS 468: Advanced UNIX Class 5 Dr. Jesús Borrego Regis University 1.
IPC Programming. Process Model Processes can be organized into a parent-child hierarchy. Consider the following example code: /* */
Concurrent Processes Processes can concurrently run same program. Processes can concurrently run same program. Processes can start other processes. Processes.
Operating Systems Process Creation
Signals (Chap 10 in the book “Advanced Programming in the UNIX Environment”) Acknowledgement : Prof. Y. Moon at Kangwon Nat’l Univ.
UNIX Signals * POSIX-Defined Signals * Signaling Processes * Signal Mask * sigaction * kill and sigaction * alarm * Interval Timers * POSIX.1b Timers *
Operating Systems Recitation 4, April th, 2002 Signals.
Recitation 11 (Nov. 22) Outline Lab 6: interposition test Error handling I/O practice problem Reminders Lab 6: Due Tuesday Minglong Shao
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Tarek Abdelzaher Vikram Adve CS241 Systems Programming System Calls and I/O.
S -1 Processes. S -2 wait and waitpid (11.2) Recall from a previous slide: pid_t wait( int *status ) wait() can: (a) block; (b) return with status; (c)
The Process CIS 370, Fall 2009 CIS UMassD. The notion of a process In UNIX a process is an instance of a program in execution A job or a task Each process.
Dsh: A Devil Shell COMPSCI210 Recitation 14 Sep 2012 Vamsi Thummala.
CS241 Systems Programming Discussion Section Week 2 Original slides by: Stephen Kloder.
CS241 Systems Programming Discussion Section Week 2 Original slides by: Stephen Kloder.
Process Related System Calls By Neha Hulkoti & Kavya Bhat.
The Shell What does a shell do? - execute commands, programs - but how? For built in commands run some code to do the command For other commands find program.
Process Manipulation. Process Manipulation in UNIX Basic process manipulation: creation, program loading, exiting, … fork(), exec(), wait(), exit() Process.
Error handling I/O Man pages
Lecture 5 Systems Programming: Unix Processes: Orphans and Zombies
Recitation 7 – 3/18/02 Outline fork and scheduling Signals
G.Jyostna.
Week 3 Redirection, Pipes, and Background
Precept 14 : Ish dup() & Signal Handling
Task Control: Signals and Alarms Chapter 7 and 8
Protection of System Resources
Unix Process Management
OS – Process Creation and Destruction
UNIX PROCESSES.
CS 3733 Operating Systems Topics: IPC and Unix Special Files
Threads and Cooperation
More on UART Interrupts; System Calls
Pipes A pipe provides a one-way flow of data example: who | sort| lpr
OPERATING SYSTEMS DESIGN AND IMPLEMENTATION Third Edition ANDREW S
Chapter 14 - Advanced C Topics
תרגול 8 – ק/פ ותקשורת תהליכים ב-Linux
System Structure and Process Model
Inter-Process Communication
Operating Systems Lecture 12.
2/25/08 Frans Kaashoek MIT OS abstractions 2/25/08 Frans Kaashoek MIT
Programming Assignment # 2 – Supplementary Discussion
Process Programming Interface
IPC Prof. Ikjun Yeom TA – Hoyoun
Inter-Process Communication ENCE 360
Task Control: Signals and Alarms Chapter 7 and 8
dup, dup2 An existing file descriptor (filedes) is duplicated
CSE 451: Operating Systems Winter 2007 Module 4 Processes
CSE 451: Operating Systems Spring 2006 Module 4 Processes
System Programming: Process Management
Presentation transcript:

System Calls: pipes CSRU3130 Ellen Zhang

Review: fork() int K; main() { int i; int j; j = 200; K = 300; printf("Before forking: j = %d, K = %d\n", j, K); i = fork(); if (i > 0) { sleep(10); printf("After forking, parent: j = %d, K = %d\n", j, K); } else { j++; K++; printf("After forking, child: j = %d, K = %d\n", j, K); }

… main() { int i; int seekp; int fd; char … main() { int i; int seekp; int fd; char *s1; char s2[1000]; fd = open("tmpfile", O_WRONLY | O_TRUNC | O_CREAT, 0666); s1 = "Before forking\n"; write(fd, s1, strlen(s1)); i = fork(); if (i > 0) { sleep(10); /* Delay the parent by ten seconds */ s1 = "Parent"; } else { s1 = "Child"; seekp = lseek(fd, 0, SEEK_CUR); sprintf(s2, "%s: After forking: Seek pointer = %d\n", s1, seekp); write(fd, s2, strlen(s2)); [zhang@storm Demo]$ ./a.out [zhang@storm Demo]$ more tmpfile Before forking Child: After forking: Seek pointer = 15 Parent: After forking: Seek pointer = 55

Signals Mechanism for OS to notify processes of special events such as Timer expire User type Ctrl-C on the controlling terminal Owner kill the process … Signals cause process to suspend its usual execution to run a signal handling procedure Similar to hardware interrupt

Signals (cont’d) A signal is an interruption of program when you hit CNTL-C, SIGINT signal is sent to your program. When you hit CNTL-\, SIGQUIT signal is sent to your program. When you generate a segmentation violation, that sends the SIGSEGV signal to your program. Command “kill” can be used to send a signal to a process kill -9 [process_id] By default, there are certain actions that take place. When you hit CNTL-C, program usually exits. When you hit CNTL-\ or get a segmentation violation, your program dumps core and then exits (default action for SIGQUIT and SIGSEGV)

Example of signals Signal Value Action Comment SIGHUP 1 Term Hangup detected on controlling terminal or death of controlling process SIGINT 2 Term Interrupt from keyboard SIGQUIT 3 Core Quit from keyboard SIGILL 4 Core Illegal Instruction SIGABRT 6 Core Abort signal from abort(3) SIGFPE 8 Core Floating point exception SIGKILL 9 Term Kill signal SIGSEGV 11 Core Invalid memory reference SIGPIPE 13 Term Broken pipe: write to pipe with no readers

Register signal handler #include < signal.h > void cntl_c_handler(int dummy) { printf("You just typed cntl-c\n"); signal(SIGINT, cntl_c_handler); } main() { int i, j; for (j = 0; j < 40; j++) { for (i = 0; i < 1000000; i++); Example file: signal.c

Signal as IPC } else { /* parent process */ printf("Hello, "); void parentdone(int signum) {} int main() { int pid; if ((pid = fork())== -1) { perror("fork() failed"); exit(1); } if (pid == 0) { /* child process */ signal(SIGUSR1, parentdone); pause(); /* sleep until a signal is received */ printf("World!\n"); fflush(stdout); } else { /* parent process */ printf("Hello, "); fflush(stdout); kill(pid, SIGUSR1); /* send a signal to the child */ wait(NULL); /* wait the child exit */ } exit(0); } // end of main()

Pipe as inter-process communication method In Unix, all inter-process communication must take place with help of operating system Process is considered as primary unit of isolation: one process cannot crash whole system, instead you get segmentation fault Well, not quite, the forkbomb we saw last class could halt whole system ! Be extremely careful! Pipes are a nice clean IPC method One process write to the pipe, one process read from it

Processes stack Heap Data Text(Code) Process memory layout Per-process opened file table stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 3 rw Operating system Heap Data Text(Code)

Pipe Pipe is a inter-process communication mechanism: Allow parent-child processes to communicate with each other Make pipeline in shell possible (avoid using disk file) Pipes are treated as files You can call read() on the reading end, call write() on writing end, close() it… FIFO: data that are written first into the pipe are read out first Operating system: buffer data to handler faster writer & slower reader… Producer: Write data to writing end Consumer: Read data from reading end

Pipe system call #include <unistd.h> int pipe(int fd[2]); Parameter: an array of two integers. Upon return: the array is filled with two file descriptions: fd[0]: reading end of pipe fd[1]: writing end of pipe Anything that is written on fd[1] can be read from fd[0]. Pipes are treated as files You can use system call read(), write(), close() … on pipes

Simple example #include <stdio.h> main() { int pipefd[2]; int i; char s[1000]; char *s2; if (pipe(pipefd) < 0) { perror("pipe"); exit(1); } s2 = “Hello World!"; write(pipefd[1], s2, strlen(s2)); i = read(pipefd[0], s, 1000); s[i] = '\0'; printf("Read %d bytes from the pipe: '%s'\n", i, s); write() to a reading end of a pipe: asks operating system to hold those bytes in a buffer until some process requests for them by performing a read() on the read end of the pipe.

Visualize pipes stack Heap Data Text(Code) Process memory layout Per-process opened file table stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pipefd[0] pipefd[1] Operating system buffer Heap Data Text(Code) Hello World!

Pipe: inter-process communication main() { int pipefd[2]; int pid, i, line; char s[1000]; if (pipe(pipefd) < 0) { perror("pipe"); exit(1); } pid = fork(); if (pid > 0) { // parent process while(fgets(s, 1000, stdin) != NULL) { write(pipefd[1], s, strlen(s)); close(pipefd[1]); else { //child process i = 0; line = 1; while(read(pipefd[0], s+i, 1) == 1) { if (s[i] == '\n') { s[i] = '\0'; printf("%6d %s\n", line, s); line++; i = 0; } i++; } // end of while loop } // end of else{ } //end of main()

Visualize pipes stack stack Heap Data Text(Code) Heap Data Text(Code) Parent Process Child process Per-process opened file table Per-process opened file table stack stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pipefd[0] pipefd[1] Heap Data Text(Code) Heap Data Text(Code) Operating system buffer Hello World!

stack stack Heap Data Text(Code) Heap Data Text(Code) Let’s try it out: ctrl-d to finish standard input Why the child process lingers ? OS does not know no one is writing to pipe Parent Process Child process Per-process opened file table Per-process opened file table stack stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pipefd[0] pipefd[1] Heap Data Text(Code) Heap Data Text(Code) Operating system buffer Hello World!

while(read(pipefd[0], s+i, 1) == 1) { if (s[i] == '\n') { s[i] = '\0'; main() { int pipefd[2]; int pid; int i, line; char s[1000]; if (pipe(pipefd) < 0) { perror("pipe"); exit(1); } pid = fork(); if (pid > 0) { close(1); close(pipefd[0]); while(fgets(s, 1000, stdin) != NULL) { write(pipefd[1], s, strlen(s)); close(pipefd[1]); else { close(0); close(pipefd[1]); i = 0; line = 1; while(read(pipefd[0], s+i, 1) == 1) { if (s[i] == '\n') { s[i] = '\0'; printf("%6d %s\n", line, s); line++; i = 0; } i++; } //end of while } //end of else } //end of main Sol: close unused ends of the pipe!!

Handling broken pipes When read from a pipe that has no write end, read() returns 0. When write to a pipe that has no read end, a SIGPIPE signal is generated. If signal isn't handled, program exits silently Example: If you execute: UNIX> cat exec1.c | head -5 | tail -1 and you kill the middle process (the head one), the other two will exit automatically

Now: command pipeline In shell, we can build command pipeline How to implement this ? Create a pipe Create two child processes (both children inherit the pipe) Redirect standard output of first child to writing end of pipe Redirect standard input of second child to reading end of pipe First child to run first command, another child to run second command How to redirect standard input/output ?

Redirect standard output To redirect standard output to a different target Open the target (whether a file, or a pipe) which returns a file descriptor, say fd Duplicate the file descriptor, fd, to descriptor 1 (standard output) i.e., let file descriptor 1 pointing to the target Old and new descriptors may be used interchangeably, and they share locks, file position pointers and flags. To duplicate file descriptor: int dup(int oldfd); int dup2(int oldfd, int newfd);   //Prefer to use this one create a copy of file descriptor oldfd, to lowest-numbered unused file descriptor (dup), or makes newfd be copy of oldfd, closing newfd first if necessary.  

Example: pipeline.c if (pipe(pipefd) < 0) { perror("pipe"); exit(1); } //upon successful return, pipefd[0] is reading end, pipefd[1] is writing end pid = fork(); if (pid==0) { ret=dup2 (pipefd[1],1); //close standard output, make 1 pointing to pipefd[1] close (pipefd[1]); //as 1 is pointing to writing end too, we can close pipefd[1] if (ret==-1){ fprintf (stderr,"first child cannot dup\n"); } close(pipefd[0]); //close reading end of pipe execlp("ls","ls",0); //the standard output of ls will be pipefd[1] fprintf (stderr,”failed to execue ls”); } //end of else

Redirect standard input to a file Here is code segment for redirect standard input to a file int fd=open(“file.txt”,O_RDONLY); if (fd<0) … ret=dup2 (fd,0); //close current standard input, make 0 //pointing to the file that fd is pointing to if (ret==-1){ fprintf (stderr,"first child cannot dup\n"); exit(1); } cin >> number >> name; //all subsequent read from standard // input is from the file file.txt

Pipe vs named pipe For two processes to communicate through pipes, they need access to same pipe Only possible if the pipe is created by their common ancestors Named pipe make it possible for two unrelated processes to communicate in a similar way Named-pipe has a name (like other files), process can open the pipe to read or write

Using named pipe Create a named pipe ls –l will show myPipe as mkfifo myPipe ls –l will show myPipe as prw-r--r-- 1 zhang staff 0 2008-04-25 09:30 myPipe In one terminal, type: ls -l > myPipe in another type: cat < myPipe Difference with using file: You can start “cat” command first “ls” process will wait until “cat” pick up the output Remember that “ls” and “cat” program are not aware of the fact that input/output is from/to a named pipe

Named pipes: server #define HALF_DUPLEX "/tmp/halfduplex" #define MAX_BUF_SIZE> 255 int main(int argc, char *argv[]) { int fd, ret_val, count, numread; char buf[MAX_BUF_SIZE]; ret_val = mkfifo(HALF_DUPLEX, 0666); if ((ret_val == -1) && (errno != EEXIST)) { perror("Error creating the named pipe"); exit (1); } fd = open(HALF_DUPLEX, O_RDONLY); numread = read(fd, buf, MAX_BUF_SIZE); buf[numread] = '0'; printf("Half Duplex Server : Read From the pipe : %sn", buf); …. printf("Half Duplex Server : Converted String : %sn", buf);

Named pipe: client #define HALF_DUPLEX "/tmp/halfduplex" #define MAX_BUF_SIZE 255 int main(int argc, char *argv[]) { int fd; if (argc != 2) { printf("Usage : %s <string to be sent to the server>n", argv[0]); exit (1); } fd = open(HALF_DUPLEX, O_WRONLY); write(fd, argv[1], strlen(argv[1]));

Process & Child Process Processes do not share data or stack Parent Process Child process Per-process opened file table Per-process opened file table stack stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 fd r/w r 1 w 2 Heap Data Text(Code) Heap Data Text(Code) Operating system Inter-Processes Communication: pipe, shared memory, file, signal, …

Multi-thread programming Threads within a process share data and code (less expensive way to achieve parallelism) Each thread has separate stack space Programs need to ensure data integrity: E.g., Multiple threads cannot write a global variable simultaneously Process Per-process opened file table stack 1 2 pipefd[0] pipefd[1] fd r/w r 1 w 2 pthread_create New stack for thread Heap Data Text(Code)

Hints for final project: analysis How to get started ? Reading the requirement ! Start with one simple cast: For example, focus first upon understanding how to support the –i mode (i.e., read command from standard input)… Identify modules: I will need to be able to run a simple command (w/o pipeline) I will need to split pipeline into two commands I will need to see if there is a trailing & in command … Do not start next stage until you are clear what the program needs to do …

Hints for final project: design How to implement the required functionalities? Do I know how to solve one case ? E.g., interactive mode Try write the pseudocode (a plan for the coding) Is the scripting mode (i.e., read command from file) much different ? Try to generalize your solution as much as possible ! Scripting mode and interactive mode Similarity ? Difference ?

Modular Design Identify and write the headers of functions Function body can be done later … Write main function A mixture of code and comments describing the pseudocode will be fine Verifying your design before start coding Walk-through your code, pay attention to: The information flow: argument passing, value returning, …

Finally, coding/testing/debugging Whenever call a library function, make sure the arguments are passed correctly And check the value returned for possible errors !!! Add assertion statement in the code to verify and isolate errors assert (fp!=NULL); assert (n>0); Add printf () or cout statements to check the value of important variables Is the program doing what I assume it is doing ? If not, when does it diverge from my assumption ?