System Calls: pipes - PowerPoint PPT Presentation

1 / 25
About This Presentation
Title:

System Calls: pipes

Description:

System Calls: pipes. CSRU3130. Ellen Zhang. 1. CSRU 3130: Unix System ... printf('After forking, child: j = %d, K = %dn', j, K); main() { int i; ... defunct ... – PowerPoint PPT presentation

Number of Views:173
Avg rating:3.0/5.0
Slides: 26
Provided by: stormCis
Category:
Tags: calls | defunct | pipes | system

less

Transcript and Presenter's Notes

Title: System Calls: pipes


1
System Calls pipes
  • CSRU3130
  • Ellen Zhang

2
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 gt 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)

3
  • main()
  • int i int seekp int fd
  • char s1
  • char s21000
  • fd open("tmpfile", O_WRONLY O_TRUNC
    O_CREAT, 0666)
  • s1 "Before forking\n"
  • write(fd, s1, strlen(s1))
  • i fork()
  • if (i gt 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)

zhang_at_storm Demo ./a.out zhang_at_storm Demo
more tmpfile Before forking Child After forking
Seek pointer 15 Parent After forking Seek
pointer 55
4
Zombie/defunct Process
  • When child process terminates, it remains in
    system until parent terminates or parent call
    wait()
  • A parent normally must wait() for child processes
    to exit. This allows all remnants of the child to
    vanish.
  • Shell fork a process to execute a command, wait
    until it ends, and then continue execute next
    command
  • For command ending with ?

5
Pipe
  • Allow parent-child processes to communicate with
    each other
  • Make pipeline in shell command script possible
  • int pipe(int fd2)
  • you pass it an array of two integers. It fills in
    that array with two file descriptors, fd0,
    fd1
  • Anything that is written on fd1 can be read
    from fd0.
  • Pipes are treated as files
  • You can call read(), write(), close() on pipes
  • fd0 is for reading, fd1 is for writing

6
Simple example
  • include ltstdio.hgt
  • main()
  • int pipefd2
  • int i
  • char s1000
  • char s2
  • if (pipe(pipefd) lt 0)
  • perror("pipe")
  • exit(1)
  • s2 Hello World!"
  • write(pipefd1, s2, strlen(s2))
  • i read(pipefd0, s, 1000)
  • si '\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.

7
Visualize pipes
program
File descriptors
Code, Globals stacks
0 1 2 pipefd0 pipefd1
Operating system
buffer
Hello World!
heap
8
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

9
Pipe inter-process communication
else //child process i 0 line 1
while(read(pipefd0, si, 1) 1)
if (si '\n') si '\0'
printf("6d s\n", line, s)
line i 0 else
i // end of while loop // end
of else //end of main()
  • main()
  • int pipefd2
  • int pid, i, line
  • char s1000
  • if (pipe(pipefd) lt 0)
  • perror("pipe")
  • exit(1)
  • pid fork()
  • if (pid gt 0)
  • // parent process
  • while(fgets(s, 1000, stdin) ! NULL)
  • write(pipefd1, s, strlen(s))
  • close(pipefd1)

10
Visualize pipes
child
Parent process
File descriptors
Code, Globals stacks
Code, Globals Stacks
File descriptors
0 ?-------- 1 --------? 2 -------? pipefd0? pipe
fd1?
------? 0 ? ------1 ? ------ 2 ?
pipefd0 ?pipefd1
Operating system
heap
heap
11
Experiment with the program
  • Lets try it out (testpipe)
  • ctrl-d to finish standard input
  • Why the child process lingers ?
  • OS does not know no one is writing to pipe

child
Parent process
File descriptors
Code, Globals stacks
Code, Globals Stacks
File descriptors
0 ?-------- 1 --------? 2 -------? pipefd0? pipe
fd1?
------? 0 ? ------1 ? ------ 2 ?
pipefd0 ?pipefd1
Operating system
heap
heap
12
  • main()
  • int pipefd2
  • int pid int i, line
  • char s1000
  • if (pipe(pipefd) lt 0)
  • perror("pipe")
  • exit(1)
  • pid fork()
  • if (pid gt 0)
  • close(1)
  • close(pipefd0)
  • while(fgets(s, 1000, stdin) ! NULL)
  • write(pipefd1, s, strlen(s))
  • close(pipefd1)

else close(0) close(pipefd1) i 0
line 1 while(read(pipefd0, si, 1) 1)
if (si '\n') si '\0'
printf("6d s\n", line, s) line i
0 else i
//end of while //end of else
//end of main
13
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 the signal isn't handled, program exits
    silently
  • Example If you execute
  • UNIXgt cat exec1.c head -5 tail -1
  • and you kill the middle process (the head one),
  • the other two will exit automatically

14
Signals
  • 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.
  • 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)

15
Register signal handler
  • include lt signal.h gt
  • void cntl_c_handler(int dummy)
  • printf("You just typed cntl-c\n")
  • signal(SIGINT, cntl_c_handler)
  • main()
  • int i, j
  • signal(SIGINT, cntl_c_handler)
  • for (j 0 j lt 40 j)
  • for (i 0 i lt 1000000 i)

16
Signal as IPC
  • 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()
17
dup, dup2
  • int dup(int oldfd)
  • int dup2(int oldfd, int newfd)  
  • dup and dup2 create a copy of file descriptor
    oldfd.
  • dup uses lowest-numbered unused descriptor for
    new descriptor
  • dup2 makes newfd be copy of oldfd, closing newfd
    first if necessary.  
  • Old and new descriptors may be used
    interchangeably, and they share locks, file
    position pointers and flags.

18
Example implement pipeline
  • if (pipe(pipefd) lt 0)
  • perror("pipe")
  • exit(1)
  • pid fork()
  • if (pid0)
  • retdup2 (pipefd1,1)
  • close (pipefd1)
  • if (ret-1)
  • fprintf (stderr,"first child
    cannot dup\n")
  • exit(1)
  • close(pipefd0)
  • execlp("ls","ls",0)
  • fprintf (stderr,failed to execue ls)
  • //end of else

19
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

20
Using named pipe
  • Create a named pipe
  • mkfifo myPipe
  • ls l will show myPipe as
  • prw-r--r-- 1 zhang staff 0 2008-04-25
    0930 myPipe
  • In one terminal, type
  • ls -l gt myPipe
  • in another type
  • cat lt 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

21
Named pipes server
  • define HALF_DUPLEX "/tmp/halfduplex"
  • define MAX_BUF_SIZEgt 255
  • int main(int argc, char argv)
  • int fd, ret_val, count, numread
  • char bufMAX_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)
  • bufnumread '0'
  • printf("Half Duplex Server Read From the pipe
    sn", buf)
  • .
  • printf("Half Duplex Server Converted String
    sn", buf)

22
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 ltstring to be sent to the
    servergtn", argv0)
  • exit (1)
  • fd open(HALF_DUPLEX, O_WRONLY)
  • write(fd, argv1, strlen(argv1))

23
Some other topics not covered
  • Thread programming
  • Processes do not share data or stack
  • Threads within a process share data and code,
    each have separate stack space (programs need to
    ensure data integrity)
  • Thread is a lighter-weight way of achieving
    parallism

Parent process
Code, Globals Stacks
pthread_creat()
New thread stack
heap
24
Some quizzes
  • How would implement the functions of for a
    shell ?
  • i.e., run the command in background ?

25
Next and Last Class
  • A lab class where each of you are asked to show
    me your project
Write a Comment
User Comments (0)
About PowerShow.com