CECS-326: Operating Systems Lab 8 Pipes


5/5 - (2 votes)

CECS-326: Operating Systems
Lab 8
1. Pipe: There are two types: unnamed and named.
Unnamed: int pipe (int filedes[2]); success: 0, failure: -1, sets errno. If successful, pipe returns two
integer file descriptors, filedes[0] and filedes[1], that reference two data streams. In full duplex setting
(current UNIX version), if a process writes to filedes[0], then filedes[1] is used for reading, and vice versa.
Named: int mkfifo (const char *path, mode_t mode); success: 0, failure: -1, sets errno. mkfifo
creates the FIFO file referenced by path; mode: File mode bits: S_IRUSR read permission, owner .
S_IWUSR write permission, owner
int mknod (const char *path, mode_t mode, dev_t dev); success: 0, failure: -1, sets errno.
mknod creates the file referenced by path; mode determines the type of file (FIFO, character or block
special, directory or plain); dev is used only when a character or block special file is specified. For nonprivileged user, mknod can only be used to generate a FIFO.
2. Open a file: int open(const char *path, int oflag, … );
The open() function establishes the connection between a file and a file descriptor. It creates an open file
description that refers to a file and a file descriptor that refers to that open file description. The file
descriptor is used by other I/O functions to refer to that file. The path argument points to a pathname
naming the file. Values for oflag are constructed by a bitwise-inclusive-OR of flags from the following list,
defined in <fcntl.h>. Applications must specify exactly one of the first three values (file access modes)
below in the value of oflag: O_RDONLY: Open for reading only. O_WRONLY: Open for writing only.
O_RDWR : Open for reading and writing. The result is undefined if this flag is applied to a FIFO. Any
combination of the following may be used:
O_NONBLOCK When opening a FIFO with O_RDONLY or O_WRONLY set: If O_NONBLOCK is set:
An open() for reading only will return without delay. An open() for writing only will return an error if no
process currently has the file open for reading. If O_NONBLOCK is clear: An open() for reading only will
block the calling thread until a thread opens the file for writing. An open() for writing only will block the
calling thread until a thread opens the file for reading.
3. Read: ssize_t read (int filedes, void *buf, size_t nbyte); success: number of bytes read, failure: –
1, sets errno. All reads are initiated from current position. Read nbyte bytes from the open file associated
with the file descriptor filedes into the buffer referenced by buf.
4. Write: ssize_t write (int filedes, const void *buf, size_t nbyte); success: number of bytes written,
failure: -1, sets errno. Write nbyte bytes from the buffer referenced by buf using the file descriptor
specified by filedes.
5. Errors: EEXIST (file already exists); EINTR (interrupted system call)
A. Study the following two programs, pipe.c and pipe1.c.
/* Unnamed pipe pipe.c */
/* Usage: pipe message_to_be_written. Parent write a message to child */
Use include files: <stdio.h>, <stdlib.h>, <limits.h>, <unistd.h>, <string.h>
void main(int argc, char *argv[])
int f_des[2]; static char message[BUFSIZ]; char buffer[MAX_CANON]; char *c; int i,k, n; pid_t
if (argc !=2) { printf (“\n Usage: %s message\n”, *argv); exit(1);}
/* generate pipe */
if (pipe(f_des) == -1) { perror (“Pipe”); exit(2); }
switch (fork()) {
case -1: perror (“Fork”); exit(3);
case 0: /* In the child */
close(f_des[1]); if (read(f_des[0], message, BUFSIZ) != -1) { printf (“Message received by child:
*%s*\n”, message); fflush(stdout); }
else { perror (“Read”); exit(4);} break;
default: /* In the parent */
if (write(f_des[1], argv[1], strlen(argv[1])) != -1){
printf (“Message sent by parent: [%s]\n”, argv[1]); fflush(stdout); }
else { perror (“Write”); exit(5); }

/* Named pipe pipe1.c */
/* Usage: pipe1 pipename. Child writes a message to parent */
Use the following include files: <stdio.h>, <stdlib.h>, <limits.h>, <unistd.h>, <string.h>, <sys/types.h>,
<sys/stat.h>, <sys/wait.h>, <fcntl.h>, <limits.h>, <errno.h>
# define BUFSIZE 256
void main(int argc, char *argv[])
mode_t fifo_mode = S_IRUSR | S_IWUSR; int fd, status, child; char buf[BUFSIZE]; unsigned strsize;
if (argc !=2) { printf (“\n Usage: %s pipename\n”, argv[0]); exit(1); }
/* generate a named pipe with r/w for user */
if ((mkfifo(argv[1],fifo_mode) == -1) && (errno != EEXIST)) { perror (“Pipe”); exit(1); }
if (( child = fork()) == -1) { perror (“Fork”); exit(1); }
else if (child == 0){ printf (“\n Child %ld is about to open FIFO %s\n”, (long)getpid(), argv[1]);
if ((fd = open(argv[1], O_WRONLY)) == -1) {perror(“Child cannot open FIFO”); exit(1);}
/* In the child */
sprintf (buf, “This was written by child %ld\n”, (long)getpid()); strsize = strlen(buf) + 1;
if (write(fd, buf, strsize) != strsize) { printf(“Child write to FIFO failed\n”); exit(1); }
printf (“Child %ld is done\n”, (long)getpid());
} else { /* parent does a read */
printf (“Parent %ld is about to open FIFO %s\n”, (long) getpid(), argv[1]);
if ((fd = open(argv[1], O_RDONLY | O_NONBLOCK)) == -1) { perror(“Parent cannot open FIFO”);
exit(1); }
printf (“Parent is about to read\n”, (long)getpid());
while ((wait(&status) == -1) && (errno == EINTR));
if (read(fd, buf, BUFSIZE) <=0) { perror(“Parent read from FIFO failed\n”);exit(1); }
printf (“Parent %ld received: %s\n”, (long)getpid(), buf);
B. Rewrite pipe to reverse roles of the sender and receiver, i.e., change to child sending message to parent.
In pipe, does the order of f_des[0] and f_des[1} make any difference?

PlaceholderCECS-326: Operating Systems Lab 8 Pipes
Open chat
Need help?
Can we help?