#include #include #include #include #include #include // These are already defined in unistd.h // STDIN_FILENO // STDOUT_FILENO // STDERR_FILENO /* Important -- this is for running on linux only! (Not KOS!) It is meant to test different scenarios for pipes in Linux, to see what Linux does. */ int capture(int r, const char* title) { if(r == 0) { errno = 0; } dprintf(STDERR_FILENO, "Return code of %s is %d, errno: %d (%s)\n", title, r, errno, strerror(errno)); return r; } char big_buffer[128 * 1024]; int main() { memset(big_buffer, 0, 128 * 1024); // turn off pipe signal for this example signal(SIGPIPE, SIG_IGN); int result = 0; result = write(STDOUT_FILENO, "Hello!\n",7); capture(result, "write"); char buf[11]; memset(buf, 0, 11); result = read(STDIN_FILENO, buf, 10); capture(result, "read"); result = write(STDOUT_FILENO, buf, 10); capture(result, "write"); // now, test pipes! int fd[2]; result = pipe(fd); capture(result, "pipe"); printf("My pipe returned a read end of %d and a write end of %d\n", fd[0], fd[1]); // lets test the basic case... one reader and one writer printf("Basic case: \n"); char* str = "Hello Pipe! How do you do?"; result = write(fd[1], str, strlen(str)); capture(result, "write"); char buf2[1024]; memset(buf2, 0, 1024); result = read(fd[0],buf2, strlen(str)); capture(result, "read"); printf("Read asks for more data than what is in the pipe\n"); // lets try reading a longer value result = write(fd[1], str, strlen(str)); capture(result, "write"); // it returns immediately! memset(buf2, 0, 1024); result = read(fd[0], buf2, 256); capture(result, "read"); printf("I close reader, what does writer say?\n"); // what happens now if I close the read end and try to write? result = close(fd[0]); capture(result, "close"); result = write(fd[1], str, strlen(str)); capture(result, "write"); result = close(fd[1]); capture(result, "close"); // Let's start over. What happens if I close the writer and try to read? memset(buf2, 0, 1024); result = pipe(fd); capture(result, "pipe"); printf("My pipe returned a read end of %d and a write end of %d\n", fd[0], fd[1]); result = write(fd[1], str, strlen(str)); capture(result, "write"); result = read(fd[0], buf2, 5); capture(result, "read"); result = close(fd[1]); capture(result, "close"); result = read(fd[0], buf2, 30); capture(result, "read"); result = read(fd[0], buf2, 30); capture(result, "read"); result = read(fd[0], buf2, 30); capture(result, "read"); // Let's start over. Let's try dup() result = close(fd[0]); capture(result, "close"); memset(buf2, 0, 1024); result = pipe(fd); capture(result, "pipe"); printf("My pipe returned a read end of %d and a write end of %d\n", fd[0], fd[1]); result = dup(fd[1]); capture(result, "dup"); int new_fd = result; result = write(fd[1], str, strlen(str)); capture(result, "write"); result = write(new_fd, str, strlen(str)); capture(result, "write"); result = read(fd[0], buf2, 1024); capture(result, "read"); // close one writer result = close(fd[1]); capture(result, "close"); // write again. result = write(new_fd, str, strlen(str)); capture(result, "write"); result = read(fd[0], buf2, 1024); capture(result, "read"); // test close result = close(fd[0]); capture(result, "close"); // try another write result = write(new_fd, str, strlen(str)); capture(result, "write"); result = close(new_fd); capture(result, "close"); // end // do big buffer test result = pipe(fd); capture(result, "pipe"); result = fork(); if(result == 0) { result = close(fd[0]); capture(result, "child-close"); for(int i = 0; i < 128 * 1024; i++) { big_buffer[i] = i % 127; } // child result = write(fd[1], big_buffer, 128 * 1024); capture(result, "child-write"); result = close(fd[1]); capture(result, "child-close"); exit(0); } // parent. result = close(fd[1]); capture(result, "parent-close"); result = read(fd[0],big_buffer, 128 * 1024); capture(result, "parent-read"); result = read(fd[0], big_buffer, 128 * 1024); capture(result, "parent-read2"); result = close(fd[0]); capture(result, "parent-close"); printf("Program done\n"); sleep(5); return 0; }