Lecture 17 Log into Linux. Copy two subdirectories in - - PowerPoint PPT Presentation

lecture 17
SMART_READER_LITE
LIVE PREVIEW

Lecture 17 Log into Linux. Copy two subdirectories in - - PowerPoint PPT Presentation

Lecture 17 Log into Linux. Copy two subdirectories in /home/hwang/cs375/lecture17/ $ cp -r /home/hwang/cs375/lecture17/* . Both subdirectories have makefiles that will make all the programs. The " unnamed " subdirectory has


slide-1
SLIDE 1

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 1

Lecture 17

 Log into Linux. Copy two subdirectories in

/home/hwang/cs375/lecture17/

$ cp -r /home/hwang/cs375/lecture17/* .

 Both subdirectories have makefiles that will

make all the programs. The "unnamed" subdirectory has programs using pipe( ), while the "named" subdirectory has programs using FIFOs (named pipes).

 Reminder: Project 5 due on Thursday.  Questions?

slide-2
SLIDE 2

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 2

Outline

 UNIX IPC Methods  An Introduction to (unnamed) Pipes  IPC via Pipes  Named Pipes (FIFOs)

slide-3
SLIDE 3

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 3

UNIX IPC

 UNIX allows several methods of interprocess

communication (IPC). Here are ten:

 shared file pointers: One process positions a file

pointer (using lseek( )); a second process reads the pointer position (also lseek( )). The position is the (integer) data to be communicated. (This is rarely

  • used. The method is restricted to related processes.

Synchronization also is required.)

 signals: Signals can be used for notifications, but

cannot be used to transfer data.

slide-4
SLIDE 4

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 4

UNIX IPC

 process tracing: This is commonly used by

debuggers, but is too complicated for normal IPC.

 files: Passing data via a file is the most common form

  • f IPC, but difficult to use with concurrent processes.

Files may get huge when processes run for long periods.

 pipes (unnamed): They solve the synchronization

problem that exists with files. Processes must be related to use pipes. Reads and writes may not be atomic on all systems (so they cannot be used with multiple readers or writers); pipes also are slow.

slide-5
SLIDE 5

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 5

UNIX IPC

 FIFOs (named pipes): They solve all pipe problems

except that they may still be too slow.

 semaphores: They are used for process

synchronization or exclusive access to resources.

 message queues: Allow small message packets to be

transferred synchronously between processes.

 shared memory: The fastest method of IPC.

Semaphores or messages may be used for synchronization.

 sockets: Used for network communication between

processes on different (or the same) hosts.

slide-6
SLIDE 6

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 6

Introduction to Pipes

 We will discuss IPC via unnamed pipes first.

You are familiar with pipes as a shell facility:

$ who | sort | pr -l 24

 Here three processes are connected via two

  • pipes. The standard output of the process on

the left of the | is connected to the standard input of the process on the right.

 Pipes use the standard UNIX read/write calls

for passing data between processes.

slide-7
SLIDE 7

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 7

The popen( ) Function

 The popen( ) function is built on top of the

lower level pipe( ) routine. It receives a command string and an open mode, and returns a stdio FILE * stream (so stdio routines must be used):

FILE *rf = popen("ls -l", "r"); while(fgets(buf,sizeof(buf),rf)!=NULL) { /* process lines */ }

slide-8
SLIDE 8

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 8

The pipe( ) Routine

 popen( ) invokes a shell to execute the

command and is expensive in terms of

  • resources. pipe( ) does not require that a shell

be started and also gives us more control over the reading and writing of data.

 pipe( ) returns two file descriptors in an array.

We read from one and write to the other.

 See pipe_xmpl1.cpp pdf[1] pdf[0]

slide-9
SLIDE 9

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 9

The pipe( ) Routine

int pfd[2]; if(pipe(pfd) == -1) error(strerror(errno)); // read from pfd[0]/write to pfd[1] string msg = "Hello world!"; // we can write a short message to // the pipe and not worry about the // write blocking and process deadlock write(pfd[1], msg.c_str(), msg.length()); count = read(pfd[0], buffer, sizeof(buffer)); buffer[count] = '\0'; cout << buffer << endl;

slide-10
SLIDE 10

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 10

Pipe Characteristics

 Several of the system routines act slightly

differently when operating on a file descriptor associated with a pipe instead of a file descriptor associated with a file.

 write( ) will normally block on a full pipe. Pipes

are at least 4096 bytes on all UNIX systems. (On Linux >2.6.11 the capacity is 65536 bytes.) There are no partial writes. To get an end-of- file on a read, you must close the write end of the pipe. (pipe_xmpl2.cpp demonstrates a blocked write.)

slide-11
SLIDE 11

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 11

Pipe Characteristics

 read( ) will block until at least one byte is

present unless the O_NDELAY flag is set (see fcntl( )) or the writing descriptor is closed. The byte count argument to read( ) will not necessarily be satisfied.

 The lseek( ) routine can not be used with pipes.

You have to read the pipe to access the data and once data is read there is no way to put it back.

slide-12
SLIDE 12

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 12

IPC Via a Pipe

 pipe( ) is used for IPC between related

  • processes. (It is not possible for an unrelated

process to get access to a system file descriptor owned by another process, but children inherit all file descriptors from their parents.)

 See pipe_xmpl3.cpp

slide-13
SLIDE 13

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 13

IPC Via a Pipe

 A process normally uses only one end of the

  • pipe. Always close the end you are not using!

 Pipes are unidirectional; for bidirectional

process communication you need two pipes.

slide-14
SLIDE 14

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 14

Pipes to exec( )'d Programs

 We rely on child processes inheriting the pipe

file descriptors to allow IPC via pipes.

pipe(pfd); // both open to both processes if (fork() == 0) { // child close(pfd[0]); // close read end write(pfd[1], msg, bufsize); exit(0); } // parent close(pfd[1]); // close write end n = read(pfd[0],msg, bufsize);

slide-15
SLIDE 15

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 15

Pipes to exec( )'d Programs

 Normally we exec a program in the child.  File descriptors stay open across an exec

(unless fcntl( ) is used to set the close-on-exec flag), but the exec'd process will not have access to the array containing the file descriptor numbers.

 One method used to get around this problem is

to pass the descriptors as arguments to the

  • program. (See wtr_xmpl1.cpp and

rdr_xmpl1.cpp)

slide-16
SLIDE 16

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 16

dup( ) and dup2( ) Routines

 Most programs are designed to read from

standard input and write to standard output. How do communicate with such a program via a pipe? We use dup( ) or dup2( ).

 The dup(oldfd) routine duplicates an existing

file descriptor. The new file descriptor returned by dup( ) is guaranteed to be the lowest numbered available. dup2(oldfd, newfd) duplicates oldfd over newfd, closing newfd first, if necessary.

slide-17
SLIDE 17

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 17

dup( ) and dup2( ) Routines

 See wtr_xmpl2.cpp and rdr_xmpl2.cpp

pipe(pfd); if(fork() == 0) { close(0); // so 0 is available dup(pfd[0]); // will dup over 0 close(pfd[0]); close(pfd[1]); execl("rdstdin", "rdstdin", (char *)0); cerr << "exec failure" << endl; exit(0); } close(pfd[0]); // close read end of pipe n = write(pfd[1], msg, bufsize); close(pfd[1]);

slide-18
SLIDE 18

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 18

dup( ) and dup2( ) Routines

 See wtr_xmpl3.cpp for a dup2( ) example.

pipe(pfd); if(fork() == 0) { dup2(pfd[0], 0); // will dup over 0 close(pfd[0]); close(pfd[1]); execl("rdstdin", "rdstdin", (char *)0); cerr << "exec failure" << endl; exit(0); } close(pfd[0]); // close read end of pipe n = write(pfd[1], msg, bufsize); close(pfd[1]);

slide-19
SLIDE 19

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 19

Named Pipes

 Named pipes (FIFOs) are special types of

“files” that can be used for communication between unrelated processes. (They are not real files and take up no disk space.)

 A FIFO combines features of files and pipes. It

has a name and may be opened for reading or writing by any process with appropriate

  • permissions. Once opened, a FIFO acts more

like a pipe. Data, once read, cannot be read again, nor does lseek( ) work.

slide-20
SLIDE 20

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 20

Named Pipes

 FIFOs can be created from the command line

using the mkfifo command (or mknod):

$ mkfifo myfifo $ ls -l myfifo prw-rw-r-- 1 hwang hwang 0 Oct 25 16:40 myfifo

 The FIFO can be used to pass data between

programs:

$ cat /etc/passwd > myfifo & $ cat myfifo $ gnuplot -persist < myfifo & $ echo "set nokey; plot sin(x)" > myfifo

slide-21
SLIDE 21

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 21

The mkfifo( ) Routine

 From within a program, a FIFO can be created

using mkfifo( ) (or mknod( )):

mkfifo("/tmp/myfifo", 0777);

 The second argument is the desired FIFO

  • permissions. mkfifo( ) returns -1 on error.

 The FIFO will exist until deleted (with rm at the

command line or by calling the unlink( ) routine from within a program).

slide-22
SLIDE 22

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 22

FIFO Characteristics

 An open( ) for read-only on a FIFO will block

until another process opens the FIFO for

  • writing. An open( ) for write-only will block until

a reader opens the FIFO. This allows synchronization before data transmission. (The

  • pen( ) routine will not block if the

O_NONBLOCK flag is used in the open( ).)

 read( ) will block if no data is present. write( )

will block on a full FIFO. (But not if O_NONBLOCK is used.)

slide-23
SLIDE 23

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 23

FIFO Characteristics

 Writes of less than PIPE_BUF (65536 on Linux

>2.6.11) are guaranteed to be atomic, i.e. the write can not be interrupted. We can have multiple writers to a FIFO if the messages are smaller in size than PIPE_BUF, and the messages will not be intermixed.

 FIFOs are often used for client-server

communication between multiple clients and a single server.

 See fifo_wtr.cpp, fifo_rdr.cpp, server.cpp,

and client.cpp

slide-24
SLIDE 24

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 24

Example Writer Code

// Error checking omitted for brevity const char *FIFO_NAME = "/tmp/db_server"; // Check for existence if(access(FIFO_NAME, F_OK) == -1) { // does not exist, create it mkfifo(FIFO_NAME, 0777); } // block on open until reader opens too wfd = open(FIFO_NAME, O_WRONLY); count = write(wfd, buffer, length); close(wfd); unlink(FIFO_NAME);

slide-25
SLIDE 25

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 25

Example Reader Code

// Error checking omitted for brevity // We wait on server to create fifo while(true) { rfd = open(FIFO_NAME, O_RDONLY); if(rfd == -1) { if(errno == ENOENT) { // does not exist, wait then try again sleep(1); continue; } else { exit(1); } } } // end while count = read(rfd, buffer, length);

slide-26
SLIDE 26

Tuesday, October 26 CS 375 UNIX System Programming - Lecture 17 26

In-class Exercise

 Copy pipe_xmpl3.cpp. Comment out the line

in the child that closes the write end of the pipe. Compile and run the program. Why doesn't the child exit? (Be sure to kill the child manually using the kill command.)

 Copy and modify pipe_xmpl3.cpp so that the

parent reads /etc/passwd and passes all the data to the child via the pipe. The child should read from the pipe and write the data to standard output.