Figure 3.21 Ordinary pipe in UNIX. /* create the pipe */ if (pipe(fd) == ‐1) { fprintf(stderr,"Pipe failed"); return 1; } /* fork a child process */ pid = fork(); if (pid < 0) { /* error occurred */ fprintf(stderr, "Fork Failed"); return 1; } if (pid > 0) { /* parent process */ /* close the unused end of the pipe */ close(fd[READ_END]); /* write to the pipe */ write(fd[WRITE_END], write_msg, strlen(write_msg)+1); /* close the write end of the pipe */ close(fd[WRITE_END]); } else { /* child process */ /* close the unused end of the pipe */ close(fd[WRITE_END]); /* read from the pipe */ read(fd[READ_END], read_msg, BUFFER_SIZE); printf("read %s",read_msg); /* close the read end of the pipe */ close(fd[READ_END]); } return 0; } Figure 3.22 Figure 3.21, continued. Ordinary pipes on Windows systems are termed anonymous pipes, and they behave similarly to their UNIX counterparts: they are unidirectional and employ parent–child relationships between the communicating processes. In addition, reading and writing to the pipe can be accomplished with the ordinary ReadFile() and WriteFile() functions. The Windows API for creating pipes is the CreatePipe() function, which is passed four parameters. The parameters provide separate handles for (1) reading and (2) writing to the pipe, as well as (3) an instance of the STARTUPINFO structure, which is used to specify that the child process is to inherit the handles of the pipe. Furthermore, (4) the size of the pipe (in bytes) may be specified. Figure 3.23 illustrates a parent process creating an anonymous pipe for communicating with its child. Unlike UNIX systems, in which a child process automatically inherits a pipe created by its parent, Windows requires the programmer to specify which attributes the child process will inherit. This is accomplished by first initializing the SECURITY_ATTRIBUTES structure to allow handles to be inherited and then redirecting the child process's handles for standard input or standard output to the read or write handle of the pipe. Since the child will be reading from the pipe, the parent must redirect the child's standard input to the read handle of the pipe. Furthermore, as the pipes are half duplex, it is necessary to prohibit the child from inheriting the write end of the pipe. The program to create the child process is similar to the program in Figure 3.25. Before reading from the pipe, this program obtains the read handle to the pipe by invoking GetStdHandle(). #include <stdio.h> #include <stdlib.h> #include <windows.h> #define BUFFER_SIZE 25 int main(VOID) { HANDLE ReadHandle, WriteHandle; STARTUPINFO si; PROCESS_INFORMATION pi; char message[BUFFER_SIZE] = “Greetings”; DWORD written; /* Program continues in Figure 3.24 */
An ordinary pipe in UNIX is commonly used between a parent and child process and is unidirectional. Similar anonymous pipes are used in Windows, but the programmer must specifically specify which pipe handle the child process inherits.