Practical FD Programming
Real-World File Descriptor Scenarios
Pipe Communication
#include <unistd.h>
int pipefd[2];
pipe(pipefd);
pid_t pid = fork();
if (pid == 0) {
// Child process
close(pipefd[1]);
char buffer[100];
read(pipefd[0], buffer, sizeof(buffer));
} else {
// Parent process
close(pipefd[0]);
write(pipefd[1], "Hello Child!", 12);
}
Socket Programming
Creating Network Sockets
#include <sys/socket.h>
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
// Socket configuration and connection
Descriptor Multiplexing
graph TD
A[Multiple File Descriptors] --> B[select()]
B --> C[poll()]
C --> D[epoll()]
Handling Multiple Connections
fd_set read_fds;
int max_fd = 0;
FD_ZERO(&read_fds);
// Add descriptors to set
FD_SET(socket1, &read_fds);
FD_SET(socket2, &read_fds);
select(max_fd + 1, &read_fds, NULL, NULL, NULL);
Temporary File Handling
Creating Temporary Files
#include <stdlib.h>
#include <unistd.h>
char template[] = "/tmp/myfileXXXXXX";
int temp_fd = mkstemp(template);
Technique |
Pros |
Cons |
select() |
Portable |
Limited connections |
poll() |
More flexible |
Performance overhead |
epoll() |
High performance |
Linux-specific |
Advanced I/O Patterns
Non-Blocking I/O
#include <fcntl.h>
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
Error Handling Strategies
ssize_t bytes = read(fd, buffer, size);
if (bytes == -1) {
switch(errno) {
case EAGAIN:
// Resource temporarily unavailable
break;
case EBADF:
// Invalid file descriptor
break;
}
}
LabEx Practical Challenge
Implement a multi-client chat server using file descriptor techniques in the LabEx Linux programming environment.
Best Practices
- Always check return values
- Close unused file descriptors
- Use appropriate I/O multiplexing techniques
- Manage resources efficiently