Welcome to the world of C Programming! Today, we're diving into a fascinating concept called Pipes. Pipes are a unique feature of the C programming language that allow inter-process communication, enabling you to combine multiple programs into a single pipeline. Let's get started!
Pipes are used to create communication channels between processes. They allow you to connect the standard input and output of processes, enabling data to flow seamlessly between them. This can be extremely useful for performing complex tasks by chaining together multiple programs.
To create a pipe, we use the pipe() function in C. This function creates a pipe by allocating space for two file descriptorsβone for reading (read end) and one for writing (write end).
#include <stdio.h>
#include <unistd.h>
int main() {
int pipefd[2];
// Create pipe
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
// Your code here...
return 0;
}π‘ Pro Tip: Always check for errors when working with system calls, as they can cause unexpected issues.
Once we've created a pipe, we can read from and write to it using the file descriptors it provides. To pass data through the pipe, we can use the write() and read() functions.
// Writing data to pipe
write(pipefd[1], "Hello, World!", 13);
// Reading data from pipe
char buffer[14];
read(pipefd[0], buffer, sizeof(buffer));When you're done using a pipe, it's essential to close both the read and write ends to free up system resources.
close(pipefd[0]);
close(pipefd[1]);To combine processes with pipes, we simply create a pipe, fork a new process, and redirect the I/O of the child process to the pipe.
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pid_t child;
// Create pipe
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
// Fork a child process
child = fork();
// Parent process
if (child > 0) {
// Your code here...
}
// Child process
else {
// Redirect I/O to pipe
dup2(pipefd[0], STDIN_FILENO);
dup2(pipefd[1], STDOUT_FILENO);
// Your code here...
}
// Close the pipe ends
close(pipefd[0]);
close(pipefd[1]);
// Wait for child process to finish
wait(NULL);
return 0;
}Let's create a simple example that takes user input, passes it through a filter, and outputs the result.
// filter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s input output\n", argv[0]);
return 1;
}
// Filter the input
char *filtered = malloc(strlen(argv[1]) + 1);
strcpy(filtered, argv[1]);
for (int i = 0; filtered[i]; ++i) {
if (filtered[i] >= 'A' && filtered[i] <= 'Z') {
filtered[i] += 3;
}
}
// Write the filtered input to stdout
fprintf(stdout, "%s\n", filtered);
return 0;
}// main.c
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pid_t child;
char input[] = "Hello, World!";
char output[256];
// Create pipe
if (pipe(pipefd) == -1) {
perror("pipe");
return 1;
}
// Fork a child process
child = fork();
// Parent process
if (child > 0) {
// Read the filtered output
ssize_t bytes_read = read(pipefd[1], output, sizeof(output));
if (bytes_read <= 0) {
perror("read");
return 1;
}
printf("Filtered output: %s\n", output);
}
// Child process
else {
// Redirect I/O to pipe
dup2(pipefd[0], STDIN_FILENO);
dup2(pipefd[1], STDOUT_FILENO);
// Execute the filter
execl("./filter", "filter", input, NULL);
perror("execl");
}
// Close the pipe ends
close(pipefd[0]);
close(pipefd[1]);
// Wait for child process to finish
wait(NULL);
return 0;
}π Note: The filter program filters the input by converting all uppercase letters to lowercase and adding 3 to each one. Save the filter code in a file named filter.c and compile it with gcc filter.c -o filter.
Which function creates a pipe in C?
That's it for today's lesson on Pipes! Stay tuned as we continue to explore the world of C Programming together. Happy coding! π